From 7063b2599fa0197ddfa8273ad188ed0e1653e751 Mon Sep 17 00:00:00 2001 From: lavolp3 Date: Tue, 4 Feb 2020 12:46:42 +0100 Subject: [PATCH 01/31] included call for matches and scorers. NOT FINAL --- MMM-soccer.js | 50 +- node_helper.js | 103 +- package-lock.json | 3443 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 3538 insertions(+), 58 deletions(-) create mode 100644 package-lock.json diff --git a/MMM-soccer.js b/MMM-soccer.js index 87aa5b2..c3f7bb0 100644 --- a/MMM-soccer.js +++ b/MMM-soccer.js @@ -7,6 +7,8 @@ * @see https://github.com/fewieden/MMM-soccer */ +/* jshint esversion: 6 */ + /* global Module Log */ /** @@ -45,7 +47,7 @@ Module.register('MMM-soccer', { max_teams: false, logos: false, leagues: { - GERMANY: 'BL1', + GERMANY: 'DFB', FRANCE: 'FL1', ENGLAND: 'PL', SPAIN: 'PD', @@ -97,7 +99,7 @@ Module.register('MMM-soccer', { * @description Adds nunjuck filters and requests for league data. * @override */ - start() { + start: function() { Log.info(`Starting module: ${this.name}`); this.addFilters(); this.currentLeague = this.config.leagues[this.config.show]; @@ -111,7 +113,7 @@ Module.register('MMM-soccer', { * @function start * @description Sends request to the node_helper to fetch data for the current selected league. */ - getData() { + getData: function() { this.sendSocketNotification('GET_DATA', { league: this.currentLeague, api_key: this.config.api_key }); }, @@ -123,7 +125,7 @@ Module.register('MMM-soccer', { * @param {string} notification - Notification name * @param {*} payload - Detailed payload of the notification. */ - socketNotificationReceived(notification, payload) { + socketNotificationReceived: function(notification, payload) { if (notification === 'DATA') { this.standing = payload.standings[0].table; this.season = payload.season; @@ -142,39 +144,24 @@ Module.register('MMM-soccer', { * @param {*} payload - Detailed payload of the notification. * @param {Object} sender - Module that sent the notification or undefined for MagicMirror² core. */ - notificationReceived(notification, payload, sender) { + notificationReceived: function(notification, payload, sender) { if (notification === 'ALL_MODULES_STARTED') { const voice = Object.assign({}, this.voice); voice.sentences.push(Object.keys(this.config.leagues).join(' ')); this.sendNotification('REGISTER_VOICE_MODULE', voice); } else if (notification === 'VOICE_SOCCER' && sender.name === 'MMM-voice') { this.checkCommands(payload); - } else if (notification === 'VOICE_MODE_CHANGED' && sender.name === 'MMM-voice' - && payload.old === this.voice.mode) { + } else if (notification === 'VOICE_MODE_CHANGED' && sender.name === 'MMM-voice' && payload.old === this.voice.mode) { this.closeAllModals(); this.updateDom(300); } }, - /** - * @function getStyles - * @description Style dependencies for this module. - * @override - * - * @returns {string[]} List of the style dependency filepaths. - */ - getStyles() { + getStyles: function() { return ['font-awesome.css', 'MMM-soccer.css']; }, - /** - * @function getTranslations - * @description Translations for this module. - * @override - * - * @returns {Object.} Available translations for this module (key: language code, value: filepath). - */ - getTranslations() { + getTranslations: function() { return { en: 'translations/en.json', de: 'translations/de.json', @@ -183,14 +170,7 @@ Module.register('MMM-soccer', { }; }, - /** - * @function getTemplate - * @description Nunjuck template. - * @override - * - * @returns {string} Path to nunjuck template. - */ - getTemplate() { + getTemplate: function() { return 'MMM-soccer.njk'; }, @@ -201,7 +181,7 @@ Module.register('MMM-soccer', { * * @returns {string} Data for the nunjuck template. */ - getTemplateData() { + getTemplateData: function() { return { boundaries: this.calculateTeamDisplayBoundaries(), competitionName: this.competition.name || this.name, @@ -219,7 +199,7 @@ Module.register('MMM-soccer', { * @function handleModals * @description Hide/show modules based on voice commands. */ - handleModals(data, modal, open, close) { + handleModals: function(data, modal, open, close) { if (close.test(data) || (this.modals[modal] && !open.test(data))) { this.closeAllModals(); } else if (open.test(data) || (!this.modals[modal] && !close.test(data))) { @@ -243,7 +223,7 @@ Module.register('MMM-soccer', { * @function closeAllModals * @description Close all modals of the module. */ - closeAllModals() { + closeAllModals: function() { const modals = Object.keys(this.modals); modals.forEach((modal) => { this.modals[modal] = false; }); }, @@ -254,7 +234,7 @@ Module.register('MMM-soccer', { * * @returns {boolean} Flag if there is an active modal. */ - isModalActive() { + isModalActive: function() { const modals = Object.keys(this.modals); return modals.some(modal => this.modals[modal] === true); }, diff --git a/node_helper.js b/node_helper.js index 32dc1c2..2e33996 100644 --- a/node_helper.js +++ b/node_helper.js @@ -9,17 +9,9 @@ /* eslint-env node */ /* eslint-disable no-console */ +/* jshint esversion: 6 */ -/** - * @external request - * @see https://www.npmjs.com/package/request - */ const request = require('request'); - -/** - * @external node_helper - * @see https://github.com/MichMich/MagicMirror/blob/master/modules/node_modules/node_helper/index.js - */ const NodeHelper = require('node_helper'); /** @@ -31,11 +23,6 @@ const NodeHelper = require('node_helper'); */ module.exports = NodeHelper.create({ - /** - * @function start - * @description Logs a start message to the console. - * @override - */ start() { console.log(`Starting module: ${this.name}`); }, @@ -50,31 +37,101 @@ module.exports = NodeHelper.create({ */ socketNotificationReceived(notification, payload) { if (notification === 'GET_DATA') { - const options = { - url: `http://api.football-data.org/v2/competitions/${payload.league}/standings` + this.options = { + standings: { + url: `http://api.football-data.org/v2/competitions/${payload.league}/standings`, + headers: payload.api_key ? { 'X-Auth-Token': payload.api_key } : {} + }, + matches: { + url: `http://api.football-data.org/v2/competitions/${payload.league}/matches`, + headers: payload.api_key ? { 'X-Auth-Token': payload.api_key } : {} + }, + detailedMatches: { + url: `http://api.football-data.org/v2/competitions/${payload.league}/match/271584`, + headers: payload.api_key ? { 'X-Auth-Token': payload.api_key } : {} + }, + scorers: { + url: `http://api.football-data.org/v2/competitions/${payload.league}/scorers`, + headers: payload.api_key ? { 'X-Auth-Token': payload.api_key } : {} + } }; - if (payload.api_key) { - options.headers = { 'X-Auth-Token': payload.api_key }; - } - this.getData(options); + this.getTable(this.options.standings); } }, /** - * @function getData + * @function getTable * @description Request data from the supplied URL and broadcast it to the MagicMirror module if it's received. * * @param {Object} options - request optionsthe notification. */ - getData(options) { + getTable(options) { console.log(`Get league table for url ${options.url}`); request(options, (error, response, body) => { if (response.statusCode === 200) { - this.sendSocketNotification('DATA', JSON.parse(body)); + var tableData = JSON.parse(body); + this.sendSocketNotification('DATA', tableData); + console.log(tableData); + var matchDay = tableData.season.currentMatchday; + console.log(matchDay); + + this.getStandings(this.options.matches, matchDay); + this.getMatches(this.options.detailedMatches, matchDay); + this.getScorers(this.options.scorers); + + } else { this.sendSocketNotification('DATA'); console.log(`Error getting league table ${response.statusCode}`); } }); + }, + + getStandings(options, matchDay) { + console.log(`Get league standings for url ${options.url}`); + request(options, (error, response, body) => { + if (response.statusCode === 200) { + var standingsData = JSON.parse(body); + this.sendSocketNotification('STANDINGS', standingsData); + matchDayStandings = standingsData.matches.filter(match => { + return (match.matchday === matchDay); + }); + console.log(JSON.stringify(matchDayStandings)); + } else { + this.sendSocketNotification('STANDINGS'); + console.log(`Error getting league match standings ${response.statusCode}`); + } + }); + }, + + + getMatches(options, matchDay) { + console.log(`Get league matches for url ${options.url}`); + request(options, (error, response, body) => { + if (response.statusCode === 200) { + var matchData = JSON.parse(body); + this.sendSocketNotification('MATCHES', matchData); + /*matchDayStandings = standingsData.matches.filter(match => { + return (match.matchday === matchDay); + });*/ + console.log(JSON.stringify(matchData)); + } else { + console.log(`Error getting match details ${response.statusCode}`); + } + }); + }, + + getScorers(options) { + console.log(`Get scorers for url ${options.url}`); + request(options, (error, response, body) => { + if (response.statusCode === 200) { + var data = JSON.parse(body); + this.sendSocketNotification('SCORERS', data); + console.log(JSON.stringify(data)); + } else { + console.log(`Error getting scorers ${response.statusCode}`); + } + }); } + }); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..81bd2ef --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3443 @@ +{ + "name": "mmm-soccer", + "version": "1.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "JSONStream": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.8.4.tgz", + "integrity": "sha1-kWV9/m/4V0gwZhMrRhi2Lo9Ih70=", + "dev": true, + "requires": { + "jsonparse": "0.0.5", + "through": ">=2.2.7 <3" + } + }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "dev": true + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-includes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", + "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + } + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "autoprefixer": { + "version": "6.7.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", + "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", + "dev": true, + "requires": { + "browserslist": "^1.7.6", + "caniuse-db": "^1.0.30000634", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^5.2.16", + "postcss-value-parser": "^3.2.3" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "browserslist": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "dev": true, + "requires": { + "caniuse-db": "^1.0.30000639", + "electron-to-chromium": "^1.2.7" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "^0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "caniuse-db": { + "version": "1.0.30001024", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30001024.tgz", + "integrity": "sha512-dmwZ7u58E68UCexHf92QERFL8kwwCv0TVS1LCNluhZo+565AXU5uNtnPF+J5E2MExwWJeNnhTD63BH8ncMV09g==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "^1.0.1" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "clone-regexp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-1.0.1.tgz", + "integrity": "sha512-Fcij9IwRW27XedRIJnSOEupS7RVcXtObJXbcUOX93UCLqqOdRpkvzKywOOSizmEK/Is3S/RHX9dLdfo6R1Q1mw==", + "dev": true, + "requires": { + "is-regexp": "^1.0.0", + "is-supported-regexp-flag": "^1.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-diff": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/color-diff/-/color-diff-0.1.7.tgz", + "integrity": "sha1-bbeM2UgqjkWdQIIer0tQMoPcuOI=", + "dev": true + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colorguard": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colorguard/-/colorguard-1.2.1.tgz", + "integrity": "sha512-qYVKTg626qpDg4/eBnPXidEPXn5+krbYqHVfyyEFBWV5z3IF4p44HKY/eE2t1ohlcrlIkDgHmFJMfQ8qMLnSFw==", + "dev": true, + "requires": { + "chalk": "^1.1.1", + "color-diff": "^0.1.3", + "log-symbols": "^1.0.2", + "object-assign": "^4.0.1", + "pipetteur": "^2.0.0", + "plur": "^2.0.0", + "postcss": "^5.0.4", + "postcss-reporter": "^1.2.1", + "text-table": "^0.2.0", + "yargs": "^1.2.6" + }, + "dependencies": { + "postcss-reporter": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-1.4.1.tgz", + "integrity": "sha1-wTbwpbFhkV83ndN2XGEHX357mvI=", + "dev": true, + "requires": { + "chalk": "^1.0.0", + "lodash": "^4.1.0", + "log-symbols": "^1.0.2", + "postcss": "^5.0.0" + } + } + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cosmiconfig": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.2.2.tgz", + "integrity": "sha512-GiNXLwAFPYHy25XmTPpafYvn3CLAkJ8FLsscq78MQd1Kh0OU6Yzhn4eV2MVF4G9WEQZoWEGltatdR+ntGPMl5A==", + "dev": true, + "requires": { + "is-directory": "^0.3.1", + "js-yaml": "^3.4.3", + "minimist": "^1.2.0", + "object-assign": "^4.1.0", + "os-homedir": "^1.0.1", + "parse-json": "^2.2.0", + "require-from-string": "^1.1.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "css-color-names": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.3.tgz", + "integrity": "sha1-3gzvFvTYqoIioyDVttfpu62nufY=", + "dev": true + }, + "css-rule-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/css-rule-stream/-/css-rule-stream-1.1.0.tgz", + "integrity": "sha1-N4bnGYmD2WWibjGVfgkHjLt3BaI=", + "dev": true, + "requires": { + "css-tokenize": "^1.0.1", + "duplexer2": "0.0.2", + "ldjson-stream": "^1.2.1", + "through2": "^0.6.3" + } + }, + "css-tokenize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/css-tokenize/-/css-tokenize-1.0.1.tgz", + "integrity": "sha1-RiXLHtohwUOFi3+B1oA8HSb8FL4=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^1.0.33" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "doiuse": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/doiuse/-/doiuse-2.6.0.tgz", + "integrity": "sha1-GJLRC2Gpo1at2/K2FJM+gfi7ODQ=", + "dev": true, + "requires": { + "browserslist": "^1.1.1", + "caniuse-db": "^1.0.30000187", + "css-rule-stream": "^1.1.0", + "duplexer2": "0.0.2", + "jsonfilter": "^1.1.2", + "ldjson-stream": "^1.2.1", + "lodash": "^4.0.0", + "multimatch": "^2.0.0", + "postcss": "^5.0.8", + "source-map": "^0.4.2", + "through2": "^0.6.3", + "yargs": "^3.5.4" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "dev": true, + "requires": { + "camelcase": "^2.0.1", + "cliui": "^3.0.3", + "decamelize": "^1.1.1", + "os-locale": "^1.4.0", + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" + } + } + } + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "~1.1.9" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "electron-to-chromium": { + "version": "1.3.344", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.344.tgz", + "integrity": "sha512-tvbx2Wl8WBR+ym3u492D0L6/jH+8NoQXqe46+QhbWH3voVPauGuZYeb1QAXYoOAWuiP2dbSvlBx0kQ1F3hu/Mw==", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + }, + "dependencies": { + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + } + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", + "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", + "dev": true, + "requires": { + "babel-code-frame": "^6.16.0", + "chalk": "^1.1.3", + "concat-stream": "^1.5.2", + "debug": "^2.1.1", + "doctrine": "^2.0.0", + "escope": "^3.6.0", + "espree": "^3.4.0", + "esquery": "^1.0.0", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "glob": "^7.0.3", + "globals": "^9.14.0", + "ignore": "^3.2.0", + "imurmurhash": "^0.1.4", + "inquirer": "^0.12.0", + "is-my-json-valid": "^2.10.0", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.5.1", + "json-stable-stringify": "^1.0.0", + "levn": "^0.3.0", + "lodash": "^4.0.0", + "mkdirp": "^0.5.0", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.1", + "pluralize": "^1.2.1", + "progress": "^1.1.8", + "require-uncached": "^1.0.2", + "shelljs": "^0.7.5", + "strip-bom": "^3.0.0", + "strip-json-comments": "~2.0.1", + "table": "^3.7.8", + "text-table": "~0.2.0", + "user-home": "^2.0.0" + } + }, + "eslint-config-airbnb-base": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.3.2.tgz", + "integrity": "sha512-/fhjt/VqzBA2SRsx7ErDtv6Ayf+XLw9LIOqmpBuHFCVwyJo2EtzGWMB9fYRFBoWWQLxmNmCpenNiH0RxyeS41w==", + "dev": true, + "requires": { + "eslint-restricted-globals": "^0.1.1" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz", + "integrity": "sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + } + }, + "eslint-module-utils": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz", + "integrity": "sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + } + }, + "eslint-plugin-import": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz", + "integrity": "sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "array.prototype.flat": "^1.2.1", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.4.1", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.0", + "read-pkg-up": "^2.0.0", + "resolve": "^1.12.0" + }, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + } + } + }, + "eslint-restricted-globals": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz", + "integrity": "sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc=", + "dev": true + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "dev": true, + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "execall": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execall/-/execall-1.0.0.tgz", + "integrity": "sha1-c9CQTjlbPKsGWLCNCewlMH8pu3M=", + "dev": true, + "requires": { + "clone-regexp": "^1.0.0" + } + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "^2.1.0" + } + }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "flat-cache": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", + "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" + } + }, + "flatten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", + "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gather-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gather-stream/-/gather-stream-1.0.0.tgz", + "integrity": "sha1-szmUr0V6gRVwDUEPMXczy+egkEs=", + "dev": true + }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dev": true, + "requires": { + "is-property": "^1.0.2" + } + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "^1.0.0" + } + }, + "get-stdin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", + "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=", + "dev": true + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "hosted-git-info": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", + "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", + "dev": true + }, + "html-tags": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", + "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", + "dev": true + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "inquirer": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "dev": true, + "requires": { + "ansi-escapes": "^1.1.0", + "ansi-regex": "^2.0.0", + "chalk": "^1.0.0", + "cli-cursor": "^1.0.1", + "cli-width": "^2.0.0", + "figures": "^1.3.5", + "lodash": "^4.3.0", + "readline2": "^1.0.1", + "run-async": "^0.1.0", + "rx-lite": "^3.1.2", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" + } + }, + "interpret": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "irregular-plurals": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-1.4.0.tgz", + "integrity": "sha1-LKmwM2UREYVUEvFr5dd8YqRYp2Y=", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", + "dev": true + }, + "is-my-json-valid": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz", + "integrity": "sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA==", + "dev": true, + "requires": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-supported-regexp-flag": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.1.tgz", + "integrity": "sha512-3vcJecUUrpgCqc/ca0aWeNu64UGgxcvO60K/Fkr1N6RSvfGCTU60UKN68JDmKokgba0rFFJs12EnzOQa14ubKQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "js-base64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", + "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonfilter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/jsonfilter/-/jsonfilter-1.1.2.tgz", + "integrity": "sha1-Ie987cdRk4E8dZMulqmL4gW6WhE=", + "dev": true, + "requires": { + "JSONStream": "^0.8.4", + "minimist": "^1.1.0", + "stream-combiner": "^0.2.1", + "through2": "^0.6.3" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonparse": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", + "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "known-css-properties": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.2.0.tgz", + "integrity": "sha512-UTCzU28rRI9wkb8qSGoZa9pgWvxr4LjP2MEhi9XHb/1XMOJy0uTnIxaxzj8My/PORG+kQG6VzAcGvRw66eIOfA==", + "dev": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "ldjson-stream": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ldjson-stream/-/ldjson-stream-1.2.1.tgz", + "integrity": "sha1-kb7O2lrE7SsX5kn7d356v6AYnCs=", + "dev": true, + "requires": { + "split2": "^0.2.1", + "through2": "^0.6.1" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "^1.0.0" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", + "dev": true + }, + "mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" + }, + "mime-types": { + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "requires": { + "mime-db": "1.43.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multimatch": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", + "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", + "dev": true, + "requires": { + "array-differ": "^1.0.0", + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "minimatch": "^3.0.0" + } + }, + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "normalize-selector": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz", + "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=", + "dev": true + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onecolor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/onecolor/-/onecolor-3.1.0.tgz", + "integrity": "sha512-YZSypViXzu3ul5LMu/m6XjJ9ol8qAy9S2VjHl5E6UlhUH1KGKWabyEJifn0Jjpw23bYDzC2ucKMPGiH5kfwSGQ==", + "dev": true + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pipetteur": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pipetteur/-/pipetteur-2.0.3.tgz", + "integrity": "sha1-GVV2CVno0aEcsqUOyD7sRwYz5J8=", + "dev": true, + "requires": { + "onecolor": "^3.0.4", + "synesthesia": "^1.0.1" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "plur": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/plur/-/plur-2.1.2.tgz", + "integrity": "sha1-dIJFLBoPUI4+NE6uwxLJHCncZVo=", + "dev": true, + "requires": { + "irregular-plurals": "^1.0.0" + } + }, + "pluralize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" + }, + "dependencies": { + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "postcss-less": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-0.14.0.tgz", + "integrity": "sha1-xjGwicbM5CK5oQ86lY0r7dOBkyQ=", + "dev": true, + "requires": { + "postcss": "^5.0.21" + } + }, + "postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", + "dev": true + }, + "postcss-reporter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-3.0.0.tgz", + "integrity": "sha1-CeoPN6RExWk4eGBuCbAY6+/3z48=", + "dev": true, + "requires": { + "chalk": "^1.0.0", + "lodash": "^4.1.0", + "log-symbols": "^1.0.2", + "postcss": "^5.0.0" + } + }, + "postcss-resolve-nested-selector": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4=", + "dev": true + }, + "postcss-scss": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-0.4.1.tgz", + "integrity": "sha1-rXcbgfD3L19IRdCKpg+TVXZT1Uw=", + "dev": true, + "requires": { + "postcss": "^5.2.13" + } + }, + "postcss-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", + "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", + "dev": true, + "requires": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "psl": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", + "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dev": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } + } + }, + "read-file-stdin": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/read-file-stdin/-/read-file-stdin-0.2.1.tgz", + "integrity": "sha1-JezP86FTtoCa+ssj7hU4fbng7mE=", + "dev": true, + "requires": { + "gather-stream": "^1.0.0" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "readline2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "mute-stream": "0.0.5" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "require-from-string": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", + "dev": true + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + } + }, + "resolve": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz", + "integrity": "sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "dev": true, + "requires": { + "once": "^1.3.0" + } + }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "dev": true + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "shelljs": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", + "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "specificity": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.3.2.tgz", + "integrity": "sha512-Nc/QN/A425Qog7j9aHmwOrlwX2e7pNI47ciwxwy4jOlvbbMHkNNJchit+FX+UjF3IAdiaaV5BKeWuDUnws6G1A==", + "dev": true + }, + "split2": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/split2/-/split2-0.2.1.tgz", + "integrity": "sha1-At2smtwD7Au3jBKC7Aecpuha6QA=", + "dev": true, + "requires": { + "through2": "~0.6.1" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "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", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stream-combiner": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", + "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", + "dev": true, + "requires": { + "duplexer": "~0.1.1", + "through": "~2.3.4" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + }, + "dependencies": { + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + } + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=", + "dev": true + }, + "stylehacks": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-2.3.2.tgz", + "integrity": "sha1-ZMg+BDimjJ7fRJ6MVSp9mrYAmws=", + "dev": true, + "requires": { + "browserslist": "^1.1.3", + "chalk": "^1.1.1", + "log-symbols": "^1.0.2", + "minimist": "^1.2.0", + "plur": "^2.1.2", + "postcss": "^5.0.18", + "postcss-reporter": "^1.3.3", + "postcss-selector-parser": "^2.0.0", + "read-file-stdin": "^0.2.1", + "text-table": "^0.2.0", + "write-file-stdout": "0.0.2" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "postcss-reporter": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-1.4.1.tgz", + "integrity": "sha1-wTbwpbFhkV83ndN2XGEHX357mvI=", + "dev": true, + "requires": { + "chalk": "^1.0.0", + "lodash": "^4.1.0", + "log-symbols": "^1.0.2", + "postcss": "^5.0.0" + } + } + } + }, + "stylelint": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-7.13.0.tgz", + "integrity": "sha1-ER+Xttpy53XICADWu29fhpmXeF0=", + "dev": true, + "requires": { + "autoprefixer": "^6.0.0", + "balanced-match": "^0.4.0", + "chalk": "^2.0.1", + "colorguard": "^1.2.0", + "cosmiconfig": "^2.1.1", + "debug": "^2.6.0", + "doiuse": "^2.4.1", + "execall": "^1.0.0", + "file-entry-cache": "^2.0.0", + "get-stdin": "^5.0.0", + "globby": "^6.0.0", + "globjoin": "^0.1.4", + "html-tags": "^2.0.0", + "ignore": "^3.2.0", + "imurmurhash": "^0.1.4", + "known-css-properties": "^0.2.0", + "lodash": "^4.17.4", + "log-symbols": "^1.0.2", + "mathml-tag-names": "^2.0.0", + "meow": "^3.3.0", + "micromatch": "^2.3.11", + "normalize-selector": "^0.2.0", + "pify": "^2.3.0", + "postcss": "^5.0.20", + "postcss-less": "^0.14.0", + "postcss-media-query-parser": "^0.2.0", + "postcss-reporter": "^3.0.0", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-scss": "^0.4.0", + "postcss-selector-parser": "^2.1.1", + "postcss-value-parser": "^3.1.1", + "resolve-from": "^3.0.0", + "specificity": "^0.3.0", + "string-width": "^2.0.0", + "style-search": "^0.1.0", + "stylehacks": "^2.3.2", + "sugarss": "^0.2.0", + "svg-tags": "^1.0.0", + "table": "^4.0.1" + }, + "dependencies": { + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", + "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", + "dev": true, + "requires": { + "ajv": "^6.0.1", + "ajv-keywords": "^3.0.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + } + } + } + }, + "stylelint-config-standard": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-16.0.0.tgz", + "integrity": "sha1-u3OHv/HX3XGGpSs+v4hbJAXWkb8=", + "dev": true + }, + "sugarss": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-0.2.0.tgz", + "integrity": "sha1-rDQjdWMyfG/4l7ZHQr9q7BkK054=", + "dev": true, + "requires": { + "postcss": "^5.2.4" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", + "dev": true + }, + "synesthesia": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/synesthesia/-/synesthesia-1.0.1.tgz", + "integrity": "sha1-XvlepUjA1cbm+btLDQcx3/hkp3c=", + "dev": true, + "requires": { + "css-color-names": "0.0.3" + } + }, + "table": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "dev": true, + "requires": { + "ajv": "^4.7.0", + "ajv-keywords": "^1.0.0", + "chalk": "^1.1.1", + "lodash": "^4.0.0", + "slice-ansi": "0.0.4", + "string-width": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "dev": true, + "requires": { + "os-homedir": "^1.0.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", + "dev": true + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "write-file-stdout": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/write-file-stdout/-/write-file-stdout-0.0.2.tgz", + "integrity": "sha1-wlLXx8WxtAKJdjDjRTx7/mkNnKE=", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.3.3.tgz", + "integrity": "sha1-BU3oth8i7v23IHBZ6u+da4P7kxo=", + "dev": true + } + } +} From 57653f9bedef3b74f7217ae1210cf5cc492119ca Mon Sep 17 00:00:00 2001 From: lavolp3 Date: Fri, 14 Feb 2020 15:35:50 +0100 Subject: [PATCH 02/31] included choice of more than one competition and matches --- MMM-soccer.js | 83 ++++++++++++++---------- MMM-soccer.njk | 47 ++++++++++---- node_helper.js | 161 +++++++++++++++++++++------------------------- package-lock.json | 29 ++++++++- package.json | 1 + 5 files changed, 187 insertions(+), 134 deletions(-) diff --git a/MMM-soccer.js b/MMM-soccer.js index c3f7bb0..475d775 100644 --- a/MMM-soccer.js +++ b/MMM-soccer.js @@ -33,25 +33,30 @@ Module.register('MMM-soccer', { * @member {Object} defaults - Defines the default config values. * @property {boolean|string} api_key - API acces key for football-data.org. * @property {boolean} colored - Flag to show logos in color or black/white. - * @property {string} show - Country name (uppercase) to be shown in module. + * @property {array} show - League names to be filtered for showing tables and games. * @property {boolean|Object} focus_on - Hash of country name -> club name to determine highlighted team per league. - * @property {boolean|int} max_teams - Maximium amount of teams to be displayed. + * @property {boolean|int} max_teams - Maximum amount of teams to be displayed. * @property {boolean} logos - Flag to show club logos. * @property {Object} leagues - Hash of country name -> league id. */ defaults: { api_key: false, colored: false, - show: 'GERMANY', + show: ['BL1', 'CL', 'PL'], focus_on: false, max_teams: false, - logos: false, + logos: true, + showTable: true, + showGames: true, + gameType: 'daily', leagues: { - GERMANY: 'DFB', + GERMANY: 'BL1', FRANCE: 'FL1', ENGLAND: 'PL', SPAIN: 'PD', - ITALY: 'SA' + ITALY: 'SA', + CHAMPIONS_LEAGUE: 'CL', + NETHERLANDS: 'DED', } }, @@ -86,13 +91,15 @@ Module.register('MMM-soccer', { */ loading: true, /** - * @member {Object[]} standing - Stores the list of standing table entries of current selected league. + * @member {Object[]} tables - Stores the list of tables of current selected leagues. + * @member {Object[]} matches - Stores the list of matches of current selected leagues. */ - standing: [], + tables: {}, + matches: {}, /** - * @member {Object} competition - Details about the current selected league. + * @member {Object} competition - The currently selected league. */ - competition: {}, + competition: "BL1", /** * @function start @@ -102,11 +109,12 @@ Module.register('MMM-soccer', { start: function() { Log.info(`Starting module: ${this.name}`); this.addFilters(); - this.currentLeague = this.config.leagues[this.config.show]; + this.competition = this.config.show[0]; this.getData(); - setInterval(() => { + /*setInterval(() => { this.getData(); - }, this.config.api_key ? 300000 : 1800000); // with api_key every 5min without every 30min + }, this.config.api_key ? 60000 : 1800000); // with api_key every 5min without every 30min + */ }, /** @@ -114,7 +122,10 @@ Module.register('MMM-soccer', { * @description Sends request to the node_helper to fetch data for the current selected league. */ getData: function() { - this.sendSocketNotification('GET_DATA', { league: this.currentLeague, api_key: this.config.api_key }); + //this.sendSocketNotification('GET_TODAYS_MATCHES', { leagues: this.config.show, api_key: this.config.api_key }); + this.sendSocketNotification('GET_TABLES', { leagues: this.config.show, api_key: this.config.api_key }); + this.sendSocketNotification('GET_MATCHES', { leagues: this.config.show, api_key: this.config.api_key }); + }, /** @@ -126,13 +137,18 @@ Module.register('MMM-soccer', { * @param {*} payload - Detailed payload of the notification. */ socketNotificationReceived: function(notification, payload) { - if (notification === 'DATA') { - this.standing = payload.standings[0].table; - this.season = payload.season; - this.competition = payload.competition; - this.loading = false; - this.updateDom(); + console.log("MMM-soccer received a Socket Notification: " + notification + ", payload: "+payload); + if (notification === 'TABLES') { + this.tables = payload; + this.standing = this.tables[0].standings[0].table; + } else if (notification === 'MATCHES') { + this.matches = payload; + console.log(this.matches[0].matches.filter(match => { return match.matchday === this.tables[0].season.currentMatchday })); } + if (this.tables.length && this.matches.length) { + this.loading = false; + this.updateDom(); + } }, /** @@ -158,7 +174,7 @@ Module.register('MMM-soccer', { }, getStyles: function() { - return ['font-awesome.css', 'MMM-soccer.css']; + return ['MMM-soccer.css']; }, getTranslations: function() { @@ -183,14 +199,15 @@ Module.register('MMM-soccer', { */ getTemplateData: function() { return { - boundaries: this.calculateTeamDisplayBoundaries(), - competitionName: this.competition.name || this.name, + boundaries: (this.tables.length) ? this.calculateTeamDisplayBoundaries(this.competition) : {}, + competitionName: (this.tables.length) ? this.tables[0].competition.name : "", config: this.config, isModalActive: this.isModalActive(), modals: this.modals, - season: this.season ? - `${this.translate('MATCHDAY')}: ${this.season.currentMatchday || 'N/A'}` : this.translate('LOADING'), - standing: this.standing, + season: (this.tables.length) ? + `${this.translate('MATCHDAY')}: ${this.tables[0].season.currentMatchday || 'N/A'}` : this.translate('LOADING'), + standings: (this.tables.length) ? this.tables[0].standings : "", + matches: (this.matches.length) ? this.matches[0].matches.filter(match => { return match.matchday === this.tables[0].season.currentMatchday }) : "", voice: this.voice }; }, @@ -283,9 +300,9 @@ Module.register('MMM-soccer', { */ findFocusTeam() { let focusTeamIndex; - - for (let i = 0; i < this.standing.length; i += 1) { - if (this.standing[i].team.name === this.config.focus_on[this.config.show]) { + var table = this.standing; + for (let i = 0; i < table.length; i += 1) { + if (table[i].team.name === this.config.focus_on[this.competition]) { focusTeamIndex = i; break; } @@ -294,7 +311,7 @@ Module.register('MMM-soccer', { const { firstTeam, lastTeam } = this.getFirstAndLastTeam(focusTeamIndex); return { focusTeamIndex, firstTeam, lastTeam }; - }, + }, /** * @function getFirstAndLastTeam @@ -330,9 +347,9 @@ Module.register('MMM-soccer', { * * @returns {Object} Index of team, first and last team to display. */ - calculateTeamDisplayBoundaries() { - if (this.config.focus_on && Object.prototype.hasOwnProperty.call(this.config.focus_on, this.config.show)) { - if (this.config.focus_on[this.config.show] === 'TOP') { + calculateTeamDisplayBoundaries(competition) { + if (this.config.focus_on && this.config.focus_on.hasOwnProperty(competition)) { + if (this.config.focus_on[competition] === 'TOP') { return { focusTeamIndex: -1, firstTeam: 0, diff --git a/MMM-soccer.njk b/MMM-soccer.njk index 8a8c34e..348ec20 100644 --- a/MMM-soccer.njk +++ b/MMM-soccer.njk @@ -5,6 +5,27 @@ {% else %}
{{competitionName}}
{{season}}
+ + + {% for index in range(0, matches.length) %} + + + {% if config.logos %} + + {% endif %} + + {% if config.logos %} + + {% endif %} + + + {% endfor %} + +
{{matches[index].homeTeam.name}} + {% if matches[index].status == "ACTIVE" %}{{matches[index].score.fullTime.homeTeam}} - {{matches[index].score.fullTime.awayTeam}} + {% else %}0 - 0 + {% endif %} + {{matches[index].awayTeam.name}}
@@ -13,27 +34,29 @@ {% endif %} - - + + {% for index in range(boundaries.firstTeam, boundaries.lastTeam) %} - + {% if config.logos %} - + {% endif %} - - - + + + {% endfor %}
{{'TEAM' | translate}}
{{standing[index].position}}{{standings[0].table[index].position}}{{standing[index].team.name}}{{standing[index].points}}{{standing[index].goalDifference}}{{standings[0].table[index].team.name}}{{standings[0].table[index].points}}{{standings[0].table[index].goalDifference}}
{% endif %} - {% if isModalActive %} + + + {% if isModalActive %} - - - {% if isModalActive %} - - {% endif %} + + {% endif %} + {{table[i].team.name | replace}} + {{table[i].points}} + {{table[i].goalDifference}} + + {% endfor %} + + + {% endif %} + {% endif %} + + +{% if isModalActive %} + {% if modal.standings %} + +{% endif %} diff --git a/node_helper.js b/node_helper.js index b60447b..791d903 100644 --- a/node_helper.js +++ b/node_helper.js @@ -11,7 +11,6 @@ /* eslint-disable no-console */ /* jshint esversion: 6 */ -const request = require('request'); const axios = require('axios'); const NodeHelper = require('node_helper'); @@ -24,6 +23,10 @@ const NodeHelper = require('node_helper'); */ module.exports = NodeHelper.create({ + matches: {}, + tables: {}, + teams: {}, + start() { console.log(`Starting module: ${this.name}`); }, @@ -38,8 +41,9 @@ module.exports = NodeHelper.create({ */ socketNotificationReceived(notification, payload) { console.log("Socket notification received: "+notification+" Payload: "+JSON.stringify(payload)); - this.headers = payload.api_key ? { 'X-Auth-Token': payload.api_key } : {} - /*this.options = { + this.headers = payload.api_key ? { 'X-Auth-Token': payload.api_key } : {}; + this.config = payload; + /*this.options = { standings: { url: `http://api.football-data.org/v2/competitions/${payload.league}/standings`, headers: payload.api_key ? { 'X-Auth-Token': payload.api_key } : {} @@ -54,71 +58,88 @@ module.exports = NodeHelper.create({ }, };*/ - - if (notification === 'GET_TABLES') { - this.getTables(payload.leagues); - } else if (notification === 'GET_MATCHES') { - this.getMatches(payload.leagues); + + if (notification === 'GET_TABLES') { + this.getTables(payload.show); + } else if (notification === 'GET_MATCHES') { + this.getMatches(payload.show); } /*else if (notification === 'GET_TODAYS_MATCHES') { - this.getMatches(this.options.currentMatches, payload.leagues); + this.getMatches(this.options.currentMatches, payload.show); }*/ }, /** - * @function getTable + * @function getTables * @description Request data from the supplied URL and broadcast it to the MagicMirror module if it's received. * * @param {Object} options - request optionsthe notification. */ getTables(leagues) { - self = this; - console.log("Collecting league tables for leagues: "+leagues); - var urlArray = leagues.map(league => { return `http://api.football-data.org/v2/competitions/${league}/standings`; }) - console.log(urlArray); - Promise.all(urlArray.map(url => { - return axios.get(url, { headers: self.headers }) - .then(function (response) { - var tableData = response.data; - var table = { - competition: tableData.competition, - season: tableData.season, - standings: tableData.standings.filter(table => {return table.type === "TOTAL"}) - }; - //console.log(table); - return(table); - }) - .catch(function (err) { - console.log(`Error fetching league table for url ${url}: ${err}`); - return ""; - }); - })) - .then(function (tableArray) { - //console.log("TableArray: "+JSON.stringify(tableArray)); - self.sendSocketNotification("TABLES", tableArray); - }); - }, + self = this; + console.log("Collecting league tables for leagues: "+leagues); + var urlArray = leagues.map(league => { return `http://api.football-data.org/v2/competitions/${league}/standings`; }); + //console.log(urlArray); + Promise.all(urlArray.map(url => { + return axios.get(url, { headers: self.headers }) + .then(function (response) { + var tableData = response.data; + var tables = { + competition: tableData.competition, + season: tableData.season, + standings: tableData.standings, + }; + //console.log(JSON.stringify(tables)); + return(tables); + }) + .catch(function (err) { + console.log(`Error fetching league table for url ${url}: ${err}`); + return ""; + }); + })) + .then(function(tableArray) { + tableArray.forEach(tables => { + tables.standings.forEach(standing => { + standing.table.forEach(team => { + self.teams[team.team.id] = team.team; + }); + }); + self.tables[tables.competition.code] = tables; + }); + //console.log(JSON.stringify(self.tables)); + //console.log(JSON.stringify(self.teams)); + //console.log("TableArray: "+JSON.stringify(tableArray)); + self.sendSocketNotification("TABLES", self.tables); + self.sendSocketNotification("TEAMS", self.teams); + }); + }, getMatches(leagues) { - self = this; - console.log("Collecting matches for leagues: "+leagues); - var urlArray = leagues.map(league => { return `http://api.football-data.org/v2/competitions/${league}/matches`; }) + self = this; + console.log("Collecting matches for leagues: "+leagues); + var urlArray = leagues.map(league => { return `http://api.football-data.org/v2/competitions/${league}/matches`; }); Promise.all(urlArray.map(url => { - return axios.get(url, { headers: self.headers }) - .then(function (response) { - var matchesData = response.data; - matchesData.matches.forEach(element => delete element.referees); - console.log(JSON.stringify(matchesData)); - return(matchesData); - }) - .catch(function (err) { - console.log(`Error fetching matches with url ${url}: ${err}`); - return ""; - }); - })) - .then(function (matchesArray) { - //console.log("MatchesArray: "+JSON.stringify(matchesArray)); - self.sendSocketNotification("MATCHES", matchesArray); - }); + return axios.get(url, { headers: self.headers }) + .then(function (response) { + var matchesData = response.data; + var league = matchesData.competition.code; + matchesData.matches.forEach(match => { + delete match.referees; + //match.focused = (match.homeTeam.name === self.config.focus_on[league]) ? true : (match.awayTeam.name === self.config.focus_on[league]) ? true : false; + }); + //console.log(JSON.stringify(matchesData)); + return(matchesData); + }) + .catch(function (err) { + console.log(`Error fetching matches with url ${url}: ${err}`); + return ""; + }); + })) + .then(function (matchesArray) { + matchesArray.forEach(comp => { + self.matches[comp.competition.code] = comp; + }); + //console.log(JSON.stringify(self.matches)); + self.sendSocketNotification("MATCHES", self.matches); + }); }, - }); diff --git a/package-lock.json b/package-lock.json index b9cdafd..545d6d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,6 +41,7 @@ "version": "6.11.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", + "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -162,24 +163,6 @@ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, "autoprefixer": { "version": "6.7.7", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", @@ -194,16 +177,6 @@ "postcss-value-parser": "^3.2.3" } }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", - "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" - }, "axios": { "version": "0.19.2", "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", @@ -229,14 +202,6 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -311,11 +276,6 @@ "integrity": "sha512-dmwZ7u58E68UCexHf92QERFL8kwwCv0TVS1LCNluhZo+565AXU5uNtnPF+J5E2MExwWJeNnhTD63BH8ncMV09g==", "dev": true }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -436,14 +396,6 @@ } } }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -471,7 +423,8 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true }, "cosmiconfig": { "version": "2.2.2", @@ -569,14 +522,6 @@ "type": "^1.0.1" } }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -607,11 +552,6 @@ "object-keys": "^1.0.12" } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -708,15 +648,6 @@ } } }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "electron-to-chromium": { "version": "1.3.344", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.344.tgz", @@ -1079,11 +1010,6 @@ } } }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, "extglob": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", @@ -1093,20 +1019,17 @@ "is-extglob": "^1.0.0" } }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, "fast-deep-equal": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", @@ -1213,21 +1136,6 @@ "for-in": "^1.0.1" } }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1270,14 +1178,6 @@ "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", "dev": true }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -1342,20 +1242,6 @@ "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - } - }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -1398,16 +1284,6 @@ "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", "dev": true }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, "ignore": { "version": "3.3.10", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", @@ -1662,11 +1538,6 @@ "has-symbols": "^1.0.1" } }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", @@ -1688,11 +1559,6 @@ "isarray": "1.0.0" } }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, "js-base64": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", @@ -1715,20 +1581,11 @@ "esprima": "^4.0.0" } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "json-stable-stringify": { "version": "1.0.1", @@ -1739,11 +1596,6 @@ "jsonify": "~0.0.0" } }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, "jsonfilter": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/jsonfilter/-/jsonfilter-1.1.2.tgz", @@ -1782,17 +1634,6 @@ "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", "dev": true }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -2022,19 +1863,6 @@ "regex-cache": "^0.4.2" } }, - "mime-db": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", - "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" - }, - "mime-types": { - "version": "2.1.26", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", - "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", - "requires": { - "mime-db": "1.43.0" - } - }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -2139,11 +1967,6 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -2324,11 +2147,6 @@ "pify": "^2.0.0" } }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -2490,20 +2308,11 @@ "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", "dev": true }, - "psl": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", - "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==" - }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true }, "randomatic": { "version": "3.1.1", @@ -2649,33 +2458,6 @@ "is-finite": "^1.0.0" } }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, "require-from-string": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", @@ -2741,16 +2523,6 @@ "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", "dev": true }, - "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -2839,22 +2611,6 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "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", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "stream-combiner": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", @@ -3293,41 +3049,12 @@ } } }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - } - } - }, "trim-newlines": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, "type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", @@ -3359,6 +3086,7 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, "requires": { "punycode": "^2.1.0" } @@ -3378,11 +3106,6 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -3393,16 +3116,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "window-size": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", diff --git a/package.json b/package.json index 41c32a8..8c2f01f 100644 --- a/package.json +++ b/package.json @@ -21,8 +21,7 @@ "docs": "./node_modules/.bin/jsdoc -c jsdoc.json ." }, "dependencies": { - "axios": "^0.19.2", - "request": "^2.74.0" + "axios": "^0.19.2" }, "devDependencies": { "eslint": "^3.14.1", diff --git a/translations/de.json b/translations/de.json index b431072..debbaa2 100644 --- a/translations/de.json +++ b/translations/de.json @@ -5,5 +5,9 @@ "TEAM": "Mannschaft", "COMMAND_LIST": "Liste aller Sprachbefehle", "MODE": "Modus", - "VOICE_COMMANDS": "Sprachbefehle" + "VOICE_COMMANDS": "Sprachbefehle", + "ROUND_OF_16": "Achtelfinale", + "ROUND_OF_8": "Viertelfinale", + "ROUND_OF_4": "Halbfinale", + "FINAL": "Finale" } \ No newline at end of file diff --git a/translations/en.json b/translations/en.json index 3935324..34613e5 100644 --- a/translations/en.json +++ b/translations/en.json @@ -5,5 +5,9 @@ "TEAM": "Team", "COMMAND_LIST": "List of all Voice Commands", "MODE": "Mode", - "VOICE_COMMANDS": "Voice Commands" + "VOICE_COMMANDS": "Voice Commands", + "ROUND_OF_16": "Round of 16", + "ROUND_OF_8": "Round of 8", + "ROUND_OF_4": "Semi Finals", + "FINAL": "Finals" } \ No newline at end of file From 65600f1668d8615656a7517bdde01eeb8b3b17a6 Mon Sep 17 00:00:00 2001 From: lavolp3 Date: Thu, 20 Feb 2020 11:15:24 +0100 Subject: [PATCH 04/31] included debug logging, updated README, tweaks and fixes und main .js --- MMM-soccer.css | 6 +++- MMM-soccer.js | 68 ++++++++++++++++++++++----------------- MMM-soccer.njk | 34 ++++++++++---------- README.md | 86 +++++++++++++++++++++++++++++++++----------------- node_helper.js | 29 ++++++++++------- 5 files changed, 137 insertions(+), 86 deletions(-) diff --git a/MMM-soccer.css b/MMM-soccer.css index f00cec3..ccfd44e 100644 --- a/MMM-soccer.css +++ b/MMM-soccer.css @@ -1,3 +1,7 @@ +.MMM-soccer .soccerWrapper { + #display: flex; +} + .MMM-soccer .icon { width: 24px; height: 24px; @@ -53,7 +57,7 @@ font-weight: bold; } -.MMM-soccer .active { +.MMM-soccer .IN_PLAY { color: yellow; } diff --git a/MMM-soccer.js b/MMM-soccer.js index 61e479e..bfd7bfe 100644 --- a/MMM-soccer.js +++ b/MMM-soccer.js @@ -46,10 +46,11 @@ Module.register('MMM-soccer', { show: ['BL1', 'CL', 'PL'], updateInterval: 60 * 1000, focus_on: false, + fadeFocus: false, max_teams: false, logos: true, showTables: true, - showGames: true, + showMatches: true, gameType: 'daily', leagues: { GERMANY: 'BL1', @@ -59,14 +60,16 @@ Module.register('MMM-soccer', { ITALY: 'SA', CHAMPIONS_LEAGUE: 'CL', NETHERLANDS: 'DED', + EUROPEAN_CHAMPIONSHIP_2020:'EC' }, + debug: true, replace: { 'BV Borussia 09 Dortmund': 'Borussia Dortmund', - '1. FC Union Berlin': 'Union Berlin', - 'TSV Fortuna 95 Düsseldorf': 'Fortuna Düsseldorf', - 'SC Paderborn 07': 'SC Paderborn', - 'Manchester City FC': 'Manchester City', - } + '1. FC Union Berlin': 'Union Berlin', + 'TSV Fortuna 95 Düsseldorf': 'Fortuna Düsseldorf', + 'SC Paderborn 07': 'SC Paderborn', + 'Manchester City FC': 'Manchester City', + }, }, /** @@ -131,10 +134,9 @@ Module.register('MMM-soccer', { setInterval(() => { count = (count === comps - 1) ? 0 : count + 1; _this.competition = _this.config.show[count]; - console.log(_this.competition); - _this.standing = _this.tables[_this.competition].standings[0].table; - console.log("Updating..."); - _this.updateDom(500); + this.log("Showing competition: "+_this.competition); + _this.standing = _this.filterTables(_this.tables[_this.competition], _this.config.focus_on[_this.competition]); + _this.updateDom(800); }, this.config.updateInterval); }, @@ -143,10 +145,13 @@ Module.register('MMM-soccer', { * @description Sends request to the node_helper to fetch data for the current selected league. */ getData: function() { + self = this; //this.sendSocketNotification('GET_TODAYS_MATCHES', { leagues: this.config.show, api_key: this.config.api_key }); this.sendSocketNotification('GET_TABLES', this.config); this.sendSocketNotification('GET_MATCHES', this.config); - + setInterval(() => { + self.sendSocketNotification('GET_MATCHES', this.config); + }, 60*1000); }, /** @@ -158,18 +163,17 @@ Module.register('MMM-soccer', { * @param {*} payload - Detailed payload of the notification. */ socketNotificationReceived: function(notification, payload) { - console.log("MMM-soccer received a Socket Notification: " + notification + ", payload: "+payload); + this.log("received a Socket Notification: " + notification + ", payload: "+payload); if (notification === 'TABLES') { this.tables = payload; this.standing = this.filterTables(this.tables[this.competition], this.config.focus_on[this.competition]); - console.log(this.standing); + this.log("Current table: "+this.standing); } else if (notification === 'MATCHES') { this.matches = payload; } else if (notification === 'TEAMS') { this.teams = payload; } if (this.tables.hasOwnProperty(this.competition) && this.matches.hasOwnProperty(this.competition)) { - //console.log(this.matches['BL1'].matches.filter(match => { return match.matchday === this.tables['BL1'].season.currentMatchday; })); this.loading = false; this.updateDom(500); } @@ -228,10 +232,10 @@ Module.register('MMM-soccer', { config: this.config, isModalActive: this.isModalActive(), modals: this.modals, + table: this.standing, + matches: (Object.keys(this.matches).length > 0) ? this.prepareMatches(this.matches[this.competition].matches, this.config.focus_on[this.competition]) : "", season: (Object.keys(this.tables).length > 0) ? `${this.translate('MATCHDAY')}: ${this.translate(this.matchDay)}` : this.translate('LOADING'), - table: this.standing, - matches: (Object.keys(this.matches).length > 0) ? this.prepareMatches(this.matches[this.competition].matches, this.config.focus_on[this.competition]) : "", showTable: this.showTable, teams: (Object.keys(this.tables).length > 0) ? this.teams : {}, voice: this.voice @@ -336,9 +340,9 @@ Module.register('MMM-soccer', { this.matchDay = matches[m].matchday; } } - console.log(this.matchDay); - this.showTable = (!isNaN(this.matchDay)) - + this.log("Current matchday: "+this.matchDay); + this.showTable = (!isNaN(this.matchDay)) + matches = matches.filter(match => { return match.matchday == this.matchDay; @@ -346,12 +350,12 @@ Module.register('MMM-soccer', { matches.forEach(match => { match.focused = (match.homeTeam.name === focusTeam) ? true : (match.awayTeam.name === focusTeam) ? true : false; if (match.status == "SCHEDULED") { - match.state = (moment(match.utcDate).diff(moment(), 'hours') > 23) ? moment(match.utcDate).format("D/M") : moment(match.utcDate).format("LT"); + match.state = (moment(match.utcDate).diff(moment(), 'days') > 7) ? moment(match.utcDate).format("D.MM") : (moment(match.utcDate).diff(moment(), 'hours') > 23) ? moment(match.utcDate).format("dd") : moment(match.utcDate).format("LT"); } else { match.state = match.score.fullTime.homeTeam + " - " + match.score.fullTime.awayTeam; } }); - //console.log(matches); + //this.log(matches); return matches; }, @@ -388,19 +392,19 @@ Module.register('MMM-soccer', { * @returns {Object} Index of team, first and last team to display. */ findFocusTeam() { - console.log("Finding focus team..."); + this.log("Finding focus team for table..."); let focusTeamIndex; var table = this.standing; for (let i = 0; i < table.length; i += 1) { if (table[i].team.name === this.config.focus_on[this.competition]) { focusTeamIndex = i; - console.log("Focus Team found: " + table[i].team.name); + this.log("Focus Team found: " + table[i].team.name); break; } } if (!focusTeamIndex) { - console.log("No Focus Team found! Please check your entry!"); + this.log("No Focus Team found! Please check your entry!"); return { focusTeamIndex: -1, firstTeam: 0, @@ -408,7 +412,6 @@ Module.register('MMM-soccer', { }; } else { const { firstTeam, lastTeam } = this.getFirstAndLastTeam(focusTeamIndex); - //console.log(focusTeamIndex, firstTeam, lastTeam); return { focusTeamIndex, firstTeam, lastTeam }; } }, @@ -447,23 +450,24 @@ Module.register('MMM-soccer', { * @returns {Object} Index of team, first and last team to display. */ calculateTeamDisplayBoundaries(competition) { - console.log("Calculating Team Display Boundaries"); + this.log("Calculating Team Display Boundaries"); if (this.config.focus_on && this.config.focus_on.hasOwnProperty(competition)) { if (this.config.focus_on[competition] === 'TOP') { - console.log("Focus on TOP"); + this.log("Focus on TOP"); return { focusTeamIndex: -1, firstTeam: 0, lastTeam: this.isMaxTeamsLessAll() ? this.config.max_teams : this.standing.length }; } else if (this.config.focus_on[this.config.show] === 'BOTTOM') { - console.log("Focus on BOTTOM"); + this.log("Focus on BOTTOM"); return { focusTeamIndex: -1, firstTeam: this.isMaxTeamsLessAll() ? this.standing.length - this.config.max_teams : 0, lastTeam: this.standing.length }; } + this.log("Focus on Team"); return this.findFocusTeam(); } @@ -481,7 +485,7 @@ Module.register('MMM-soccer', { addFilters() { njEnv = this.nunjucksEnvironment(); njEnv.addFilter('fade', (index, focus) => { - if (this.config.max_teams && focus >= 0) { + if (this.config.max_teams && this.config.fadeFocus && focus >= 0) { if (index !== focus) { const currentStep = Math.abs(index - focus); return `opacity: ${1 - ((1 / this.config.max_teams) * currentStep)}`; @@ -499,4 +503,10 @@ Module.register('MMM-soccer', { } }); }, + + log: function (msg) { + if (this.config && this.config.debug) { + console.log(this.name + ":", JSON.stringify(msg)); + } + }, }); diff --git a/MMM-soccer.njk b/MMM-soccer.njk index d596e63..f0c6de9 100644 --- a/MMM-soccer.njk +++ b/MMM-soccer.njk @@ -1,27 +1,29 @@ -
+
{% if loading %} {{'LOADING' | translate}} {% else %} -
{{competitionName}}
-
{{season}}
- - +
{{competitionName}}
+
{{season}}
+ {% if config.showMatches %} +
+ {% for i in range(0, matches.length) %} - - - {% if config.logos %} - - {% endif %} - - {% if config.logos %} - - {% endif %} - + + + {% if config.logos %} + + {% endif %} + + {% if config.logos %} + + {% endif %} + {% endfor %}
{{matches[i].homeTeam.name | replace}}{{ matches[i].state }} - {{matches[i].awayTeam.name | replace}}
{{matches[i].homeTeam.name | replace}}{{ matches[i].state }} + {{matches[i].awayTeam.name | replace}}
+ {% endif %} {% if showTable %} diff --git a/README.md b/README.md index c770047..96b4320 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# MMM-soccer [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://raw.githubusercontent.com/fewieden/MMM-soccer/master/LICENSE) [![Build Status](https://travis-ci.org/fewieden/MMM-soccer.svg?branch=master)](https://travis-ci.org/fewieden/MMM-soccer) [![Code Climate](https://codeclimate.com/github/fewieden/MMM-soccer/badges/gpa.svg?style=flat)](https://codeclimate.com/github/fewieden/MMM-soccer) [![Known Vulnerabilities](https://snyk.io/test/github/fewieden/mmm-soccer/badge.svg)](https://snyk.io/test/github/fewieden/mmm-soccer) [![API Doc](https://doclets.io/fewieden/MMM-soccer/master.svg)](https://doclets.io/fewieden/MMM-soccer/master) +# MMM-soccer [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://raw.githubusercontent.com/fewieden/MMM-soccer/master/LICENSE) -European Soccer Standings Module for MagicMirror² +A Soccer Standings Module for MagicMirror², based on @fewiedens [!MMM-soccer](https://github.com/fewieden/MMM-soccer) -## Example +## Examples ![](.github/example_full.png) ![](.github/example_focused.png) ![](.github/example.jpg) @@ -12,57 +12,68 @@ European Soccer Standings Module for MagicMirror² * An installation of [MagicMirror²](https://github.com/MichMich/MagicMirror) * OPTIONAL: [Voice Control](https://github.com/fewieden/MMM-voice) * npm -* [request](https://www.npmjs.com/package/request) +* [axios](https://www.npmjs.com/package/axios) ## Installation -1. Clone this repo into `~/MagicMirror/modules` directory. -1. Configure your `~/MagicMirror/config/config.js`: +1. Clone this repo into your `~/MagicMirror/modules` directory. +```git clone https://github.com/lavolp3/MMM-soccer``` +2. Run command `npm install` in `~/MagicMirror/modules/MMM-soccer` directory. +3. Configure your `~/MagicMirror/config/config.js`: ``` { module: 'MMM-soccer', - position: 'bottom_right', + position: 'bottom_left', config: { ... } } ``` -1. Run command `npm i --production` in `~/MagicMirror/modules/MMM-soccer` directory. -1. Optional: Get a free api key [here](http://api.football-data.org/register) + +4. Optional: Get a free api key [here](http://api.football-data.org/register) (highly recommended) + ## Config Options | **Option** | **Default** | **Description** | | --- | --- | --- | -| `api_key` | false | Either false (limited to 50 requests a day) or an API Key obtained from (limited to 50 requests a minute) . | -| `colored` | false | Boolean to show club logos in color or not. | -| `show` | 'GERMANY' | Which league should be displayed 'GERMANY', 'FRANCE', 'ENGLAND', 'SPAIN' or 'ITALY' | -| `focus_on` | false | Which team should the standings focus on per league e.g. {"GERMANY": "FC Bayern München", "FRANCE": "Olympique Lyonnais"}. Omit this option or set to false to show the full league table. | -| `max_teams` | false | How many teams should be displayed. Omit this option or set to false to show the full league table. | -| `leagues` | `{"GERMANY": "BL1", "FRANCE": "FL1", "ENGLAND": "PL", "SPAIN": "PD", "ITALY": "SA"}` | A collection of leagues obtained from | -| `logos` | `false` | Boolean to show club logos or not. | +| `width` | `400` | Width of match and standings table. The module has a flexible design aligning matches and table vertically or horizontically as space allows. | +| `api_key` | false | Either false (limited to 50 requests a day) or an API Key obtained from (limited to 10 requests a minute) . | +| `colored` | true | Boolean to show club logos in color or not. | +| `show` | ['BL1', 'PL', 'CL'] | An array of league codes to be displayed. With activated touch mode (see below) | +| `showMatches` | true | Show matches of current league | +| `showTables` | true | Show table of current league. Remark: For cups like Champions league, this will be set to false in knockout mode. | +| `focus_on` | false | Which team should the standings focus on per league e.g. {'BL1': 'FC Bayern München', 'CL': 'Liverpool FC'. Leave out any league you do not want to have a focus for any team. Omit this option or set to false to show the full league tables. | +| `max_teams` | false | How many teams should be displayed when focus is activated. Omit this option or set to false to show the full league table. | +| `logos` | false | Boolean to show club logos or not. | +| `liveMode` | true | Activates live mode when games are in play. (see below, not active yet) | +| `touchMode` | false | Activates touch mode with touch options (see below, not active yet) | +| `debug` | false | Debug mode: additional output on server side (console) and client side (browser) | + +## Live Mode (planned) + +The modules calls all requested matches every 5 minutes. Whenever one or more matches are scheduled in less than 5 minutes, a Live Mode will activate. +All matches currently played will be included in an array and requested for updates as regularly as the free api (10 calls per minute) allows. +Additional informations like game minute and scorers will be provided for these games. +Also, only the leagues with current matches will be shown (does not count for touch mode) +When no game is active, the module will return back to normal mode. -## Logos +Can be switched off in config -As the v2 api doesn't provide logos anymore, I developed a club logo downloader. It supports the five major leagues as above named. -To run the downloader you need to execute the following steps. -1. Go to the module directory `cd ~/MagicMirror/modules/MMM-soccer`. -1. Execute `node scripts/downloader COUNTRYNAME`. -1. Run this command for all the leagues you want to display on the mirror. -1. Don't forget to activate the display of the logos in the config. +## Touch mode (planned) -If there isn't every club logo, you can also place them manually in the public directory of the module, -the logos need to be in `svg` format and the name of the file has to match the displayed name. +Touch mode will create buttons to choose between leagues. +It is also planned to include more detailed information like scorers per league and scorers per game. + +Can be switched off in config ## OPTIONAL: Voice Control -This module supports voice control by -[MMM-voice](https://github.com/fewieden/MMM-voice). In order to use this -feature, it's required to install the voice module. There are no extra config -options for voice control needed. +This module supports voice control by @fewiedens [MMM-voice](https://github.com/fewieden/MMM-voice). In order to use this feature, it's required to install the voice module. There are no extra config options for voice control needed. + ### Mode @@ -78,3 +89,20 @@ The voice control mode for this module is `SOCCER` you have to edit the config) * EXPAND VIEW -> Expands the standings table and shows all teams. * COLLAPSE VIEW -> Collapse the expanded view. + +## List of available leagues (for the FREE API): + +As per [Football-data API Docs](https://www.football-data.org/documentation/api#league-codes): + +| **League** | **code** | +| (Europe) Champions League | 'CL1' | +| (Europe) European Championships 2020 | 'EC' | +| (English) Premier League | 'PL' | +| (English) Championship | 'ELC' | +| (German) Bundesliga | 'BL1' | +| (Italian) Serie A | 'PD' | +| (French) Ligue 1 | 'FL1' | +| (Spain) La Liga | 'PD' | +| (Portugal) Primiera Liga | 'PPL' | +| (Netherlands) Eredivisie | 'DED' | +| (Brazil) Serie A | --- | diff --git a/node_helper.js b/node_helper.js index 791d903..650785b 100644 --- a/node_helper.js +++ b/node_helper.js @@ -40,9 +40,10 @@ module.exports = NodeHelper.create({ * @param {*} payload - Detailed payload of the notification. */ socketNotificationReceived(notification, payload) { - console.log("Socket notification received: "+notification+" Payload: "+JSON.stringify(payload)); + this.log("Socket notification received: "+notification+" Payload: "+JSON.stringify(payload)); this.headers = payload.api_key ? { 'X-Auth-Token': payload.api_key } : {}; this.config = payload; + self = this; /*this.options = { standings: { url: `http://api.football-data.org/v2/competitions/${payload.league}/standings`, @@ -60,9 +61,9 @@ module.exports = NodeHelper.create({ };*/ if (notification === 'GET_TABLES') { - this.getTables(payload.show); + this.getTables(payload.show); } else if (notification === 'GET_MATCHES') { - this.getMatches(payload.show); + this.getMatches(payload.show); } /*else if (notification === 'GET_TODAYS_MATCHES') { this.getMatches(this.options.currentMatches, payload.show); }*/ @@ -76,9 +77,9 @@ module.exports = NodeHelper.create({ */ getTables(leagues) { self = this; - console.log("Collecting league tables for leagues: "+leagues); + this.log("Collecting league tables for leagues: "+leagues); var urlArray = leagues.map(league => { return `http://api.football-data.org/v2/competitions/${league}/standings`; }); - //console.log(urlArray); + //this.log(urlArray); Promise.all(urlArray.map(url => { return axios.get(url, { headers: self.headers }) .then(function (response) { @@ -88,7 +89,7 @@ module.exports = NodeHelper.create({ season: tableData.season, standings: tableData.standings, }; - //console.log(JSON.stringify(tables)); + //this.log(tables); return(tables); }) .catch(function (err) { @@ -105,9 +106,9 @@ module.exports = NodeHelper.create({ }); self.tables[tables.competition.code] = tables; }); - //console.log(JSON.stringify(self.tables)); - //console.log(JSON.stringify(self.teams)); - //console.log("TableArray: "+JSON.stringify(tableArray)); + //this.log("Collected tables: "+self.tables); + this.log("Collected Teams: "+self.teams); + //this.log("TableArray: "tableArray); self.sendSocketNotification("TABLES", self.tables); self.sendSocketNotification("TEAMS", self.teams); }); @@ -126,7 +127,7 @@ module.exports = NodeHelper.create({ delete match.referees; //match.focused = (match.homeTeam.name === self.config.focus_on[league]) ? true : (match.awayTeam.name === self.config.focus_on[league]) ? true : false; }); - //console.log(JSON.stringify(matchesData)); + //this.log(matchesData); return(matchesData); }) .catch(function (err) { @@ -138,8 +139,14 @@ module.exports = NodeHelper.create({ matchesArray.forEach(comp => { self.matches[comp.competition.code] = comp; }); - //console.log(JSON.stringify(self.matches)); + //this.log("Collected Matches: "+self.matches); self.sendSocketNotification("MATCHES", self.matches); }); }, + + log: function (msg) { + if (this.config && this.config.debug) { + console.log(this.name + ":", JSON.stringify(msg)); + } + }, }); From ea7adab769848eed671f52e0b2e0c99f63c9b91f Mon Sep 17 00:00:00 2001 From: Dirk Date: Thu, 20 Feb 2020 11:23:18 +0100 Subject: [PATCH 05/31] Update README.md updated example screenshots --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 96b4320..aedd9f3 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,10 @@ # MMM-soccer [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://raw.githubusercontent.com/fewieden/MMM-soccer/master/LICENSE) -A Soccer Standings Module for MagicMirror², based on @fewiedens [!MMM-soccer](https://github.com/fewieden/MMM-soccer) +A Soccer Standings Module for MagicMirror², based on @fewiedens [MMM-soccer](https://github.com/fewieden/MMM-soccer) ## Examples -![](.github/example_full.png) ![](.github/example_focused.png) -![](.github/example.jpg) +![](.github/example1.jpg) ![](.github/example2.jpg) ## Dependencies From 0fb813b60b49eb8be4d56ba5a07f6796e919b751 Mon Sep 17 00:00:00 2001 From: lavolp3 Date: Thu, 20 Feb 2020 11:24:15 +0100 Subject: [PATCH 06/31] updated screenshots --- .github/example.jpg | Bin 40241 -> 0 bytes .github/example1.JPG | Bin 0 -> 52585 bytes .github/example2.JPG | Bin 0 -> 43746 bytes .github/example_focused.png | Bin 24727 -> 0 bytes .github/example_full.png | Bin 62831 -> 0 bytes 5 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .github/example.jpg create mode 100644 .github/example1.JPG create mode 100644 .github/example2.JPG delete mode 100644 .github/example_focused.png delete mode 100644 .github/example_full.png diff --git a/.github/example.jpg b/.github/example.jpg deleted file mode 100644 index 3e4c81b94ada67dc4384203ecc76a68abe3d52b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40241 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 diff --git a/.github/example1.JPG b/.github/example1.JPG new file mode 100644 index 0000000000000000000000000000000000000000..a42cacbf3da21d7cdb46321c1c7c4a637ad95942 GIT binary patch literal 52585 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Р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 literal 0 HcmV?d00001 diff --git a/.github/example_focused.png b/.github/example_focused.png deleted file mode 100644 index 3fcaaf252d334cdb8c57db90878c2582244bbc86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24727 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 P;18mrtz4n_H1xj!MY^cT From c396a1e5a669cfb57be9b3d63a23b54a753395ab Mon Sep 17 00:00:00 2001 From: Dirk Date: Thu, 20 Feb 2020 11:25:20 +0100 Subject: [PATCH 07/31] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aedd9f3..cc79d87 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A Soccer Standings Module for MagicMirror², based on @fewiedens [MMM-soccer](ht ## Examples -![](.github/example1.jpg) ![](.github/example2.jpg) +![](.github/example1.JPG) ![](.github/example2.JPG) ## Dependencies From 64db1cdde3d00774eb825dcaae143be9a3ff4d8a Mon Sep 17 00:00:00 2001 From: Dirk Date: Thu, 20 Feb 2020 11:40:31 +0100 Subject: [PATCH 08/31] Update README.md --- README.md | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index cc79d87..8338b1c 100644 --- a/README.md +++ b/README.md @@ -41,16 +41,29 @@ A Soccer Standings Module for MagicMirror², based on @fewiedens [MMM-soccer](ht | `width` | `400` | Width of match and standings table. The module has a flexible design aligning matches and table vertically or horizontically as space allows. | | `api_key` | false | Either false (limited to 50 requests a day) or an API Key obtained from (limited to 10 requests a minute) . | | `colored` | true | Boolean to show club logos in color or not. | -| `show` | ['BL1', 'PL', 'CL'] | An array of league codes to be displayed. With activated touch mode (see below) | +| `show` | ['BL1', 'PL', 'CL'] | An array of league codes to be displayed. In normal mode, the leagues revolve using below update cycle. With activated touch mode (see below), you can choose one of the leagues via a button (planned) | +| `updateInterval` | 60 | The time frame for each league to be shown in seconds. | | `showMatches` | true | Show matches of current league | -| `showTables` | true | Show table of current league. Remark: For cups like Champions league, this will be set to false in knockout mode. | -| `focus_on` | false | Which team should the standings focus on per league e.g. {'BL1': 'FC Bayern München', 'CL': 'Liverpool FC'. Leave out any league you do not want to have a focus for any team. Omit this option or set to false to show the full league tables. | +| `showTables` | true | Show table of current league.*Remark*: For cups like Champions league, this will be set to false in knockout mode. | +| `focus_on` | null | Which team should to focus on per league. This needs to be an object. {'BL1': 'FC Bayern München', 'CL': 'Liverpool FC'}. See description below. | | `max_teams` | false | How many teams should be displayed when focus is activated. Omit this option or set to false to show the full league table. | -| `logos` | false | Boolean to show club logos or not. | +| `logos` | true | Boolean to show club logos. | | `liveMode` | true | Activates live mode when games are in play. (see below, not active yet) | | `touchMode` | false | Activates touch mode with touch options (see below, not active yet) | | `debug` | false | Debug mode: additional output on server side (console) and client side (browser) | + +## Focus + +You can focus on one time per league/cup using the focus_on method. This variable needs to be an object. +An example is below: +```{'BL1': 'FC Bayern München', 'CL': 'Liverpool FC'}``` +Please take care to include all quotation marks and use the league code (find below) for any league you have included in the "show" array. The team name needs to correspond to the name of the team as shown on your mirror. + +Omitting a league code from 'show' in this array will show the full league table and not include any focus. +Any league included here need to be included in 'show' as well to show the league on your mirror. + + ## Live Mode (planned) The modules calls all requested matches every 5 minutes. Whenever one or more matches are scheduled in less than 5 minutes, a Live Mode will activate. @@ -89,9 +102,10 @@ The voice control mode for this module is `SOCCER` * EXPAND VIEW -> Expands the standings table and shows all teams. * COLLAPSE VIEW -> Collapse the expanded view. -## List of available leagues (for the FREE API): -As per [Football-data API Docs](https://www.football-data.org/documentation/api#league-codes): +## List of available leagues (for the free API): + +As per the [Football-data API Docs](https://www.football-data.org/documentation/api#league-codes): | **League** | **code** | | (Europe) Champions League | 'CL1' | From b4a151a6f57041be61a5a2babc3eeab3e1f1146f Mon Sep 17 00:00:00 2001 From: lavolp3 Date: Fri, 21 Feb 2020 10:10:22 +0100 Subject: [PATCH 09/31] Updates in README --- MMM-soccer.js | 10 ---------- README.md | 33 +++++++++++++++++++++++++++------ 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/MMM-soccer.js b/MMM-soccer.js index bfd7bfe..a8518d4 100644 --- a/MMM-soccer.js +++ b/MMM-soccer.js @@ -52,16 +52,6 @@ Module.register('MMM-soccer', { showTables: true, showMatches: true, gameType: 'daily', - leagues: { - GERMANY: 'BL1', - FRANCE: 'FL1', - ENGLAND: 'PL', - SPAIN: 'PD', - ITALY: 'SA', - CHAMPIONS_LEAGUE: 'CL', - NETHERLANDS: 'DED', - EUROPEAN_CHAMPIONSHIP_2020:'EC' - }, debug: true, replace: { 'BV Borussia 09 Dortmund': 'Borussia Dortmund', diff --git a/README.md b/README.md index 8338b1c..5af2afd 100644 --- a/README.md +++ b/README.md @@ -44,8 +44,8 @@ A Soccer Standings Module for MagicMirror², based on @fewiedens [MMM-soccer](ht | `show` | ['BL1', 'PL', 'CL'] | An array of league codes to be displayed. In normal mode, the leagues revolve using below update cycle. With activated touch mode (see below), you can choose one of the leagues via a button (planned) | | `updateInterval` | 60 | The time frame for each league to be shown in seconds. | | `showMatches` | true | Show matches of current league | -| `showTables` | true | Show table of current league.*Remark*: For cups like Champions league, this will be set to false in knockout mode. | -| `focus_on` | null | Which team should to focus on per league. This needs to be an object. {'BL1': 'FC Bayern München', 'CL': 'Liverpool FC'}. See description below. | +| `showTables` | true | Show table of current league. *Remark*: For cups like Champions league, this will be set to false in knockout mode. | +| `focus_on` | null | Which team should to focus on per league. This needs to be an object, e.g. {'BL1': 'FC Bayern München', 'CL': 'Liverpool FC'}. See description below. | | `max_teams` | false | How many teams should be displayed when focus is activated. Omit this option or set to false to show the full league table. | | `logos` | true | Boolean to show club logos. | | `liveMode` | true | Activates live mode when games are in play. (see below, not active yet) | @@ -57,8 +57,13 @@ A Soccer Standings Module for MagicMirror², based on @fewiedens [MMM-soccer](ht You can focus on one time per league/cup using the focus_on method. This variable needs to be an object. An example is below: -```{'BL1': 'FC Bayern München', 'CL': 'Liverpool FC'}``` -Please take care to include all quotation marks and use the league code (find below) for any league you have included in the "show" array. The team name needs to correspond to the name of the team as shown on your mirror. +``` +{'BL1': 'FC Bayern München', 'CL': 'Liverpool FC'} +``` +Please take care to include all quotation marks, separate with commata, and use the same league codes (find below) you have included in the 'show' array. + +The team name needs to correspond to the original name of the team as provided by the API. +Have a look into the ```replace``` object in the config to see if the team name is replaced with a shorter one on the mirror. If that is the case, take the original one (the one on the left for each replace property). Omitting a league code from 'show' in this array will show the full league table and not include any focus. Any league included here need to be included in 'show' as well to show the league on your mirror. @@ -82,6 +87,7 @@ It is also planned to include more detailed information like scorers per league Can be switched off in config + ## OPTIONAL: Voice Control This module supports voice control by @fewiedens [MMM-voice](https://github.com/fewieden/MMM-voice). In order to use this feature, it's required to install the voice module. There are no extra config options for voice control needed. @@ -107,7 +113,9 @@ The voice control mode for this module is `SOCCER` As per the [Football-data API Docs](https://www.football-data.org/documentation/api#league-codes): -| **League** | **code** | + +| **League** | **Code** | +| --- | --- | | (Europe) Champions League | 'CL1' | | (Europe) European Championships 2020 | 'EC' | | (English) Premier League | 'PL' | @@ -118,4 +126,17 @@ As per the [Football-data API Docs](https://www.football-data.org/documentation/ | (Spain) La Liga | 'PD' | | (Portugal) Primiera Liga | 'PPL' | | (Netherlands) Eredivisie | 'DED' | -| (Brazil) Serie A | --- | +| (Brazil) Serie A | '' | + + +### TODOs + +- [ ] Include live mode +- [ ] Include option to replace team names with 3-letter-codes (very slim module) +- [ ] Include option to show scorers for each match +- [ ] Current top scorer list per league +- [ ] Touch mode +- [ ] Tap additional API (presumably API-football) for further competitions (e.g. DFB cup) +Add team specific data, e.g. +- [ ] next matches +- [ ] current squad / line-up From 9c6557f40d62a43f116c9ddf525b504f99a683c8 Mon Sep 17 00:00:00 2001 From: lavolp3 Date: Fri, 28 Feb 2020 00:59:31 +0100 Subject: [PATCH 10/31] stable 1.0.0 --- .github/CONTRIBUTING.md | 3 - CHANGELOG.md | 24 +-- LICENSE | 2 +- MMM-soccer.css | 15 +- MMM-soccer.js | 379 +++++++++++++++++++++++----------------- MMM-soccer.njk | 13 +- README.md | 62 ++++--- node_helper.js | 198 +++++++++++++++------ package.json | 17 +- replacements.json | 344 ++++++++++++++++++++++++++++++++++++ scripts/downloader.js | 137 --------------- 11 files changed, 771 insertions(+), 423 deletions(-) create mode 100644 replacements.json delete mode 100644 scripts/downloader.js diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 5956f32..41e0c23 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -3,6 +3,3 @@ Thanks for contributing to this module! Please create pull requests to the branch `develop`. - -To hold one code style and standard there are several linters and tools in this project set. Make sure you fullfill the requirements. -Also there will be automatically analysis performed once you created the pull request. diff --git a/CHANGELOG.md b/CHANGELOG.md index 602a0b6..83c2a11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,26 +1,4 @@ -# MMM-soccer Changelog - -## [2.0.0] - -### Added - -* Club logo downloader -* New config option `logos`. -* Swedish translations -* Documentation -* [Doclets.io](https://doclets.io/fewieden/MMM-soccer/master) integration -* Contributing guidelines -* Issue template -* Pull request template -* Editor config - -### Changed - -* Switched from Api v1 to v2. -* Updated league ids. -* Switched rendering from js to nunjuck template. -* Updated travis-ci config. -* Disabled markdown lint rules `MD024` and `MD026` +# MMM-soccer v2 changelog ## [1.0.0] diff --git a/LICENSE b/LICENSE index 7eedfa7..050a484 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016 fewieden +Copyright (c) 2020 lavolp3 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/MMM-soccer.css b/MMM-soccer.css index ccfd44e..ddaf360 100644 --- a/MMM-soccer.css +++ b/MMM-soccer.css @@ -31,18 +31,23 @@ .MMM-soccer .games .status { padding: 5px; border: 4px solid black; - background-color: grey; + background-color: #99aacc; color: black; border-radius: 10px; text-align: center; - font-size: 100%; + font-size: 100%; width: 50px; } +.MMM-soccer .games .status .IN_PLAY { + background-color: #fdfd96; + +} + .MMM-soccer .logo { width: 25px; - padding: 0px 3px; - vertical-align: middle; + padding: 0px 3px; + vertical-align: middle; } .MMM-soccer .centered-row { @@ -57,7 +62,7 @@ font-weight: bold; } -.MMM-soccer .IN_PLAY { +.MMM-soccer .name .IN_PLAY { color: yellow; } diff --git a/MMM-soccer.js b/MMM-soccer.js index a8518d4..a35ff45 100644 --- a/MMM-soccer.js +++ b/MMM-soccer.js @@ -44,22 +44,24 @@ Module.register('MMM-soccer', { colored: false, width: 400, show: ['BL1', 'CL', 'PL'], - updateInterval: 60 * 1000, + updateInterval: 60, + apiCallInterval: 10 * 60, focus_on: false, - fadeFocus: false, + fadeFocus: true, max_teams: false, logos: true, showTables: true, showMatches: true, - gameType: 'daily', - debug: true, - replace: { - 'BV Borussia 09 Dortmund': 'Borussia Dortmund', - '1. FC Union Berlin': 'Union Berlin', - 'TSV Fortuna 95 Düsseldorf': 'Fortuna Düsseldorf', - 'SC Paderborn 07': 'SC Paderborn', - 'Manchester City FC': 'Manchester City', + matchType: 'next', //choose 'next', 'daily', or 'league' + leagues: { + GERMANY: 'BL1', + FRANCE: 'FL1', + ENGLAND: 'PL', + SPAIN: 'PD', + ITALY: 'SA' }, + debug: false, + replace: 'default', //choose 'default', 'short' or '' for original names }, /** @@ -88,60 +90,77 @@ Module.register('MMM-soccer', { ] }, - /** - * @member {boolean} loading - Flag to indicate the loading state of the module. - */ loading: true, - /** - * @member {Object[]} tables - Stores the list of tables of current selected leagues. - * @member {Object[]} matches - Stores the list of matches of current selected leagues. - * @member {Object[]} teams - Stores infomration about all collected teams (important for logo). - */ tables: {}, matches: {}, teams: {}, - matchDay: "", - showTable: true, - /** - * @member {Object} competition - The currently selected league. - */ - competition: 'BL1', + matchDay: "", + showTable: true, + leagues: [], + liveMatches: [], + liveLeagues: [], + replacements: { + default: {} + }, + competition: '', + - /** - * @function start - * @description Adds nunjuck filters and requests for league data. - * @override - */ start: function() { Log.info(`Starting module: ${this.name}`); this.addFilters(); - this.competition = this.config.show[0]; - this.showTable = this.config.showTables; - this.getData(); - _this = this; + this.leagues = this.config.show; + this.competition = this.leagues[0]; + this.showTable = this.config.showTables; + var self = this; + this.replacers = this.loadReplacements(response => { + self.replacements = JSON.parse(response); + self.log(self.replacements); + }); + this.sendSocketNotification('GET_SOCCER_DATA', this.config); + this.scheduleDOMUpdates(); + }, + + + loadReplacements: function(callback) { + this.log("Loading replacements file"); + var xobj = new XMLHttpRequest(), + path = this.file('replacements.json'); + xobj.overrideMimeType("application/json"); + xobj.open("GET", path, true); + xobj.onreadystatechange = function() { + if (xobj.readyState === 4 && xobj.status === 200) { + callback(xobj.responseText); + } + }; + xobj.send(null); + }, + + + /** + * @function scheduleDOMUpdates + * @description Schedules updates for displaying leagues. + */ + scheduleDOMUpdates: function () { var count = 0; - const comps = this.config.show.length; + var _this = this; + const comps = this.leagues.length; setInterval(() => { count = (count === comps - 1) ? 0 : count + 1; - _this.competition = _this.config.show[count]; - this.log("Showing competition: "+_this.competition); + _this.competition = _this.leagues[count]; + _this.log("Showing competition: "+_this.competition); _this.standing = _this.filterTables(_this.tables[_this.competition], _this.config.focus_on[_this.competition]); _this.updateDom(800); - }, this.config.updateInterval); + }, this.config.updateInterval * 1000); }, - /** - * @function start - * @description Sends request to the node_helper to fetch data for the current selected league. - */ - getData: function() { - self = this; - //this.sendSocketNotification('GET_TODAYS_MATCHES', { leagues: this.config.show, api_key: this.config.api_key }); - this.sendSocketNotification('GET_TABLES', this.config); - this.sendSocketNotification('GET_MATCHES', this.config); - setInterval(() => { - self.sendSocketNotification('GET_MATCHES', this.config); - }, 60*1000); + + liveMode: function (isLive) { + if (isLive) { + //clearInterval(this.mainInterval); + this.log("Live Mode activated, main Interval stopped."); + } else { + this.scheduleAPICalls(); + } }, /** @@ -157,15 +176,21 @@ Module.register('MMM-soccer', { if (notification === 'TABLES') { this.tables = payload; this.standing = this.filterTables(this.tables[this.competition], this.config.focus_on[this.competition]); - this.log("Current table: "+this.standing); + this.log("Current table: "+this.standing); } else if (notification === 'MATCHES') { this.matches = payload; + //this.log(this.matches); } else if (notification === 'TEAMS') { this.teams = payload; + } else if (notification === 'LIVE_MATCHES') { + var matches = payload; + } else if (notification === 'LIVE') { + this.liveLeagues = payload.leagues; + this.liveMatches = payload.matches; } - if (this.tables.hasOwnProperty(this.competition) && this.matches.hasOwnProperty(this.competition)) { + if (this.loading === true && this.tables.hasOwnProperty(this.competition) && this.matches.hasOwnProperty(this.competition)) { this.loading = false; - this.updateDom(500); + this.updateDom(); } }, @@ -223,7 +248,7 @@ Module.register('MMM-soccer', { isModalActive: this.isModalActive(), modals: this.modals, table: this.standing, - matches: (Object.keys(this.matches).length > 0) ? this.prepareMatches(this.matches[this.competition].matches, this.config.focus_on[this.competition]) : "", + matches: (Object.keys(this.matches).length > 0) ? this.prepareMatches(this.matches, this.config.focus_on[this.competition]) : "", season: (Object.keys(this.tables).length > 0) ? `${this.translate('MATCHDAY')}: ${this.translate(this.matchDay)}` : this.translate('LOADING'), showTable: this.showTable, @@ -233,122 +258,65 @@ Module.register('MMM-soccer', { }, /** - * @function handleModals - * @description Hide/show modules based on voice commands. - */ - handleModals: function(data, modal, open, close) { - if (close.test(data) || (this.modals[modal] && !open.test(data))) { - this.closeAllModals(); - } else if (open.test(data) || (!this.modals[modal] && !close.test(data))) { - this.closeAllModals(); - this.modals[modal] = true; - } - - const modules = document.querySelectorAll('.module'); - for (let i = 0; i < modules.length; i += 1) { - if (!modules[i].classList.contains('MMM-soccer')) { - if (this.isModalActive()) { - modules[i].classList.add('MMM-soccer-blur'); - } else { - modules[i].classList.remove('MMM-soccer-blur'); - } - } - } - }, - - /** - * @function closeAllModals - * @description Close all modals of the module. - */ - closeAllModals: function() { - const modals = Object.keys(this.modals); - modals.forEach((modal) => { this.modals[modal] = false; }); - }, - - /** - * @function isModalActive - * @description Checks if at least one modal is active. + * @function prepareMatches + * @description Filters matches to show only one matchday. Also focuses on focused team(s) * - * @returns {boolean} Flag if there is an active modal. - */ - isModalActive: function() { - const modals = Object.keys(this.modals); - return modals.some(modal => this.modals[modal] === true); - }, - - /** - * @function checkCommands - * @description Voice command handler. + * @returns {Object} matches */ - checkCommands(data) { - if (/(HELP)/g.test(data)) { - this.handleModals(data, 'help', /(OPEN)/g, /(CLOSE)/g); - } else if (/(VIEW)/g.test(data)) { - this.handleModals(data, 'standings', /(EXPAND)/g, /(COLLAPSE)/g); - } else if (/(STANDINGS)/g.test(data)) { - const countrys = Object.keys(this.config.leagues); - for (let i = 0; i < countrys.length; i += 1) { - const regexp = new RegExp(countrys[i], 'g'); - if (regexp.test(data)) { - this.closeAllModals(); - if (this.currentLeague !== this.config.leagues[countrys[i]]) { - this.currentLeague = this.config.leagues[countrys[i]]; - this.getData(); - } - break; + prepareMatches: function(allMatches, focusTeam) { + if (this.config.matchType === "league") { + var diff = 0; + var matches = allMatches[this.competition]; + var minDiff = Math.abs(moment().diff(matches[0].utcDate)); + for (var m = 0; m < matches.length; m++) { + if (!matches[m].matchday) {matches[m].matchday = matches[m].stage; } //for cup modes, copy stage to matchday property + diff = Math.abs(moment().diff(matches[m].utcDate)); + if (diff < minDiff) { + minDiff = diff; + this.matchDay = matches[m].matchday; } } - } - this.updateDom(300); - }, - - /** - * @function isMaxTeamsLessAll - * @description Are there more entries than the config option specifies. - * - * @returns {boolean} - */ - isMaxTeamsLessAll() { - return (this.config.max_teams && this.config.max_teams <= this.standing.length); - }, - - - /** - * @function filterMatches - * @description Filters matches to show only one matchday. Also focuses on focused team - * - * @returns {Object} matches - */ - prepareMatches(matches, focusTeam) { - var diff = 0; - var minDiff = Math.abs(moment().diff(matches[0].utcDate)); - for (var m = 0; m < matches.length; m++) { - if (!matches[m].matchday) {matches[m].matchday = matches[m].stage; } //for cup modes, copy stage to matchday property - diff = Math.abs(moment().diff(matches[m].utcDate)); - if (diff < minDiff) { - minDiff = diff; - this.matchDay = matches[m].matchday; + this.log("Current matchday: "+this.matchDay); + this.showTable = (!isNaN(this.matchDay)); + + returnedMatches = matches.filter(match => { + return match.matchday == this.matchDay; + }); + } else if (this.config.matchType === "next") { + var teams = []; + var nextMatches = []; + for (var comp in this.config.focus_on) { + teams.push(this.config.focus_on[comp]); + } + for (var league in allMatches) { + filteredMatches = allMatches[league].matches.filter(match => { + return (teams.includes(match.homeTeam.name) || teams.includes(match.awayTeam.name)); + }); + var index = filteredMatches.findIndex(match => { + return (moment(match.utcDate) > moment()); + }); + for (var i = index - 1; i < filteredMatches.length; i++) { + nextMatches.push(filteredMatches[i]); + } } + nextMatches.sort(function (match1, match2) { + return (moment(match1.utcDate) - moment(match2.utcDate)); + }); + returnedMatches = nextMatches.slice(0, 5 * teams.length); } - this.log("Current matchday: "+this.matchDay); - this.showTable = (!isNaN(this.matchDay)) - - - matches = matches.filter(match => { - return match.matchday == this.matchDay; - }); - matches.forEach(match => { + returnedMatches.forEach(match => { match.focused = (match.homeTeam.name === focusTeam) ? true : (match.awayTeam.name === focusTeam) ? true : false; - if (match.status == "SCHEDULED") { - match.state = (moment(match.utcDate).diff(moment(), 'days') > 7) ? moment(match.utcDate).format("D.MM") : (moment(match.utcDate).diff(moment(), 'hours') > 23) ? moment(match.utcDate).format("dd") : moment(match.utcDate).format("LT"); + if (match.status == "SCHEDULED" || match.status == "POSTPONED") { + match.state = (moment(match.utcDate).diff(moment(), 'days') > 7) ? moment(match.utcDate).format("D.MM.") : (moment(match.utcDate).startOf('day') > moment()) ? moment(match.utcDate).format("dd") : moment(match.utcDate).format("LT"); } else { match.state = match.score.fullTime.homeTeam + " - " + match.score.fullTime.awayTeam; } }); //this.log(matches); - return matches; + return returnedMatches; }, + /** * @function filterTables * @description Filters tables to show one table per competition. For leagues mode "home" and "away" tables are filtered out. @@ -356,8 +324,9 @@ Module.register('MMM-soccer', { * * @returns {Object} Object including current matchday and array of teams. */ - filterTables(tables, focusTeam) { + filterTables: function(tables, focusTeam) { //filtering out "home" and "away" tables + if (!tables.standings) return ""; tableArray = tables.standings.filter(table => { return table.type === "TOTAL"; }); @@ -381,7 +350,7 @@ Module.register('MMM-soccer', { * * @returns {Object} Index of team, first and last team to display. */ - findFocusTeam() { + findFocusTeam: function() { this.log("Finding focus team for table..."); let focusTeamIndex; var table = this.standing; @@ -412,7 +381,7 @@ Module.register('MMM-soccer', { * * @returns {Object} Index of the first and the last team. */ - getFirstAndLastTeam(index) { + getFirstAndLastTeam: function(index) { let firstTeam; let lastTeam; @@ -449,7 +418,7 @@ Module.register('MMM-soccer', { firstTeam: 0, lastTeam: this.isMaxTeamsLessAll() ? this.config.max_teams : this.standing.length }; - } else if (this.config.focus_on[this.config.show] === 'BOTTOM') { + } else if (this.config.focus_on[this.leagues] === 'BOTTOM') { this.log("Focus on BOTTOM"); return { focusTeamIndex: -1, @@ -457,7 +426,7 @@ Module.register('MMM-soccer', { lastTeam: this.standing.length }; } - this.log("Focus on Team"); + this.log("Focus on Team"); return this.findFocusTeam(); } @@ -468,11 +437,91 @@ Module.register('MMM-soccer', { }; }, + /** + * @function isMaxTeamsLessAll + * @description Are there more entries than the config option specifies. + * + * @returns {boolean} + */ + isMaxTeamsLessAll: function() { + return (this.config.max_teams && this.config.max_teams <= this.standing.length); + }, + + /** + * @function handleModals + * @description Hide/show modules based on voice commands. + */ + handleModals: function(data, modal, open, close) { + if (close.test(data) || (this.modals[modal] && !open.test(data))) { + this.closeAllModals(); + } else if (open.test(data) || (!this.modals[modal] && !close.test(data))) { + this.closeAllModals(); + this.modals[modal] = true; + } + + const modules = document.querySelectorAll('.module'); + for (let i = 0; i < modules.length; i += 1) { + if (!modules[i].classList.contains('MMM-soccer')) { + if (this.isModalActive()) { + modules[i].classList.add('MMM-soccer-blur'); + } else { + modules[i].classList.remove('MMM-soccer-blur'); + } + } + } + }, + + /** + * @function closeAllModals + * @description Close all modals of the module. + */ + closeAllModals: function() { + const modals = Object.keys(this.modals); + modals.forEach((modal) => { this.modals[modal] = false; }); + }, + + /** + * @function isModalActive + * @description Checks if at least one modal is active. + * + * @returns {boolean} Flag if there is an active modal. + */ + isModalActive: function() { + const modals = Object.keys(this.modals); + return modals.some(modal => this.modals[modal] === true); + }, + + /** + * @function checkCommands + * @description Voice command handler. + */ + checkCommands: function(data) { + if (/(HELP)/g.test(data)) { + this.handleModals(data, 'help', /(OPEN)/g, /(CLOSE)/g); + } else if (/(VIEW)/g.test(data)) { + this.handleModals(data, 'standings', /(EXPAND)/g, /(COLLAPSE)/g); + } else if (/(STANDINGS)/g.test(data)) { + const countrys = Object.keys(this.config.leagues); + for (let i = 0; i < countrys.length; i += 1) { + const regexp = new RegExp(countrys[i], 'g'); + if (regexp.test(data)) { + this.closeAllModals(); + if (this.currentLeague !== this.config.leagues[countrys[i]]) { + this.currentLeague = this.config.leagues[countrys[i]]; + this.getData(); + } + break; + } + } + } + this.updateDom(300); + }, + /** * @function addFilters * @description Adds the filter used by the nunjuck template. */ - addFilters() { + addFilters: function () { njEnv = this.nunjucksEnvironment(); njEnv.addFilter('fade', (index, focus) => { if (this.config.max_teams && this.config.fadeFocus && focus >= 0) { @@ -481,19 +530,19 @@ Module.register('MMM-soccer', { return `opacity: ${1 - ((1 / this.config.max_teams) * currentStep)}`; } } - return ''; }); njEnv.addFilter('replace', (team) => { - if (this.config.replace.hasOwnProperty(team)) { - return this.config.replace[team]; + var replace = this.config.replace; + if ((replace == 'default' || replace == 'short') && (this.replacements.default.hasOwnProperty(team))) { + return this.replacements[replace][team]; } else { return team; } }); }, - + log: function (msg) { if (this.config && this.config.debug) { console.log(this.name + ":", JSON.stringify(msg)); diff --git a/MMM-soccer.njk b/MMM-soccer.njk index f0c6de9..b1cf872 100644 --- a/MMM-soccer.njk +++ b/MMM-soccer.njk @@ -2,23 +2,24 @@ {% if loading %} {{'LOADING' | translate}} {% else %} -

{{competitionName}}
-
{{season}}
+
{{this.name}}
+
{{competitionName}}
+
{{season}}
{% if config.showMatches %}
{% for i in range(0, matches.length) %} - - + + {% if config.logos %} {% endif %} - {% if config.logos %} {% endif %} - + {% endfor %} diff --git a/README.md b/README.md index 5af2afd..8604e16 100644 --- a/README.md +++ b/README.md @@ -23,11 +23,19 @@ A Soccer Standings Module for MagicMirror², based on @fewiedens [MMM-soccer](ht ``` { module: 'MMM-soccer', - position: 'bottom_left', + position: 'top_left', config: { - ... + api_key: '', + show: ['CL', 'BL1', 'PL'], + colored: true, + updateInterval: 60, + focus_on: { + null + }, + max_teams: 5, + matchType: 'league' } - } + }, ``` @@ -43,41 +51,49 @@ A Soccer Standings Module for MagicMirror², based on @fewiedens [MMM-soccer](ht | `colored` | true | Boolean to show club logos in color or not. | | `show` | ['BL1', 'PL', 'CL'] | An array of league codes to be displayed. In normal mode, the leagues revolve using below update cycle. With activated touch mode (see below), you can choose one of the leagues via a button (planned) | | `updateInterval` | 60 | The time frame for each league to be shown in seconds. | +| `apiCallInterval` | 10 | The time frame for API calls in normal mode. | | `showMatches` | true | Show matches of current league | | `showTables` | true | Show table of current league. *Remark*: For cups like Champions league, this will be set to false in knockout mode. | | `focus_on` | null | Which team should to focus on per league. This needs to be an object, e.g. {'BL1': 'FC Bayern München', 'CL': 'Liverpool FC'}. See description below. | +| `fadeFocus` | true | Includes fading the teams out if one is focused. | | `max_teams` | false | How many teams should be displayed when focus is activated. Omit this option or set to false to show the full league table. | +| `replace` | 'default' | Choose between 'default' for a default replacement of original club names or 'short' for a 3-Letter-Code of the teams. Choose anything else (like '') for original team names from the API. See below for further information | | `logos` | true | Boolean to show club logos. | | `liveMode` | true | Activates live mode when games are in play. (see below, not active yet) | +| `matchType` | 'league' | Choose between the following: 'league' for showing the current matchday of selected leagues (in `show`), 'next' for showing the next matches of all your focused clubs (in `focus_on`), 'daily' for showing all of todays matches for selected leagues. | | `touchMode` | false | Activates touch mode with touch options (see below, not active yet) | | `debug` | false | Debug mode: additional output on server side (console) and client side (browser) | ## Focus -You can focus on one time per league/cup using the focus_on method. This variable needs to be an object. +You can focus on one time per league/cup using the focus_on method. This variable needs to be an object. An example is below: ``` -{'BL1': 'FC Bayern München', 'CL': 'Liverpool FC'} +focus_on: { + 'BL1': 'FC Bayern München', + 'CL': 'Liverpool FC' +}, ``` -Please take care to include all quotation marks, separate with commata, and use the same league codes (find below) you have included in the 'show' array. - -The team name needs to correspond to the original name of the team as provided by the API. +Please take care to include all quotation marks, separate with commata, and use the same league codes (find below) you have included in the 'show' array. +The team name needs to correspond to the original name of the team as provided by the API. Have a look into the ```replace``` object in the config to see if the team name is replaced with a shorter one on the mirror. If that is the case, take the original one (the one on the left for each replace property). Omitting a league code from 'show' in this array will show the full league table and not include any focus. Any league included here need to be included in 'show' as well to show the league on your mirror. +##replacements +There is a `replacements.json` file in the directory including all teams of the free plan. By default, the default replacement for the original team name will be used in the module. YOu can choose between 'default' mode or 'short' mode showing the 3-letter ID code for the team for a super slim module. -## Live Mode (planned) +## Live Mode -The modules calls all requested matches every 5 minutes. Whenever one or more matches are scheduled in less than 5 minutes, a Live Mode will activate. +The module calls all requested matches every X minutes (see config option apiCallInterval). Whenever one or more matches are scheduled in less than this interval, a Live Mode will activate. All matches currently played will be included in an array and requested for updates as regularly as the free api (10 calls per minute) allows. -Additional informations like game minute and scorers will be provided for these games. -Also, only the leagues with current matches will be shown (does not count for touch mode) -When no game is active, the module will return back to normal mode. +~Additional informations like game minute and scorers will be provided for these games.~ (another API is needed for this) +Also, only the leagues with current matches will be shown (not in touch mode) +When no game is active, the module will return back to normal mode. -Can be switched off in config +Can be switched off in config. ## Touch mode (planned) @@ -85,10 +101,10 @@ Can be switched off in config Touch mode will create buttons to choose between leagues. It is also planned to include more detailed information like scorers per league and scorers per game. -Can be switched off in config +Can be switched off in config. -## OPTIONAL: Voice Control +## OPTIONAL: Voice Control (may be buggy!) This module supports voice control by @fewiedens [MMM-voice](https://github.com/fewieden/MMM-voice). In order to use this feature, it's required to install the voice module. There are no extra config options for voice control needed. @@ -121,7 +137,7 @@ As per the [Football-data API Docs](https://www.football-data.org/documentation/ | (English) Premier League | 'PL' | | (English) Championship | 'ELC' | | (German) Bundesliga | 'BL1' | -| (Italian) Serie A | 'PD' | +| (Italian) Serie A | 'SA' | | (French) Ligue 1 | 'FL1' | | (Spain) La Liga | 'PD' | | (Portugal) Primiera Liga | 'PPL' | @@ -131,12 +147,14 @@ As per the [Football-data API Docs](https://www.football-data.org/documentation/ ### TODOs -- [ ] Include live mode -- [ ] Include option to replace team names with 3-letter-codes (very slim module) -- [ ] Include option to show scorers for each match - [ ] Current top scorer list per league - [ ] Touch mode - [ ] Tap additional API (presumably API-football) for further competitions (e.g. DFB cup) -Add team specific data, e.g. +- [ ] Option to show fixed table head with focus on. +- [ ] Highlight currently playing teams in table. + + +Add team specific data, e.g. - [ ] next matches -- [ ] current squad / line-up +- [ ] ~current squad / line-up~ not available in free plan! +- [ ] ~Include option to show scorers for each match~ not available in free plan! diff --git a/node_helper.js b/node_helper.js index 650785b..aedd082 100644 --- a/node_helper.js +++ b/node_helper.js @@ -13,6 +13,7 @@ const axios = require('axios'); const NodeHelper = require('node_helper'); +const moment = require('moment'); /** * @module node_helper @@ -26,6 +27,9 @@ module.exports = NodeHelper.create({ matches: {}, tables: {}, teams: {}, + teamList: {}, + liveMatches: [], + liveLeagues: [], start() { console.log(`Starting module: ${this.name}`); @@ -44,29 +48,42 @@ module.exports = NodeHelper.create({ this.headers = payload.api_key ? { 'X-Auth-Token': payload.api_key } : {}; this.config = payload; self = this; - /*this.options = { - standings: { - url: `http://api.football-data.org/v2/competitions/${payload.league}/standings`, - headers: payload.api_key ? { 'X-Auth-Token': payload.api_key } : {} - }, - compMatches: { - url: `http://api.football-data.org/v2/competitions/${payload.league}/matches`, - headers: payload.api_key ? { 'X-Auth-Token': payload.api_key } : {} - }, - matches: { - url: `http://api.football-data.org/v2/matches/`, - headers: payload.api_key ? { 'X-Auth-Token': payload.api_key } : {} - }, - - };*/ + if (notification === 'GET_SOCCER_DATA') { + this.config = payload; + this.scheduleAPICalls(false); + } + }, - if (notification === 'GET_TABLES') { - this.getTables(payload.show); - } else if (notification === 'GET_MATCHES') { - this.getMatches(payload.show); - } /*else if (notification === 'GET_TODAYS_MATCHES') { - this.getMatches(this.options.currentMatches, payload.show); - }*/ + /** + * @function scheduleAPICalls + * @description Sends request to the node_helper to fetch data for the current selected leagues. + */ + scheduleAPICalls: function(live) { + this.getTables(this.config.show); + this.getMatches(this.config.show); + var self = this; + if (live === false) { + this.mainInterval = setInterval(() => { + if (self.liveMatches.length > 0) { + self.toggleLiveMode(true); + } else { + self.getTables(self.config.show); + //self.getMatches(self.config.show); + } + }, this.config.apiCallInterval * 1000); + } else { + var liveUpdateInterval = Math.max(Math.floor(10/(this.liveLeagues.length * 2)), 1) * 1000; + console.log("Live update interval: "+liveUpdateInterval); + this.liveInterval = setInterval(() => { + if (self.liveMatches.length == 0) { + self.toggleLiveMode(false); + } else { + //self.getTables(self.config.show); + //self.getMatches(self.config.show); + //self.getMatchDetails(self.liveMatches); + } + }, liveUpdateInterval); + } }, /** @@ -84,31 +101,34 @@ module.exports = NodeHelper.create({ return axios.get(url, { headers: self.headers }) .then(function (response) { var tableData = response.data; - var tables = { - competition: tableData.competition, - season: tableData.season, - standings: tableData.standings, - }; - //this.log(tables); - return(tables); - }) - .catch(function (err) { - console.log(`Error fetching league table for url ${url}: ${err}`); - return ""; - }); - })) + var tables = { + competition: tableData.competition, + season: tableData.season, + standings: tableData.standings, + }; + //self.log(tables); + return(tables); + }) + .catch(function (error) { + self.handleErrors(error, url); + return {}; + }); + })) .then(function(tableArray) { tableArray.forEach(tables => { - tables.standings.forEach(standing => { - standing.table.forEach(team => { - self.teams[team.team.id] = team.team; + if (tables.hasOwnProperty('standings')) { + tables.standings.forEach(standing => { + standing.table.forEach(team => { + self.teams[team.team.id] = team.team; + self.teamList[team.team.name] = team.team.name; + }); }); - }); - self.tables[tables.competition.code] = tables; + self.tables[tables.competition.code] = tables; + } }); - //this.log("Collected tables: "+self.tables); - this.log("Collected Teams: "+self.teams); - //this.log("TableArray: "tableArray); + //self.log("Collected Tables: " + self.tables); + //self.log("Collected Teams: " + JSON.stringify(self.teams)); + //self.log("TableArray: " + tableArray); self.sendSocketNotification("TABLES", self.tables); self.sendSocketNotification("TEAMS", self.teams); }); @@ -116,35 +136,105 @@ module.exports = NodeHelper.create({ getMatches(leagues) { self = this; - console.log("Collecting matches for leagues: "+leagues); + this.log("Collecting matches for leagues: "+leagues); var urlArray = leagues.map(league => { return `http://api.football-data.org/v2/competitions/${league}/matches`; }); Promise.all(urlArray.map(url => { - return axios.get(url, { headers: self.headers }) + return axios.get(url, { headers: self.headers }) .then(function (response) { var matchesData = response.data; var league = matchesData.competition.code; matchesData.matches.forEach(match => { delete match.referees; - //match.focused = (match.homeTeam.name === self.config.focus_on[league]) ? true : (match.awayTeam.name === self.config.focus_on[league]) ? true : false; + //check for live matches + if (moment(match.utcDate).add(90, 'minutes').diff(moment()) > 0 && moment(match.utcDate).diff(moment(), 'seconds') < self.config.apiCallInterval) { + if (self.liveMatches.indexOf(match.id) === -1) { + console.log(`Live match detected starting at ${moment(match.utcDate).format("HH:mm")}, Home Team: ${match.homeTeam.name}`); + self.liveMatches.push(match.id); + } + if (self.liveLeagues.indexOf(league) === -1) { + self.log(`Live league ${league} added at ${moment().format("HH:mm")}`); + self.liveLeagues.push(league); + } + } }); - //this.log(matchesData); return(matchesData); }) - .catch(function (err) { - console.log(`Error fetching matches with url ${url}: ${err}`); - return ""; + .catch(function (error) { + self.handleErrors(error, url); + return {}; }); })) .then(function (matchesArray) { matchesArray.forEach(comp => { - self.matches[comp.competition.code] = comp; + if (comp.hasOwnProperty('competition')) { + self.matches[comp.competition.code] = comp; + } }); - //this.log("Collected Matches: "+self.matches); + //self.log("Collected Matches: "+self.matches); + self.log("Live matches: "+JSON.stringify(self.liveMatches)); self.sendSocketNotification("MATCHES", self.matches); }); }, - - log: function (msg) { + + + getMatchDetails(matches) { + self = this; + this.log("Getting match details for matches: " + matches); + var urlArray = matches.map(match => { return `http://api.football-data.org/v2/matches/${match}`; }); + Promise.all(urlArray.map(url => { + return axios.get(url, { headers: self.headers }) + .then(function (response) { + var matchData = response.data; + self.log(matchData); + if (matchData.match.status != "IN_PLAY" && self.liveMatches.indexOf(matchData.match.id)!= -1) { + self.log("Live match finished"); + self.liveMatches.splice(self.liveMatches.indexOf(comp.matches[m].id), 1); + self.log("Live matches: "+self.liveMatches); + } + return(matchData); + }) + .catch(function (error) { + self.handleErrors(error, url); + return {}; + }); + })) + .then(function (liveMatchesArray) { + /*LiveMatchesArray.forEach(match => { + liveMatches[match.match.competition.id] = match; + });*/ + self.sendSocketNotification("LIVE_MATCHES", liveMatchesArray); + }); + }, + + handleErrors: function(error, url) { + console.log("An error occured while requesting the API for Data:"); + console.log("URL: "+url); + if (error.response.status === 429) { + console.log(error.response.status + ": API Request Quota of 10 calls per minute exceeded. Try selecting less leagues."); + } else if (error.request) { + console.log(error.request); + } else { + // Something happened in setting up the request that triggered an Error + console.log('Error ', error.message); + } + }, + + toggleLiveMode: function (isLive) { + if (isLive) { + clearInterval(this.mainInterval); + this.log("Live Mode activated, main interval stopped."); + this.sendSocketNotification("LIVE", { matches: this.liveMatches, leagues: this.liveLeagues }); + this.scheduleAPICalls(true); + } else { + clearInterval(this.liveInterval); + this.log("Live Mode deactivated, back to main interval."); + this.sendSocketNotification("LIVE", { matches: this.liveMatches, leagues: this.liveLeagues }); + this.scheduleAPICalls(false); + } + }, + + + log: function (msg) { if (this.config && this.config.debug) { console.log(this.name + ":", JSON.stringify(msg)); } diff --git a/package.json b/package.json index 8c2f01f..6ac9b48 100644 --- a/package.json +++ b/package.json @@ -1,21 +1,24 @@ { - "name": "mmm-soccer", - "version": "1.0.1", + "name": "mmm-soccer v2", + "version": "1.0.0", "description": "European Soccer Standings Module for MagicMirror2", "repository": { "type": "git", - "url": "git+https://github.com/fewieden/MMM-soccer.git" + "url": "git+https://github.com/lavolp3/MMM-soccer.git" }, "keywords": [ "MagicMirror", - "soccer standings" + "soccer standings", + "soccer", + "tables" + "football" ], - "author": "fewieden", + "author": "lavolp3", "license": "MIT", "bugs": { - "url": "https://github.com/fewieden/MMM-soccer/issues" + "url": "https://github.com/lavolp3/MMM-soccer/issues" }, - "homepage": "https://github.com/fewieden/MMM-soccer#readme", + "homepage": "https://github.com/lavolp3/MMM-soccer#readme", "scripts": { "lint": "./node_modules/.bin/eslint . && ./node_modules/.bin/stylelint .", "docs": "./node_modules/.bin/jsdoc -c jsdoc.json ." diff --git a/replacements.json b/replacements.json new file mode 100644 index 0000000..2431790 --- /dev/null +++ b/replacements.json @@ -0,0 +1,344 @@ +{ + "default": { + "Paris Saint-Germain FC":"Paris Saint-Germain", + "Real Madrid CF":"Real Madrid", + "Club Brugge KV":"Club Brugge", + "Galatasaray SK":"Galatasaray", + "FC Bayern München":"Bayern München", + "Tottenham Hotspur FC":"Tottenham Hotspur", + "PAE Olympiakos SFP":"Olympiakos Piräus", + "FK Crvena Zvezda":"Roter Stern Belgrad", + "Manchester City FC":"Manchester City", + "Atalanta BC":"Atalanta BC", + "FK Shakhtar Donetsk":"Shakhtar Donetsk", + "GNK Dinamo Zagreb":"Dinamo Zagreb", + "Juventus FC":"Juventus FC", + "Club Atlético de Madrid":"Athletico Madrid", + "Bayer 04 Leverkusen":"Bayer Leverkusen", + "FK Lokomotiv Moskva":"Lokomotive Moskva", + "Liverpool FC":"Liverpool", + "SSC Napoli":"SSC Napoli", + "FC Red Bull Salzburg":"Red Bull Salzburg", + "KRC Genk":"KRC Genk", + "FC Barcelona":"Barcelona", + "BV Borussia 09 Dortmund":"Borussia Dortmund", + "FC Internazionale Milano":"Inter Mailand", + "SK Slavia Praha":"Slavia Prag", + "RB Leipzig":"RB Leipzig", + "Olympique Lyonnais":"Olympique Lyon", + "Sport Lisboa e Benfica":"Benfica Lissabon", + "FK Zenit Sankt-Petersburg":"Zenit Sankt-Petersburg", + "Valencia CF":"Valencia", + "Chelsea FC":"Chelsea", + "AFC Ajax":"Ajax Amsterdam", + "Lille OSC":"Lille OSC", + "Borussia Mönchengladbach":"Bor Mönchengladbach", + "FC Schalke 04":"FC Schalke 04", + "VfL Wolfsburg":"VfL Wolfsburg", + "TSG 1899 Hoffenheim":"1899 Hoffenheim", + "SC Freiburg":"SC Freiburg", + "1. FC Union Berlin":"Union Berlin", + "Eintracht Frankfurt":"Eintracht Frankfurt", + "FC Augsburg":"FC Augsburg", + "1. FC Köln":"1. FC Köln", + "Hertha BSC":"Hertha BSC", + "1. FSV Mainz 05":"FSV Mainz", + "TSV Fortuna 95 Düsseldorf":"Fortuna Düsseldorf", + "SV Werder Bremen":"Werder Bremen", + "SC Paderborn 07":"SC Paderborn", + "Leicester City FC":"Leicester City", + "Manchester United FC":"Manchester United", + "Sheffield United FC":"Sheffield United", + "Wolverhampton Wanderers FC":"Wolverhampton Wanderers", + "Arsenal FC":"Arsenal London", + "Burnley FC":"Burnley", + "Everton FC":"Everton", + "Southampton FC":"Southampton", + "Crystal Palace FC":"Crystal Palace", + "Newcastle United FC":"Newcastle United", + "Brighton & Hove Albion FC":"Brighton & Hove Albion", + "AFC Bournemouth":"Bournemouth", + "Aston Villa FC":"Aston Villa", + "West Ham United FC":"West Ham United", + "Watford FC":"Watford", + "Norwich City FC":"Norwich City", + "West Bromwich Albion FC":"West Bromwich Albion", + "Leeds United AFC":"Leeds United", + "Nottingham Forest FC":"Nottingham Forest", + "Fulham FC":"Fulham", + "Brentford FC":"Brentford", + "Preston North End FC":"Preston North End", + "Bristol City FC":"Bristol City", + "Blackburn Rovers FC":"Blackburn Rovers", + "Swansea City AFC":"Swansea City", + "Cardiff City FC":"Cardiff City", + "Millwall FC":"Millwall", + "Queens Park Rangers FC":"Queens Park Rangers", + "Sheffield Wednesday FC":"Sheffield Wednesday", + "Derby County FC":"Derby County", + "Birmingham City FC":"Birmingham City", + "Reading FC":"Reading", + "Hull City AFC":"Hull City", + "Charlton Athletic FC":"Charlton Athletic", + "Huddersfield Town AFC":"Huddersfield Town", + "Stoke City FC":"Stoke City", + "Middlesbrough FC":"Middlesbrough", + "Wigan Athletic FC":"Wigan Athletic", + "Luton Town FC":"Luton Town", + "Barnsley FC":"Barnsley FC", + "SS Lazio":"Lazio Rom", + "AS Roma":"AS Rom", + "AC Milan":"AC Mailand", + "Hellas Verona FC":"Hellas Verona", + "Parma Calcio 1913":"Parma Calcio", + "Bologna FC 1909":"Bologna FC", + "Cagliari Calcio":"Cagliari Calcio", + "ACF Fiorentina":"ACF Fiorentina", + "US Sassuolo Calcio":"Sassuolo Calcio", + "Udinese Calcio":"Udinese Calcio", + "Torino FC":"FC Turin", + "US Lecce":"US Lecce", + "UC Sampdoria":"UC Sampdoria", + "Genoa CFC":"Genoa CFC", + "Brescia Calcio":"Brescia Calcio", + "SPAL 2013":"SPAL 2013", + "Olympique de Marseille":"Olympique Marseille", + "Stade Rennais FC 1901":"Stade Rennais", + "AS Monaco FC":"AS Monaco", + "RC Strasbourg Alsace":"Strasbourg Alsace", + "Stade de Reims":"Stade de Reims", + "Montpellier HSC":"Montpellier HSC", + "OGC Nice":"OGC Nice", + "FC Nantes":"FC Nantes", + "FC Girondins de Bordeaux":"Girondins de Bordeaux", + "Stade Brestois 29":"Stade Brestois", + "Angers SCO":"Angers SCO", + "AS Saint-Étienne":"Saint-Étienne", + "FC Metz":"FC Metz", + "Dijon Football Côte d'Or":"FCO Dijon", + "Nîmes Olympique":"Olympique Nîmes", + "Amiens SC":"Amiens SC", + "Toulouse FC":"Toulouse FC", + "Sevilla FC":"Sevilla FC", + "Getafe CF":"Getafe CF", + "Real Sociedad de Fútbol":"Real Sociedad", + "Villarreal CF":"Villarreal CF", + "Granada CF":"Granada CF", + "Levante UD":"Levante UD", + "Athletic Club":"Athletico Bilbao", + "CA Osasuna":"CA Osasuna", + "Real Betis Balompié":"Betis Sevilla", + "Deportivo Alavés":"Deportivo Alavés", + "Real Valladolid CF":"Real Valladolid", + "SD Eibar":"SD Eibar", + "RC Celta de Vigo":"Celta de Vigo", + "RCD Mallorca":"RCD Mallorca", + "CD Leganés":"CD Leganés", + "RCD Espanyol de Barcelona":"Espanyol de Barcelona", + "FC Porto":"FC Porto", + "Sporting Clube de Braga":"Sporting Braga", + "Sporting Clube de Portugal":"Sporting Lissabon", + "Rio Ave FC":"Rio Ave FC", + "FC Famalicão":"FC Famalicão", + "Vitória SC":"Vitória SC", + "CD Santa Clara":"CD Santa Clara", + "Boavista FC":"Boavista FC", + "Moreirense FC":"Moreirense FC", + "Gil Vicente FC":"Gil Vicente FC", + "Vitória FC":"Vitória FC", + "Os Belenenses Futebol":"Os Belenenses Futebol", + "CD Tondela":"CD Tondela", + "CS Marítimo":"CS Marítimo", + "FC Paços de Ferreira":"FC Paços de Ferreira", + "Portimonense SC":"Portimonense SC", + "CD Aves":"CD Aves", + "AZ":"AZ Alkmaar", + "Feyenoord Rotterdam":"Feyenoord Rotterdam", + "PSV":"PSV Eindhoven", + "Willem II Tilburg":"Willem II Tilburg", + "FC Utrecht":"FC Utrecht", + "SBV Vitesse":"Vitesse Arnhem", + "FC Groningen":"FC Groningen", + "Heracles Almelo":"Heracles Almelo", + "SC Heerenveen":"SC Heerenveen", + "Sparta Rotterdam":"Sparta Rotterdam", + "FC Emmen":"FC Emmen", + "FC Twente '65":"FC Twente", + "VVV Venlo":"VVV Venlo", + "Fortuna Sittard":"Fortuna Sittard", + "PEC Zwolle":"PEC Zwolle", + "ADO Den Haag":"ADO Den Haag", + "RKC Waalwijk":"RKC Waalwijk" + }, + "short": { + "Paris Saint-Germain FC":"PSG", + "Real Madrid CF":"MAD", + "Club Brugge KV":"BRU", + "Galatasaray SK":"GAL", + "FC Bayern München":"BAY", + "Tottenham Hotspur FC":"TOT", + "PAE Olympiakos SFP":"OLY", + "FK Crvena Zvezda":"RSB", + "Manchester City FC":"MCI", + "Atalanta BC":"ATT", + "FK Shakhtar Donetsk":"SHK", + "GNK Dinamo Zagreb":"DZA", + "Juventus FC":"JUV", + "Club Atlético de Madrid":"ATM", + "Bayer 04 Leverkusen":"B04", + "FK Lokomotiv Moskva":"LMO", + "Liverpool FC":"LIV", + "SSC Napoli":"NAP", + "FC Red Bull Salzburg":"RBS", + "KRC Genk":"KRC Genk", + "FC Barcelona":"FCB", + "BV Borussia 09 Dortmund":"BVB", + "FC Internazionale Milano":"INT", + "SK Slavia Praha":"SLP", + "RB Leipzig":"RBL", + "Olympique Lyonnais":"LYO", + "Sport Lisboa e Benfica":"SLB", + "FK Zenit Sankt-Petersburg":"ZSP", + "Valencia CF":"VAL", + "Chelsea FC":"CHE", + "AFC Ajax":"AJA", + "Lille OSC":"LIL", + "Borussia Mönchengladbach":"BMG", + "FC Schalke 04":"S04", + "VfL Wolfsburg":"WOB", + "TSG 1899 Hoffenheim":"TSG", + "SC Freiburg":"SCF", + "1. FC Union Berlin":"UNB", + "Eintracht Frankfurt":"SGE", + "FC Augsburg":"AUG", + "1. FC Köln":"CGN", + "Hertha BSC":"BSC", + "1. FSV Mainz 05":"MAI", + "TSV Fortuna 95 Düsseldorf":"DUS", + "SV Werder Bremen":"SVW", + "SC Paderborn 07":"SCP", + "Leicester City FC":"LEI", + "Manchester United FC":"MUN", + "Sheffield United FC":"SHU", + "Wolverhampton Wanderers FC":"WLV", + "Arsenal FC":"ARS", + "Burnley FC":"BUR", + "Everton FC":"EVE", + "Southampton FC":"SOU", + "Crystal Palace FC":"CRY", + "Newcastle United FC":"NEW", + "Brighton & Hove Albion FC":"BRH", + "AFC Bournemouth":"BOU", + "Aston Villa FC":"AVA", + "West Ham United FC":"WHU", + "Watford FC":"WAT", + "Norwich City FC":"NOR", + "West Bromwich Albion FC":"WBA", + "Leeds United AFC":"LEE", + "Nottingham Forest FC":"NTG", + "Fulham FC":"FUL", + "Brentford FC":"BRE", + "Preston North End FC":"PNE", + "Bristol City FC":"BSC", + "Blackburn Rovers FC":"BBR", + "Swansea City AFC":"SWA", + "Cardiff City FC":"CDF", + "Millwall FC":"MLW", + "Queens Park Rangers FC":"QPR", + "Sheffield Wednesday FC":"SHF", + "Derby County FC":"DRB", + "Birmingham City FC":"BRC", + "Reading FC":"RDG", + "Hull City AFC":"HUL", + "Charlton Athletic FC":"CHA", + "Huddersfield Town AFC":"HDD", + "Stoke City FC":"STK", + "Middlesbrough FC":"MID", + "Wigan Athletic FC":"WIG", + "Luton Town FC":"LUT", + "Barnsley FC":"BRS", + "SS Lazio":"LAZ", + "AS Roma":"ROM", + "AC Milan":"MIL", + "Hellas Verona FC":"HEL", + "Parma Calcio 1913":"PRM", + "Bologna FC 1909":"BGN", + "Cagliari Calcio":"CAG", + "ACF Fiorentina":"FIO", + "US Sassuolo Calcio":"SAS", + "Udinese Calcio":"UDI", + "Torino FC":"TOR", + "US Lecce":"LEC", + "UC Sampdoria":"SAM", + "Genoa CFC":"GEN", + "Brescia Calcio":"BCA", + "SPAL 2013":"SPA", + "Olympique de Marseille":"OLM", + "Stade Rennais FC 1901":"REN", + "AS Monaco FC":"AMO", + "RC Strasbourg Alsace":"STR", + "Stade de Reims":"REI", + "Montpellier HSC":"MPL", + "OGC Nice":"NCE", + "FC Nantes":"NAN", + "FC Girondins de Bordeaux":"BOR", + "Stade Brestois 29":"B29", + "Angers SCO":"ANG", + "AS Saint-Étienne":"STE", + "FC Metz":"MTZ", + "Dijon Football Côte d'Or":"DIJ", + "Nîmes Olympique":"NIM", + "Amiens SC":"AMI", + "Toulouse FC":"TOU", + "Sevilla FC":"SEV", + "Getafe CF":"GET", + "Real Sociedad de Fútbol":"SOC", + "Villarreal CF":"VIL", + "Granada CF":"GCF", + "Levante UD":"LVT", + "Athletic Club":"ATB", + "CA Osasuna":"OSA", + "Real Betis Balompié":"SEV", + "Deportivo Alavés":"ALV", + "Real Valladolid CF":"REV", + "SD Eibar":"EIB", + "RC Celta de Vigo":"CLV", + "RCD Mallorca":"RCD", + "CD Leganés":"LEG", + "RCD Espanyol de Barcelona":"ESY", + "FC Porto":"POR", + "Sporting Clube de Braga":"SBR", + "Sporting Clube de Portugal":"SLI", + "Rio Ave FC":"RIO", + "FC Famalicão":"FAM", + "Vitória SC":"VDG", + "CD Santa Clara":"SCL", + "Boavista FC":"BOA", + "Moreirense FC":"MOE", + "Gil Vicente FC":"GVI", + "Vitória FC":"SET", + "Os Belenenses Futebol":"BLN", + "CD Tondela":"TND", + "CS Marítimo":"MTI", + "FC Paços de Ferreira":"PAC", + "Portimonense SC":"PRT", + "CD Aves":"AVE", + "AZ":"AZA", + "Feyenoord Rotterdam":"FEY", + "PSV":"PSV", + "Willem II Tilburg":"WIL", + "FC Utrecht":"UTR", + "SBV Vitesse":"VIT", + "FC Groningen":"GRO", + "Heracles Almelo":"HEA", + "SC Heerenveen":"HEE", + "Sparta Rotterdam":"SPR", + "FC Emmen":"EMM", + "FC Twente '65":"TWE", + "VVV Venlo":"VVV", + "Fortuna Sittard":"FST", + "PEC Zwolle":"PEC", + "ADO Den Haag":"ADO", + "RKC Waalwijk":"WAA" + } +} \ No newline at end of file diff --git a/scripts/downloader.js b/scripts/downloader.js deleted file mode 100644 index 1363480..0000000 --- a/scripts/downloader.js +++ /dev/null @@ -1,137 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const request = require('request'); - -const leagues = { - GERMANY: 452, - FRANCE: 450, - ENGLAND: 445, - SPAIN: 455, - ITALY: 456 -}; - -if (process.argv.length <= 2) { - throw new Error('You need to specify a country name!'); -} - -const country = process.argv[2].toUpperCase(); - -if (!Object.prototype.hasOwnProperty.call(leagues, country)) { - throw new Error('Selected country is not supported!'); -} - -const options = { - url: `http://api.football-data.org/v1/competitions/${leagues[country]}/leagueTable` -}; - -const missingTeams = { - GERMANY: ['1. FC Nürnberg', 'TSV Fortuna 95 Düsseldorf'], - FRANCE: ['En Avant Guingamp', 'Nîmes Olympique', 'Stade de Reims'], - ENGLAND: ['Cardiff City FC', 'Fulham FC', 'Wolverhampton Wanderers FC'], - SPAIN: ['Rayo Vallecano de Madrid', 'Real Valladolid CF', 'SD Huesca'], - ITALY: ['Empoli FC', 'Frosinone Calcio', 'Parma Calcio 1913'] -}; - -function extendTeams(teams) { - missingTeams[country].forEach((name) => { - teams.push({ teamName: name }); - }); -} - -const iconFixes = { - // Germany - '1. FC Nürnberg': 'https://upload.wikimedia.org/wikipedia/commons/5/56/FC_N%C3%BCrnberg.svg', - 'Bor. Mönchengladbach': 'https://upload.wikimedia.org/wikipedia/commons/8/81/Borussia_M%C3%B6nchengladbach_logo.svg', - 'FC Bayern München': 'https://upload.wikimedia.org/wikipedia/commons/1/1f/Logo_FC_Bayern_M%C3%BCnchen_%282002%E2%80%932017%29.svg', - 'TSV Fortuna 95 Düsseldorf': 'https://upload.wikimedia.org/wikipedia/commons/9/94/Fortuna_D%C3%BCsseldorf.svg', - // France - 'En Avant Guingamp': 'https://vignette.wikia.nocookie.net/logopedia/images/9/99/En_Avant_de_Guingamp_logo.svg', - 'Nîmes Olympique': 'https://upload.wikimedia.org/wikipedia/fr/f/f0/N%C3%AEmes_Olympique_logo_2018.svg', - 'OGC Nice': 'https://upload.wikimedia.org/wikipedia/de/5/58/OGC_Nizza_Logo.svg', - 'OSC Lille': 'https://vignette.wikia.nocookie.net/logopedia/images/a/ab/Lille_OSC_logo.svg', - 'SM Caen': 'https://upload.wikimedia.org/wikipedia/commons/6/64/SM_Caen.svg', - 'Stade de Reims': 'https://upload.wikimedia.org/wikipedia/de/9/9e/Stade_Reims_Logo.svg', - // England - 'Burnley FC': 'https://upload.wikimedia.org/wikipedia/de/4/49/FC_Burnley.svg', - 'Cardiff City FC': 'https://upload.wikimedia.org/wikipedia/de/1/18/Cardiff_City_AFC.svg', - 'Crystal Palace FC': 'https://upload.wikimedia.org/wikipedia/de/f/fc/Crystal_Palace_FC.svg', - 'Fulham FC': 'https://upload.wikimedia.org/wikipedia/de/a/a8/Fulham_fc.svg', - 'Leicester City FC': 'https://upload.wikimedia.org/wikipedia/de/b/b6/Leicester_City.svg', - 'Wolverhampton Wanderers FC': 'https://upload.wikimedia.org/wikipedia/de/1/1d/Wolverhampton_wanderers.svg', - // Spain - 'CD Leganes': 'https://svgur.com/i/890.svg', - 'Málaga CF': 'https://upload.wikimedia.org/wikipedia/de/e/e8/FC_M%C3%A1laga.svg', - 'Rayo Vallecano de Madrid': 'https://upload.wikimedia.org/wikipedia/de/1/12/Rayo_vallecano_madrid.svg', - 'RC Deportivo La Coruna': 'https://upload.wikimedia.org/wikipedia/de/b/b9/Deportivo_La_Coruna.svg', - 'Real Sociedad de Fútbol': 'https://upload.wikimedia.org/wikipedia/de/5/55/Real_Sociedad_San_Sebasti%C3%A1n.svg', - 'Real Valladolid CF': 'https://upload.wikimedia.org/wikipedia/de/6/6e/Real_Valladolid_Logo.svg', - 'SD Huesca': 'https://upload.wikimedia.org/wikipedia/de/7/71/SD_Huesca.svg', - 'Sevilla FC': 'https://upload.wikimedia.org/wikipedia/de/c/c0/FC_Sevilla.svg', - // Italy - 'Benevento Calcio': 'https://upload.wikimedia.org/wikipedia/de/4/48/Benevento_Calcio_Logo.svg', - 'Empoli FC': 'https://upload.wikimedia.org/wikipedia/de/4/42/Logo_FC_Empoli.svg', - 'FC Internazionale Milano': 'https://upload.wikimedia.org/wikipedia/commons/4/41/Inter_Mailand.svg', - 'Frosinone Calcio': 'https://upload.wikimedia.org/wikipedia/de/2/2b/Frosinone_Calcio.svg', - 'Parma Calcio 1913': 'https://upload.wikimedia.org/wikipedia/de/e/e2/FC_Parma.svg', - 'SPAL Ferrara': 'https://upload.wikimedia.org/wikipedia/de/e/e7/SPAL_Ferrara.svg', - 'SS Lazio': 'https://upload.wikimedia.org/wikipedia/sco/e/e4/SS_Lazio.svg', - 'UC Sampdoria': 'https://upload.wikimedia.org/wikipedia/ro/c/c4/UC_Sampdoria.svg' -}; - -const renamedTeams = { - // Germany - 'Bayer Leverkusen': 'Bayer 04 Leverkusen', - 'Borussia Dortmund': 'BV Borussia 09 Dortmund', - 'Bor. Mönchengladbach': 'Borussia Mönchengladbach', - 'Red Bull Leipzig': 'RB Leipzig', - 'Werder Bremen': 'SV Werder Bremen', - // France - 'Dijon FCO': 'Dijon Football Côte d\'Or', - 'Montpellier Hérault SC': 'Montpellier HSC', - 'OGC Nice': 'OGC de Nice Côte d\'Azur', - 'OSC Lille': 'Lille OSC', - 'Paris Saint-Germain': 'Paris Saint-Germain FC', - 'Stade Rennais FC': 'Stade Rennais FC 1901', - // England - 'Brighton & Hove Albion': 'Brighton & Hove Albion FC', - 'Huddersfield Town': 'Huddersfield Town AFC', - // Spain, - 'RCD Espanyol': 'RCD Espanyol de Barcelona', - 'Real Betis': 'Real Betis Balompié', - // Italy - 'Bologna FC': 'Bologna FC 1909', - 'Juventus Turin': 'Juventus FC', - 'SPAL Ferrara': 'SPAL 2013' -}; - -function download(uri, team, callback) { - const filename = path.join(__dirname, '..', 'public', `${Object.prototype.hasOwnProperty.call(renamedTeams, team) ? renamedTeams[team] : team}.svg`); - request(Object.prototype.hasOwnProperty.call(iconFixes, team) ? iconFixes[team] : uri) - .pipe(fs.createWriteStream(filename)) - .on('close', () => callback(team)); -} - -let iconsCount = 0; - -function counter(team) { - iconsCount -= 1; - console.log(`Downloaded: ${team}`); // eslint-disable-line no-console - - if (iconsCount <= 0) { - console.log('All icons downloaded'); // eslint-disable-line no-console - process.exit(1); - } -} - -request(options, (error, response, body) => { - if (response.statusCode === 200) { - const parsedBody = JSON.parse(body); - extendTeams(parsedBody.standing); - iconsCount = parsedBody.standing.length; - - parsedBody.standing.forEach(({ teamName, crestURI }) => { - const uri = Object.prototype.hasOwnProperty.call(iconFixes, teamName) ? iconFixes[teamName] : crestURI; - download(uri, teamName, counter); - }); - } -}); From c081e175988b1077ed7c977cd98f6180eeeac2f6 Mon Sep 17 00:00:00 2001 From: lavolp3 Date: Fri, 28 Feb 2020 09:49:35 +0100 Subject: [PATCH 11/31] Minor bugfixes --- MMM-soccer.js | 6 ++++-- MMM-soccer.njk | 7 +++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/MMM-soccer.js b/MMM-soccer.js index a35ff45..52ba230 100644 --- a/MMM-soccer.js +++ b/MMM-soccer.js @@ -253,6 +253,7 @@ Module.register('MMM-soccer', { `${this.translate('MATCHDAY')}: ${this.translate(this.matchDay)}` : this.translate('LOADING'), showTable: this.showTable, teams: (Object.keys(this.tables).length > 0) ? this.teams : {}, + showMatchDay: (this.config.matchType == "league"), voice: this.voice }; }, @@ -264,9 +265,10 @@ Module.register('MMM-soccer', { * @returns {Object} matches */ prepareMatches: function(allMatches, focusTeam) { - if (this.config.matchType === "league") { + if (this.config.matchType === 'league') { var diff = 0; - var matches = allMatches[this.competition]; + var matches = allMatches[this.competition].matches; + console.log(matches); var minDiff = Math.abs(moment().diff(matches[0].utcDate)); for (var m = 0; m < matches.length; m++) { if (!matches[m].matchday) {matches[m].matchday = matches[m].stage; } //for cup modes, copy stage to matchday property diff --git a/MMM-soccer.njk b/MMM-soccer.njk index b1cf872..ff54747 100644 --- a/MMM-soccer.njk +++ b/MMM-soccer.njk @@ -1,10 +1,13 @@
+
MMM-Soccer
{% if loading %} {{'LOADING' | translate}} {% else %} -
{{this.name}}
-
{{competitionName}}
+ + {% if showMatchDay %} +
{{competitionName}}
{{season}}
+ {% endif %} {% if config.showMatches %}
{{matches[i].homeTeam.name | replace}}
{{matches[i].homeTeam.name | replace}}{{ matches[i].state }} + {{ matches[i].state }} {{matches[i].awayTeam.name | replace}}{{matches[i].awayTeam.name | replace}}
From b306cf77f56e9767d5f0054c28ff82b492dc2f15 Mon Sep 17 00:00:00 2001 From: Dirk Date: Fri, 28 Feb 2020 09:51:33 +0100 Subject: [PATCH 12/31] Update MMM-soccer.js --- MMM-soccer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/MMM-soccer.js b/MMM-soccer.js index 52ba230..75c0d68 100644 --- a/MMM-soccer.js +++ b/MMM-soccer.js @@ -268,7 +268,6 @@ Module.register('MMM-soccer', { if (this.config.matchType === 'league') { var diff = 0; var matches = allMatches[this.competition].matches; - console.log(matches); var minDiff = Math.abs(moment().diff(matches[0].utcDate)); for (var m = 0; m < matches.length; m++) { if (!matches[m].matchday) {matches[m].matchday = matches[m].stage; } //for cup modes, copy stage to matchday property From fa33d2eec491e3fb417c8cfc330be0f713755e56 Mon Sep 17 00:00:00 2001 From: Dirk Date: Fri, 28 Feb 2020 15:50:44 +0100 Subject: [PATCH 13/31] Update package.json bugfix on package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6ac9b48..f59ecdd 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "MagicMirror", "soccer standings", "soccer", - "tables" + "tables", "football" ], "author": "lavolp3", From f84c5a1e87006611e779821ee37bd57a0d0af097 Mon Sep 17 00:00:00 2001 From: Dirk Date: Fri, 28 Feb 2020 15:54:26 +0100 Subject: [PATCH 14/31] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f59ecdd..36e6fa0 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "mmm-soccer v2", + "name": "mmm-soccer", "version": "1.0.0", "description": "European Soccer Standings Module for MagicMirror2", "repository": { From 9657bac135c18b262f9044b70b55464cf1409f7b Mon Sep 17 00:00:00 2001 From: Dirk Date: Fri, 28 Feb 2020 15:56:02 +0100 Subject: [PATCH 15/31] Update package.json removed dev dependencies --- package.json | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/package.json b/package.json index 36e6fa0..0628dc3 100644 --- a/package.json +++ b/package.json @@ -19,18 +19,7 @@ "url": "https://github.com/lavolp3/MMM-soccer/issues" }, "homepage": "https://github.com/lavolp3/MMM-soccer#readme", - "scripts": { - "lint": "./node_modules/.bin/eslint . && ./node_modules/.bin/stylelint .", - "docs": "./node_modules/.bin/jsdoc -c jsdoc.json ." - }, "dependencies": { "axios": "^0.19.2" }, - "devDependencies": { - "eslint": "^3.14.1", - "eslint-config-airbnb-base": "^11.0.1", - "eslint-plugin-import": "^2.2.0", - "stylelint": "^7.8.0", - "stylelint-config-standard": "^16.0.0" - } } From eb57a68bcaf4c66d4095c3049e90e8aab034d733 Mon Sep 17 00:00:00 2001 From: Dirk Date: Fri, 28 Feb 2020 15:57:24 +0100 Subject: [PATCH 16/31] Update package.json removed comma in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0628dc3..f1afb39 100644 --- a/package.json +++ b/package.json @@ -21,5 +21,5 @@ "homepage": "https://github.com/lavolp3/MMM-soccer#readme", "dependencies": { "axios": "^0.19.2" - }, + } } From 77c465eeee3b4d0feaf2e9292cf5f3d5c10d346b Mon Sep 17 00:00:00 2001 From: Dirk Date: Sat, 29 Feb 2020 01:09:40 +0100 Subject: [PATCH 17/31] bugfixes: self variable not properly declared in calls. Tweaks on UI deleted comments --- MMM-soccer.js | 109 ++++++++----------------------------------------- MMM-soccer.njk | 6 +-- node_helper.js | 24 ++++++----- 3 files changed, 35 insertions(+), 104 deletions(-) diff --git a/MMM-soccer.js b/MMM-soccer.js index 75c0d68..3c57ba3 100644 --- a/MMM-soccer.js +++ b/MMM-soccer.js @@ -52,7 +52,7 @@ Module.register('MMM-soccer', { logos: true, showTables: true, showMatches: true, - matchType: 'next', //choose 'next', 'daily', or 'league' + matchType: 'league', //choose 'next', 'daily', or 'league' leagues: { GERMANY: 'BL1', FRANCE: 'FL1', @@ -60,8 +60,8 @@ Module.register('MMM-soccer', { SPAIN: 'PD', ITALY: 'SA' }, - debug: false, replace: 'default', //choose 'default', 'short' or '' for original names + debug: false, }, /** @@ -114,7 +114,7 @@ Module.register('MMM-soccer', { var self = this; this.replacers = this.loadReplacements(response => { self.replacements = JSON.parse(response); - self.log(self.replacements); + //self.log(self.replacements); }); this.sendSocketNotification('GET_SOCCER_DATA', this.config); this.scheduleDOMUpdates(); @@ -136,10 +136,6 @@ Module.register('MMM-soccer', { }, - /** - * @function scheduleDOMUpdates - * @description Schedules updates for displaying leagues. - */ scheduleDOMUpdates: function () { var count = 0; var _this = this; @@ -163,14 +159,7 @@ Module.register('MMM-soccer', { } }, - /** - * @function socketNotificationReceived - * @description Handles incoming messages from node_helper. - * @override - * - * @param {string} notification - Notification name - * @param {*} payload - Detailed payload of the notification. - */ + socketNotificationReceived: function(notification, payload) { this.log("received a Socket Notification: " + notification + ", payload: "+payload); if (notification === 'TABLES') { @@ -194,15 +183,7 @@ Module.register('MMM-soccer', { } }, - /** - * @function notificationReceived - * @description Handles incoming broadcasts from other modules or the MagicMirror² core. - * @override - * - * @param {string} notification - Notification name - * @param {*} payload - Detailed payload of the notification. - * @param {Object} sender - Module that sent the notification or undefined for MagicMirror² core. - */ + notificationReceived: function(notification, payload, sender) { if (notification === 'ALL_MODULES_STARTED') { const voice = Object.assign({}, this.voice); @@ -233,13 +214,7 @@ Module.register('MMM-soccer', { return 'MMM-soccer.njk'; }, - /** - * @function getTemplateData - * @description Data that gets rendered in the nunjuck template. - * @override - * - * @returns {string} Data for the nunjuck template. - */ + getTemplateData: function() { return { boundaries: (this.tables.hasOwnProperty(this.competition)) ? this.calculateTeamDisplayBoundaries(this.competition) : {}, @@ -258,12 +233,7 @@ Module.register('MMM-soccer', { }; }, - /** - * @function prepareMatches - * @description Filters matches to show only one matchday. Also focuses on focused team(s) - * - * @returns {Object} matches - */ + prepareMatches: function(allMatches, focusTeam) { if (this.config.matchType === 'league') { var diff = 0; @@ -318,13 +288,6 @@ Module.register('MMM-soccer', { }, - /** - * @function filterTables - * @description Filters tables to show one table per competition. For leagues mode "home" and "away" tables are filtered out. - * For cups only the table including the focused team is extracted - * - * @returns {Object} Object including current matchday and array of teams. - */ filterTables: function(tables, focusTeam) { //filtering out "home" and "away" tables if (!tables.standings) return ""; @@ -345,12 +308,7 @@ Module.register('MMM-soccer', { return table; }, - /** - * @function findFocusTeam - * @description Helper function to find index of team in standings - * - * @returns {Object} Index of team, first and last team to display. - */ + findFocusTeam: function() { this.log("Finding focus team for table..."); let focusTeamIndex; @@ -376,12 +334,7 @@ Module.register('MMM-soccer', { } }, - /** - * @function getFirstAndLastTeam - * @description Helper function to get the boundaries of the teams that should be displayed. - * - * @returns {Object} Index of the first and the last team. - */ + getFirstAndLastTeam: function(index) { let firstTeam; let lastTeam; @@ -403,13 +356,8 @@ Module.register('MMM-soccer', { return { firstTeam, lastTeam }; }, - /** - * @function calculateTeamDisplayBoundaries - * @description Calculates the boundaries of teams based on the config. - * - * @returns {Object} Index of team, first and last team to display. - */ - calculateTeamDisplayBoundaries(competition) { + + calculateTeamDisplayBoundaries: function(competition) { this.log("Calculating Team Display Boundaries"); if (this.config.focus_on && this.config.focus_on.hasOwnProperty(competition)) { if (this.config.focus_on[competition] === 'TOP') { @@ -438,20 +386,13 @@ Module.register('MMM-soccer', { }; }, - /** - * @function isMaxTeamsLessAll - * @description Are there more entries than the config option specifies. - * - * @returns {boolean} - */ + + isMaxTeamsLessAll: function() { return (this.config.max_teams && this.config.max_teams <= this.standing.length); }, - /** - * @function handleModals - * @description Hide/show modules based on voice commands. - */ + handleModals: function(data, modal, open, close) { if (close.test(data) || (this.modals[modal] && !open.test(data))) { this.closeAllModals(); @@ -472,30 +413,19 @@ Module.register('MMM-soccer', { } }, - /** - * @function closeAllModals - * @description Close all modals of the module. - */ + closeAllModals: function() { const modals = Object.keys(this.modals); modals.forEach((modal) => { this.modals[modal] = false; }); }, - /** - * @function isModalActive - * @description Checks if at least one modal is active. - * - * @returns {boolean} Flag if there is an active modal. - */ + isModalActive: function() { const modals = Object.keys(this.modals); return modals.some(modal => this.modals[modal] === true); }, - /** - * @function checkCommands - * @description Voice command handler. - */ + checkCommands: function(data) { if (/(HELP)/g.test(data)) { this.handleModals(data, 'help', /(OPEN)/g, /(CLOSE)/g); @@ -518,10 +448,7 @@ Module.register('MMM-soccer', { this.updateDom(300); }, - /** - * @function addFilters - * @description Adds the filter used by the nunjuck template. - */ + addFilters: function () { njEnv = this.nunjucksEnvironment(); njEnv.addFilter('fade', (index, focus) => { diff --git a/MMM-soccer.njk b/MMM-soccer.njk index ff54747..b2db75c 100644 --- a/MMM-soccer.njk +++ b/MMM-soccer.njk @@ -3,8 +3,8 @@ {% if loading %} {{'LOADING' | translate}} {% else %} - - {% if showMatchDay %} + + {% if showMatchDay %}
{{competitionName}}
{{season}}
{% endif %} @@ -29,7 +29,7 @@
{% endif %} {% if showTable %} - +
diff --git a/node_helper.js b/node_helper.js index aedd082..c3bfb1e 100644 --- a/node_helper.js +++ b/node_helper.js @@ -31,7 +31,7 @@ module.exports = NodeHelper.create({ liveMatches: [], liveLeagues: [], - start() { + start: function() { console.log(`Starting module: ${this.name}`); }, @@ -43,11 +43,10 @@ module.exports = NodeHelper.create({ * @param {string} notification - Notification name * @param {*} payload - Detailed payload of the notification. */ - socketNotificationReceived(notification, payload) { + socketNotificationReceived: function(notification, payload) { this.log("Socket notification received: "+notification+" Payload: "+JSON.stringify(payload)); this.headers = payload.api_key ? { 'X-Auth-Token': payload.api_key } : {}; this.config = payload; - self = this; if (notification === 'GET_SOCCER_DATA') { this.config = payload; this.scheduleAPICalls(false); @@ -92,8 +91,8 @@ module.exports = NodeHelper.create({ * * @param {Object} options - request optionsthe notification. */ - getTables(leagues) { - self = this; + getTables: function(leagues) { + var self = this; this.log("Collecting league tables for leagues: "+leagues); var urlArray = leagues.map(league => { return `http://api.football-data.org/v2/competitions/${league}/standings`; }); //this.log(urlArray); @@ -131,11 +130,14 @@ module.exports = NodeHelper.create({ //self.log("TableArray: " + tableArray); self.sendSocketNotification("TABLES", self.tables); self.sendSocketNotification("TEAMS", self.teams); + }) + .catch(function(error) { + console.error("[MMM-soccer] ERROR occured while fetching tables: " + error); }); }, - getMatches(leagues) { - self = this; + getMatches: function(leagues) { + var self = this; this.log("Collecting matches for leagues: "+leagues); var urlArray = leagues.map(league => { return `http://api.football-data.org/v2/competitions/${league}/matches`; }); Promise.all(urlArray.map(url => { @@ -173,12 +175,15 @@ module.exports = NodeHelper.create({ //self.log("Collected Matches: "+self.matches); self.log("Live matches: "+JSON.stringify(self.liveMatches)); self.sendSocketNotification("MATCHES", self.matches); + }) + .catch(function(error) { + console.error("[MMM-soccer] ERROR occured while fetching matches: " + error); }); }, - getMatchDetails(matches) { - self = this; + getMatchDetails: function (matches) { + var self = this; this.log("Getting match details for matches: " + matches); var urlArray = matches.map(match => { return `http://api.football-data.org/v2/matches/${match}`; }); Promise.all(urlArray.map(url => { @@ -233,7 +238,6 @@ module.exports = NodeHelper.create({ } }, - log: function (msg) { if (this.config && this.config.debug) { console.log(this.name + ":", JSON.stringify(msg)); From 56c157d5e692911071618e32c40fc72c6a014c97 Mon Sep 17 00:00:00 2001 From: lavolp3 Date: Sun, 1 Mar 2020 01:50:38 +0100 Subject: [PATCH 18/31] Fixed live mode --- MMM-soccer.js | 25 ++++++++----------------- MMM-soccer.njk | 0 node_helper.js | 18 ++++++++++-------- 3 files changed, 18 insertions(+), 25 deletions(-) mode change 100644 => 100755 MMM-soccer.js mode change 100644 => 100755 MMM-soccer.njk mode change 100644 => 100755 node_helper.js diff --git a/MMM-soccer.js b/MMM-soccer.js old mode 100644 new mode 100755 index 3c57ba3..c002e1c --- a/MMM-soccer.js +++ b/MMM-soccer.js @@ -97,6 +97,7 @@ Module.register('MMM-soccer', { matchDay: "", showTable: true, leagues: [], + liveMode: false, liveMatches: [], liveLeagues: [], replacements: { @@ -139,27 +140,17 @@ Module.register('MMM-soccer', { scheduleDOMUpdates: function () { var count = 0; var _this = this; - const comps = this.leagues.length; setInterval(() => { + const comps = _this.leagues.length; count = (count === comps - 1) ? 0 : count + 1; _this.competition = _this.leagues[count]; _this.log("Showing competition: "+_this.competition); _this.standing = _this.filterTables(_this.tables[_this.competition], _this.config.focus_on[_this.competition]); - _this.updateDom(800); + _this.updateDom(500); }, this.config.updateInterval * 1000); }, - liveMode: function (isLive) { - if (isLive) { - //clearInterval(this.mainInterval); - this.log("Live Mode activated, main Interval stopped."); - } else { - this.scheduleAPICalls(); - } - }, - - socketNotificationReceived: function(notification, payload) { this.log("received a Socket Notification: " + notification + ", payload: "+payload); if (notification === 'TABLES') { @@ -171,10 +162,11 @@ Module.register('MMM-soccer', { //this.log(this.matches); } else if (notification === 'TEAMS') { this.teams = payload; - } else if (notification === 'LIVE_MATCHES') { - var matches = payload; + /*} else if (notification === 'LIVE_MATCHES') { + var matches = payload;*/ } else if (notification === 'LIVE') { - this.liveLeagues = payload.leagues; + this.liveMode = payload.live; + this.leagues = (payload.leagues.length > 0) ? payload.leagues : this.config.show; this.liveMatches = payload.matches; } if (this.loading === true && this.tables.hasOwnProperty(this.competition) && this.matches.hasOwnProperty(this.competition)) { @@ -183,7 +175,6 @@ Module.register('MMM-soccer', { } }, - notificationReceived: function(notification, payload, sender) { if (notification === 'ALL_MODULES_STARTED') { const voice = Object.assign({}, this.voice); @@ -228,7 +219,7 @@ Module.register('MMM-soccer', { `${this.translate('MATCHDAY')}: ${this.translate(this.matchDay)}` : this.translate('LOADING'), showTable: this.showTable, teams: (Object.keys(this.tables).length > 0) ? this.teams : {}, - showMatchDay: (this.config.matchType == "league"), + showMatchDay: (this.config.matchType == "league"), voice: this.voice }; }, diff --git a/MMM-soccer.njk b/MMM-soccer.njk old mode 100644 new mode 100755 diff --git a/node_helper.js b/node_helper.js old mode 100644 new mode 100755 index c3bfb1e..23ba1b3 --- a/node_helper.js +++ b/node_helper.js @@ -49,6 +49,8 @@ module.exports = NodeHelper.create({ this.config = payload; if (notification === 'GET_SOCCER_DATA') { this.config = payload; + this.getTables(this.config.show); + this.getMatches(this.config.show); this.scheduleAPICalls(false); } }, @@ -58,8 +60,6 @@ module.exports = NodeHelper.create({ * @description Sends request to the node_helper to fetch data for the current selected leagues. */ scheduleAPICalls: function(live) { - this.getTables(this.config.show); - this.getMatches(this.config.show); var self = this; if (live === false) { this.mainInterval = setInterval(() => { @@ -67,7 +67,7 @@ module.exports = NodeHelper.create({ self.toggleLiveMode(true); } else { self.getTables(self.config.show); - //self.getMatches(self.config.show); + self.getMatches(self.config.show); } }, this.config.apiCallInterval * 1000); } else { @@ -77,8 +77,8 @@ module.exports = NodeHelper.create({ if (self.liveMatches.length == 0) { self.toggleLiveMode(false); } else { - //self.getTables(self.config.show); - //self.getMatches(self.config.show); + self.getTables(self.config.show); + self.getMatches(self.config.show); //self.getMatchDetails(self.liveMatches); } }, liveUpdateInterval); @@ -138,6 +138,7 @@ module.exports = NodeHelper.create({ getMatches: function(leagues) { var self = this; + var now = moment().subtract(9, 'hours'); this.log("Collecting matches for leagues: "+leagues); var urlArray = leagues.map(league => { return `http://api.football-data.org/v2/competitions/${league}/matches`; }); Promise.all(urlArray.map(url => { @@ -148,7 +149,7 @@ module.exports = NodeHelper.create({ matchesData.matches.forEach(match => { delete match.referees; //check for live matches - if (moment(match.utcDate).add(90, 'minutes').diff(moment()) > 0 && moment(match.utcDate).diff(moment(), 'seconds') < self.config.apiCallInterval) { + if (moment(match.utcDate).add(90, 'minutes').diff(now) > 0 && moment(match.utcDate).diff(now, 'seconds') < self.config.apiCallInterval) { if (self.liveMatches.indexOf(match.id) === -1) { console.log(`Live match detected starting at ${moment(match.utcDate).format("HH:mm")}, Home Team: ${match.homeTeam.name}`); self.liveMatches.push(match.id); @@ -174,6 +175,7 @@ module.exports = NodeHelper.create({ }); //self.log("Collected Matches: "+self.matches); self.log("Live matches: "+JSON.stringify(self.liveMatches)); + self.log("Live leagues: "+JSON.stringify(self.liveLeagues)); self.sendSocketNotification("MATCHES", self.matches); }) .catch(function(error) { @@ -228,12 +230,12 @@ module.exports = NodeHelper.create({ if (isLive) { clearInterval(this.mainInterval); this.log("Live Mode activated, main interval stopped."); - this.sendSocketNotification("LIVE", { matches: this.liveMatches, leagues: this.liveLeagues }); + this.sendSocketNotification("LIVE", { live: true, matches: this.liveMatches, leagues: this.liveLeagues }); this.scheduleAPICalls(true); } else { clearInterval(this.liveInterval); this.log("Live Mode deactivated, back to main interval."); - this.sendSocketNotification("LIVE", { matches: this.liveMatches, leagues: this.liveLeagues }); + this.sendSocketNotification("LIVE", { live: false, matches: this.liveMatches, leagues: this.liveLeagues }); this.scheduleAPICalls(false); } }, From 6292b3888c94051d81a077842f7c8a8c3d7e9dd5 Mon Sep 17 00:00:00 2001 From: Dirk Date: Sun, 1 Mar 2020 07:40:45 +0100 Subject: [PATCH 19/31] fixed live mode --- node_helper.js | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/node_helper.js b/node_helper.js index 23ba1b3..f190d64 100755 --- a/node_helper.js +++ b/node_helper.js @@ -1,14 +1,12 @@ /** * @file node_helper.js * - * @author fewieden + * @author lavolp3 * @license MIT * - * @see https://github.com/fewieden/MMM-soccer + * @see https://github.com/lavolp3/MMM-soccer */ -/* eslint-env node */ -/* eslint-disable no-console */ /* jshint esversion: 6 */ const axios = require('axios'); @@ -35,14 +33,7 @@ module.exports = NodeHelper.create({ console.log(`Starting module: ${this.name}`); }, - /** - * @function socketNotificationReceived - * @description Receives socket notifications from the module. - * @override - * - * @param {string} notification - Notification name - * @param {*} payload - Detailed payload of the notification. - */ + socketNotificationReceived: function(notification, payload) { this.log("Socket notification received: "+notification+" Payload: "+JSON.stringify(payload)); this.headers = payload.api_key ? { 'X-Auth-Token': payload.api_key } : {}; @@ -55,10 +46,6 @@ module.exports = NodeHelper.create({ } }, - /** - * @function scheduleAPICalls - * @description Sends request to the node_helper to fetch data for the current selected leagues. - */ scheduleAPICalls: function(live) { var self = this; if (live === false) { @@ -85,13 +72,7 @@ module.exports = NodeHelper.create({ } }, - /** - * @function getTables - * @description Request data from the supplied URL and broadcast it to the MagicMirror module if it's received. - * - * @param {Object} options - request optionsthe notification. - */ - getTables: function(leagues) { + getTables: function(leagues) { var self = this; this.log("Collecting league tables for leagues: "+leagues); var urlArray = leagues.map(league => { return `http://api.football-data.org/v2/competitions/${league}/standings`; }); @@ -138,7 +119,7 @@ module.exports = NodeHelper.create({ getMatches: function(leagues) { var self = this; - var now = moment().subtract(9, 'hours'); + var now = moment(); this.log("Collecting matches for leagues: "+leagues); var urlArray = leagues.map(league => { return `http://api.football-data.org/v2/competitions/${league}/matches`; }); Promise.all(urlArray.map(url => { From 1ccac9375ba70e8e2bdb776f0a2d395a05671e9d Mon Sep 17 00:00:00 2001 From: Dirk Date: Wed, 11 Mar 2020 23:33:02 +0100 Subject: [PATCH 20/31] fixed live mode (again) --- MMM-soccer.css | 8 ++++-- MMM-soccer.js | 19 +++++++------ MMM-soccer.njk | 0 README.md | 1 + node_helper.js | 77 +++++++++++++++++++++++++------------------------- 5 files changed, 55 insertions(+), 50 deletions(-) mode change 100755 => 100644 MMM-soccer.js mode change 100755 => 100644 MMM-soccer.njk mode change 100755 => 100644 node_helper.js diff --git a/MMM-soccer.css b/MMM-soccer.css index ddaf360..44a4c29 100644 --- a/MMM-soccer.css +++ b/MMM-soccer.css @@ -39,9 +39,13 @@ width: 50px; } -.MMM-soccer .games .status .IN_PLAY { - background-color: #fdfd96; +.MMM-soccer .games .IN_PLAY { + color: #fdfd96; +} +.MMM-soccer .games .status.IN_PLAY { + background-color: #fdfd96; + color: black; } .MMM-soccer .logo { diff --git a/MMM-soccer.js b/MMM-soccer.js old mode 100755 new mode 100644 index c002e1c..faf830b --- a/MMM-soccer.js +++ b/MMM-soccer.js @@ -44,7 +44,7 @@ Module.register('MMM-soccer', { colored: false, width: 400, show: ['BL1', 'CL', 'PL'], - updateInterval: 60, + updateInterval: 30, apiCallInterval: 10 * 60, focus_on: false, fadeFocus: true, @@ -53,6 +53,7 @@ Module.register('MMM-soccer', { showTables: true, showMatches: true, matchType: 'league', //choose 'next', 'daily', or 'league' + numberOfNextMatches: 8, leagues: { GERMANY: 'BL1', FRANCE: 'FL1', @@ -142,9 +143,9 @@ Module.register('MMM-soccer', { var _this = this; setInterval(() => { const comps = _this.leagues.length; - count = (count === comps - 1) ? 0 : count + 1; + count = (count >= comps - 1) ? 0 : count + 1; _this.competition = _this.leagues[count]; - _this.log("Showing competition: "+_this.competition); + _this.log("Showing competition: " + _this.competition); _this.standing = _this.filterTables(_this.tables[_this.competition], _this.config.focus_on[_this.competition]); _this.updateDom(500); }, this.config.updateInterval * 1000); @@ -152,11 +153,11 @@ Module.register('MMM-soccer', { socketNotificationReceived: function(notification, payload) { - this.log("received a Socket Notification: " + notification + ", payload: "+payload); + this.log(`received a Socket Notification: ${notification}`); if (notification === 'TABLES') { this.tables = payload; this.standing = this.filterTables(this.tables[this.competition], this.config.focus_on[this.competition]); - this.log("Current table: "+this.standing); + this.log("Current table: " + JSON.stringify(this.standing)); } else if (notification === 'MATCHES') { this.matches = payload; //this.log(this.matches); @@ -238,10 +239,10 @@ Module.register('MMM-soccer', { this.matchDay = matches[m].matchday; } } - this.log("Current matchday: "+this.matchDay); + this.log("Current matchday: " + this.matchDay); this.showTable = (!isNaN(this.matchDay)); - returnedMatches = matches.filter(match => { + returnedMatches = matches.filter(match => { return match.matchday == this.matchDay; }); } else if (this.config.matchType === "next") { @@ -264,7 +265,7 @@ Module.register('MMM-soccer', { nextMatches.sort(function (match1, match2) { return (moment(match1.utcDate) - moment(match2.utcDate)); }); - returnedMatches = nextMatches.slice(0, 5 * teams.length); + returnedMatches = nextMatches.slice(0, numberOfNextMatches); } returnedMatches.forEach(match => { match.focused = (match.homeTeam.name === focusTeam) ? true : (match.awayTeam.name === focusTeam) ? true : false; @@ -274,7 +275,7 @@ Module.register('MMM-soccer', { match.state = match.score.fullTime.homeTeam + " - " + match.score.fullTime.awayTeam; } }); - //this.log(matches); + //this.log("Returned matches: "+JSON.stringify(returnedMatches)); return returnedMatches; }, diff --git a/MMM-soccer.njk b/MMM-soccer.njk old mode 100755 new mode 100644 diff --git a/README.md b/README.md index 8604e16..b5ddb24 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ A Soccer Standings Module for MagicMirror², based on @fewiedens [MMM-soccer](ht | `logos` | true | Boolean to show club logos. | | `liveMode` | true | Activates live mode when games are in play. (see below, not active yet) | | `matchType` | 'league' | Choose between the following: 'league' for showing the current matchday of selected leagues (in `show`), 'next' for showing the next matches of all your focused clubs (in `focus_on`), 'daily' for showing all of todays matches for selected leagues. | +| `numberOfNextMatches` | 8 | Defines number of next matches of all focused clubs for matchType `next` | | `touchMode` | false | Activates touch mode with touch options (see below, not active yet) | | `debug` | false | Debug mode: additional output on server side (console) and client side (browser) | diff --git a/node_helper.js b/node_helper.js old mode 100755 new mode 100644 index f190d64..f3016c3 --- a/node_helper.js +++ b/node_helper.js @@ -33,43 +33,30 @@ module.exports = NodeHelper.create({ console.log(`Starting module: ${this.name}`); }, - + socketNotificationReceived: function(notification, payload) { this.log("Socket notification received: "+notification+" Payload: "+JSON.stringify(payload)); this.headers = payload.api_key ? { 'X-Auth-Token': payload.api_key } : {}; this.config = payload; + this.leagues = this.config.show; if (notification === 'GET_SOCCER_DATA') { this.config = payload; - this.getTables(this.config.show); - this.getMatches(this.config.show); + this.getTables(this.leagues); + this.getMatches(this.leagues); + this.liveMode = false; this.scheduleAPICalls(false); } }, scheduleAPICalls: function(live) { var self = this; - if (live === false) { - this.mainInterval = setInterval(() => { - if (self.liveMatches.length > 0) { - self.toggleLiveMode(true); - } else { - self.getTables(self.config.show); - self.getMatches(self.config.show); - } - }, this.config.apiCallInterval * 1000); - } else { - var liveUpdateInterval = Math.max(Math.floor(10/(this.liveLeagues.length * 2)), 1) * 1000; - console.log("Live update interval: "+liveUpdateInterval); - this.liveInterval = setInterval(() => { - if (self.liveMatches.length == 0) { - self.toggleLiveMode(false); - } else { - self.getTables(self.config.show); - self.getMatches(self.config.show); - //self.getMatchDetails(self.liveMatches); - } - }, liveUpdateInterval); - } + //var updateInterval = (this.liveLeagues.length > 0) ? (60/(Math.floor(5/this.liveLeagues.length))) * 1000 : this.config.apiCallInterval * 1000; + var updateInterval = (this.liveLeagues.length > 0) ? 60 * 1000 : this.config.apiCallInterval * 1000; + this.callInterval = setInterval(() => { + self.getTables(self.leagues); + self.getMatches(self.leagues); + //self.getMatchDetails(self.liveMatches); + }, updateInterval); }, getTables: function(leagues) { @@ -119,9 +106,10 @@ module.exports = NodeHelper.create({ getMatches: function(leagues) { var self = this; - var now = moment(); + var now = moment().subtract(0, "hours"); this.log("Collecting matches for leagues: "+leagues); var urlArray = leagues.map(league => { return `http://api.football-data.org/v2/competitions/${league}/matches`; }); + this.liveLeagues = []; Promise.all(urlArray.map(url => { return axios.get(url, { headers: self.headers }) .then(function (response) { @@ -130,15 +118,21 @@ module.exports = NodeHelper.create({ matchesData.matches.forEach(match => { delete match.referees; //check for live matches - if (moment(match.utcDate).add(90, 'minutes').diff(now) > 0 && moment(match.utcDate).diff(now, 'seconds') < self.config.apiCallInterval) { + if (match.status == "IN_PLAY" || Math.abs(moment(match.utcDate).diff(now, 'seconds')) < self.config.apiCallInterval * 10) { + self.log(`Live match detected starting at ${moment(match.utcDate).format("HH:mm")}, Home Team: ${match.homeTeam.name}`); if (self.liveMatches.indexOf(match.id) === -1) { - console.log(`Live match detected starting at ${moment(match.utcDate).format("HH:mm")}, Home Team: ${match.homeTeam.name}`); + //self.log(`Live match ${match.id} added at ${moment().format("HH:mm")}`); self.liveMatches.push(match.id); } if (self.liveLeagues.indexOf(league) === -1) { self.log(`Live league ${league} added at ${moment().format("HH:mm")}`); self.liveLeagues.push(league); } + } else { + if (self.liveMatches.indexOf(match.id)!= -1) { + self.log("Live match finished"); + self.liveMatches.splice(self.liveMatches.indexOf(comp.matches[m].id), 1); + } } }); return(matchesData); @@ -158,6 +152,7 @@ module.exports = NodeHelper.create({ self.log("Live matches: "+JSON.stringify(self.liveMatches)); self.log("Live leagues: "+JSON.stringify(self.liveLeagues)); self.sendSocketNotification("MATCHES", self.matches); + self.toggleLiveMode(self.liveMatches.length > 0); }) .catch(function(error) { console.error("[MMM-soccer] ERROR occured while fetching matches: " + error); @@ -195,7 +190,7 @@ module.exports = NodeHelper.create({ }, handleErrors: function(error, url) { - console.log("An error occured while requesting the API for Data:"); + console.log("An error occured while requesting the API for Data: "+error); console.log("URL: "+url); if (error.response.status === 429) { console.log(error.response.status + ": API Request Quota of 10 calls per minute exceeded. Try selecting less leagues."); @@ -208,16 +203,20 @@ module.exports = NodeHelper.create({ }, toggleLiveMode: function (isLive) { - if (isLive) { - clearInterval(this.mainInterval); - this.log("Live Mode activated, main interval stopped."); - this.sendSocketNotification("LIVE", { live: true, matches: this.liveMatches, leagues: this.liveLeagues }); - this.scheduleAPICalls(true); - } else { - clearInterval(this.liveInterval); - this.log("Live Mode deactivated, back to main interval."); - this.sendSocketNotification("LIVE", { live: false, matches: this.liveMatches, leagues: this.liveLeagues }); - this.scheduleAPICalls(false); + if (isLive != this.liveMode) { + clearInterval(this.callInterval); + if (isLive) { + this.log("Live Mode activate!"); + //this.leagues = this.liveLeagues; + this.sendSocketNotification("LIVE", { live: true, matches: this.liveMatches, leagues: this.liveLeagues }); + this.scheduleAPICalls(true); + } else { + this.log("Usual mode active!"); + //this.leagues = this.config.show; + this.sendSocketNotification("LIVE", { live: false, matches: this.liveMatches, leagues: this.liveLeagues }); + this.scheduleAPICalls(false); + } + this.liveMode = isLive; } }, From 10bf3cc9b5fe712358e92cff166bc78d7aeeece6 Mon Sep 17 00:00:00 2001 From: Dirk Date: Tue, 7 Apr 2020 17:05:59 +0200 Subject: [PATCH 21/31] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b5ddb24..1b08e74 100644 --- a/README.md +++ b/README.md @@ -83,16 +83,16 @@ Have a look into the ```replace``` object in the config to see if the team name Omitting a league code from 'show' in this array will show the full league table and not include any focus. Any league included here need to be included in 'show' as well to show the league on your mirror. -##replacements -There is a `replacements.json` file in the directory including all teams of the free plan. By default, the default replacement for the original team name will be used in the module. YOu can choose between 'default' mode or 'short' mode showing the 3-letter ID code for the team for a super slim module. +## Replacements +There is a `replacements.json` file in the directory including all teams of the free plan. By default, the default replacement for the original team name will be used in the module. You can choose between 'default' mode or 'short' mode showing the 3-letter ID code for the team for a super slim module. ## Live Mode The module calls all requested matches every X minutes (see config option apiCallInterval). Whenever one or more matches are scheduled in less than this interval, a Live Mode will activate. -All matches currently played will be included in an array and requested for updates as regularly as the free api (10 calls per minute) allows. +All matches currently played will be included in an array and requested every minute. ~Additional informations like game minute and scorers will be provided for these games.~ (another API is needed for this) -Also, only the leagues with current matches will be shown (not in touch mode) -When no game is active, the module will return back to normal mode. +Also, only the leagues with current matches will be shown. +When no game is live, the module will return back to normal mode. Can be switched off in config. From 3eacfcd7a44781929c0aa73ed11961ae6db45de9 Mon Sep 17 00:00:00 2001 From: lavolp3 Date: Mon, 8 Jun 2020 16:20:37 +0200 Subject: [PATCH 22/31] fixes in live mode and code cosmetics --- MMM-soccer.js | 46 +++++---------------------------------- node_helper.js | 58 +++++++++++++++++++++++--------------------------- 2 files changed, 32 insertions(+), 72 deletions(-) diff --git a/MMM-soccer.js b/MMM-soccer.js index faf830b..81773a2 100644 --- a/MMM-soccer.js +++ b/MMM-soccer.js @@ -1,44 +1,18 @@ /** * @file MMM-soccer.js * - * @author fewieden + * @author lavolp3/fewieden * @license MIT * - * @see https://github.com/fewieden/MMM-soccer + * @see https://github.com/lavolp3/MMM-soccer */ /* jshint esversion: 6 */ /* global Module Log */ -/** - * @external Module - * @see https://github.com/MichMich/MagicMirror/blob/master/js/module.js - */ - -/** - * @external Log - * @see https://github.com/MichMich/MagicMirror/blob/master/js/logger.js - */ - -/** - * @module MMM-soccer - * @description Frontend of the MagicMirror² module. - * - * @requires external:Module - * @requires external:Log - */ Module.register('MMM-soccer', { - /** - * @member {Object} defaults - Defines the default config values. - * @property {boolean|string} api_key - API acces key for football-data.org. - * @property {boolean} colored - Flag to show logos in color or black/white. - * @property {array} show - League names to be filtered for showing tables and games. - * @property {boolean|Object} focus_on - Hash of country name -> club name to determine highlighted team per league. - * @property {boolean|int} max_teams - Maximum amount of teams to be displayed. - * @property {boolean} logos - Flag to show club logos. - * @property {Object} leagues - Hash of country name -> league id. - */ + defaults: { api_key: false, colored: false, @@ -65,21 +39,11 @@ Module.register('MMM-soccer', { debug: false, }, - /** - * @member {Object} modals - Stores the status of the module's modals. - * @property {boolean} standings - Full standings table. - * @property {boolean} help - List of voice commands of this module. - */ modals: { standings: false, help: false }, - /** - * @member {Object} voice - Defines the default mode and commands of this module. - * @property {string} mode - Voice mode of this module. - * @property {string[]} sentences - List of voice commands of this module. - */ voice: { mode: 'SOCCER', sentences: [ @@ -113,8 +77,8 @@ Module.register('MMM-soccer', { this.leagues = this.config.show; this.competition = this.leagues[0]; this.showTable = this.config.showTables; - var self = this; - this.replacers = this.loadReplacements(response => { + var self = this; + this.replacers = this.loadReplacements(response => { self.replacements = JSON.parse(response); //self.log(self.replacements); }); diff --git a/node_helper.js b/node_helper.js index f3016c3..11e96e5 100644 --- a/node_helper.js +++ b/node_helper.js @@ -1,7 +1,7 @@ /** * @file node_helper.js * - * @author lavolp3 + * @author lavolp3 / fewieden (original module) * @license MIT * * @see https://github.com/lavolp3/MMM-soccer @@ -13,13 +13,6 @@ const axios = require('axios'); const NodeHelper = require('node_helper'); const moment = require('moment'); -/** - * @module node_helper - * @description Backend for the module to query data from the API provider. - * - * @requires external:request - * @requires external:node_helper - */ module.exports = NodeHelper.create({ matches: {}, @@ -35,12 +28,12 @@ module.exports = NodeHelper.create({ socketNotificationReceived: function(notification, payload) { - this.log("Socket notification received: "+notification+" Payload: "+JSON.stringify(payload)); - this.headers = payload.api_key ? { 'X-Auth-Token': payload.api_key } : {}; - this.config = payload; - this.leagues = this.config.show; if (notification === 'GET_SOCCER_DATA') { + this.log("Socket notification received: " + notification + " Payload: " + JSON.stringify(payload)); + this.log("Starting API call cycle"); this.config = payload; + this.headers = payload.api_key ? { 'X-Auth-Token': payload.api_key } : {}; + this.leagues = this.config.show; this.getTables(this.leagues); this.getMatches(this.leagues); this.liveMode = false; @@ -59,14 +52,14 @@ module.exports = NodeHelper.create({ }, updateInterval); }, - getTables: function(leagues) { + getTables: function(leagues) { var self = this; this.log("Collecting league tables for leagues: "+leagues); var urlArray = leagues.map(league => { return `http://api.football-data.org/v2/competitions/${league}/standings`; }); - //this.log(urlArray); Promise.all(urlArray.map(url => { return axios.get(url, { headers: self.headers }) .then(function (response) { + console.log("Requests available: " + response.headers["x-requests-available-minute"]); var tableData = response.data; var tables = { competition: tableData.competition, @@ -99,39 +92,41 @@ module.exports = NodeHelper.create({ self.sendSocketNotification("TABLES", self.tables); self.sendSocketNotification("TEAMS", self.teams); }) - .catch(function(error) { + /*.catch(function(error) { console.error("[MMM-soccer] ERROR occured while fetching tables: " + error); - }); + });*/ }, getMatches: function(leagues) { - var self = this; - var now = moment().subtract(0, "hours"); - this.log("Collecting matches for leagues: "+leagues); + var now = moment().subtract(0, "minutes"); + this.log("Collecting matches for leagues: " + leagues); var urlArray = leagues.map(league => { return `http://api.football-data.org/v2/competitions/${league}/matches`; }); this.liveLeagues = []; + var self = this; Promise.all(urlArray.map(url => { return axios.get(url, { headers: self.headers }) .then(function (response) { + //console.log("Requests available: " + response.headers["x-requests-available-minute"]); var matchesData = response.data; - var league = matchesData.competition.code; + var currentLeague = matchesData.competition.code; matchesData.matches.forEach(match => { delete match.referees; + //check for live matches - if (match.status == "IN_PLAY" || Math.abs(moment(match.utcDate).diff(now, 'seconds')) < self.config.apiCallInterval * 10) { - self.log(`Live match detected starting at ${moment(match.utcDate).format("HH:mm")}, Home Team: ${match.homeTeam.name}`); + if (match.status == "IN_PLAY" || Math.abs(moment(match.utcDate).diff(now, 'seconds')) < self.config.apiCallInterval * 2) { if (self.liveMatches.indexOf(match.id) === -1) { - //self.log(`Live match ${match.id} added at ${moment().format("HH:mm")}`); + self.log(`Live match detected starting at ${moment(match.utcDate).format("HH:mm")}, Home Team: ${match.homeTeam.name}`); + self.log(`Live match ${match.id} added at ${moment().format("HH:mm")}`); self.liveMatches.push(match.id); } - if (self.liveLeagues.indexOf(league) === -1) { - self.log(`Live league ${league} added at ${moment().format("HH:mm")}`); - self.liveLeagues.push(league); + if (self.liveLeagues.indexOf(currentLeague) === -1) { + self.log(`Live league ${currentLeague} added at ${moment().format("HH:mm")}`); + self.liveLeagues.push(currentLeague); } } else { if (self.liveMatches.indexOf(match.id)!= -1) { - self.log("Live match finished"); - self.liveMatches.splice(self.liveMatches.indexOf(comp.matches[m].id), 1); + self.log("Live match finished!"); + self.liveMatches.splice(self.liveMatches.indexOf(match.id), 1); } } }); @@ -167,6 +162,7 @@ module.exports = NodeHelper.create({ Promise.all(urlArray.map(url => { return axios.get(url, { headers: self.headers }) .then(function (response) { + console.log("Requests available: " + response.headers["x-requests-available-minute"]); var matchData = response.data; self.log(matchData); if (matchData.match.status != "IN_PLAY" && self.liveMatches.indexOf(matchData.match.id)!= -1) { @@ -192,13 +188,13 @@ module.exports = NodeHelper.create({ handleErrors: function(error, url) { console.log("An error occured while requesting the API for Data: "+error); console.log("URL: "+url); - if (error.response.status === 429) { + if (error.response && error.response.status === 429) { console.log(error.response.status + ": API Request Quota of 10 calls per minute exceeded. Try selecting less leagues."); } else if (error.request) { console.log(error.request); } else { // Something happened in setting up the request that triggered an Error - console.log('Error ', error.message); + console.log('Error: ', error.message); } }, @@ -206,7 +202,7 @@ module.exports = NodeHelper.create({ if (isLive != this.liveMode) { clearInterval(this.callInterval); if (isLive) { - this.log("Live Mode activate!"); + this.log("Live Mode activated!"); //this.leagues = this.liveLeagues; this.sendSocketNotification("LIVE", { live: true, matches: this.liveMatches, leagues: this.liveLeagues }); this.scheduleAPICalls(true); From cd6137d4ed56b0a47b58469abd1ed78e86456747 Mon Sep 17 00:00:00 2001 From: lavolp3 Date: Mon, 22 Mar 2021 14:57:12 +0100 Subject: [PATCH 23/31] several small changes and fix for table focus --- MMM-soccer.css | 25 ++++-- MMM-soccer.js | 154 ++++++++++++++++++++++++++----------- MMM-soccer.njk | 177 +++++++++++++++++++++++-------------------- MMM-soccer.njk.save | 114 ++++++++++++++++++++++++++++ README.md | 42 +++++----- node_helper.js | 16 ++-- replacements.json | 3 +- translations/de.json | 10 ++- translations/en.json | 8 +- 9 files changed, 384 insertions(+), 165 deletions(-) create mode 100644 MMM-soccer.njk.save diff --git a/MMM-soccer.css b/MMM-soccer.css index 44a4c29..f329964 100644 --- a/MMM-soccer.css +++ b/MMM-soccer.css @@ -20,12 +20,9 @@ margin-bottom: 10px; } -.MMM-soccer table { - margin-bottom: 30px; -} - .MMM-soccer .games { table-layout: fixed; + margin-bottom: 20px; } .MMM-soccer .games .status { @@ -35,7 +32,7 @@ color: black; border-radius: 10px; text-align: center; - font-size: 100%; + font-size: 100%; width: 50px; } @@ -50,8 +47,8 @@ .MMM-soccer .logo { width: 25px; - padding: 0px 3px; - vertical-align: middle; + padding: 0px 3px; + vertical-align: middle; } .MMM-soccer .centered-row { @@ -70,6 +67,11 @@ color: yellow; } + +.MMM-soccer .table { + margin: 10px 0px; +} + .MMM-soccer-blur { -webkit-filter: blur(2px) brightness(50%); } @@ -99,3 +101,12 @@ text-overflow: ellipsis; white-space: nowrap; } + +.MMM-soccer .matchName.winner { + font-weight: bold; + #text-decoration: underline; +} + +.MMM-soccer svg { + background-color: #000; +} diff --git a/MMM-soccer.js b/MMM-soccer.js index 81773a2..c739bc9 100644 --- a/MMM-soccer.js +++ b/MMM-soccer.js @@ -12,7 +12,7 @@ /* global Module Log */ Module.register('MMM-soccer', { - + defaults: { api_key: false, colored: false, @@ -26,8 +26,9 @@ Module.register('MMM-soccer', { logos: true, showTables: true, showMatches: true, + showMatchDay: true, matchType: 'league', //choose 'next', 'daily', or 'league' - numberOfNextMatches: 8, + numberOfNextMatches: 8, leagues: { GERMANY: 'BL1', FRANCE: 'FL1', @@ -36,6 +37,7 @@ Module.register('MMM-soccer', { ITALY: 'SA' }, replace: 'default', //choose 'default', 'short' or '' for original names + daysOffset: 0, debug: false, }, @@ -57,14 +59,14 @@ Module.register('MMM-soccer', { loading: true, tables: {}, - matches: {}, + matches: {}, teams: {}, matchDay: "", - showTable: true, + showTable: true, leagues: [], liveMode: false, - liveMatches: [], - liveLeagues: [], + liveMatches: [], + liveLeagues: [], replacements: { default: {} }, @@ -77,8 +79,8 @@ Module.register('MMM-soccer', { this.leagues = this.config.show; this.competition = this.leagues[0]; this.showTable = this.config.showTables; - var self = this; - this.replacers = this.loadReplacements(response => { + var self = this; + this.replacers = this.loadReplacements(response => { self.replacements = JSON.parse(response); //self.log(self.replacements); }); @@ -87,10 +89,10 @@ Module.register('MMM-soccer', { }, - loadReplacements: function(callback) { - this.log("Loading replacements file"); - var xobj = new XMLHttpRequest(), - path = this.file('replacements.json'); + loadReplacements: function(callback) { + this.log("Loading replacements file"); + var xobj = new XMLHttpRequest(); + var path = this.file('replacements.json'); xobj.overrideMimeType("application/json"); xobj.open("GET", path, true); xobj.onreadystatechange = function() { @@ -104,14 +106,15 @@ Module.register('MMM-soccer', { scheduleDOMUpdates: function () { var count = 0; - var _this = this; + var self = this; setInterval(() => { - const comps = _this.leagues.length; + const comps = self.leagues.length; count = (count >= comps - 1) ? 0 : count + 1; - _this.competition = _this.leagues[count]; - _this.log("Showing competition: " + _this.competition); - _this.standing = _this.filterTables(_this.tables[_this.competition], _this.config.focus_on[_this.competition]); - _this.updateDom(500); + self.competition = self.leagues[count]; + self.log("Showing competition: " + self.competition); + self.log(self.tables[self.competition]); + self.standing = self.filterTables(self.tables[self.competition], self.config.focus_on[self.competition]); + self.updateDom(500); }, this.config.updateInterval * 1000); }, @@ -119,12 +122,13 @@ Module.register('MMM-soccer', { socketNotificationReceived: function(notification, payload) { this.log(`received a Socket Notification: ${notification}`); if (notification === 'TABLES') { + this.log(payload); this.tables = payload; this.standing = this.filterTables(this.tables[this.competition], this.config.focus_on[this.competition]); this.log("Current table: " + JSON.stringify(this.standing)); } else if (notification === 'MATCHES') { this.matches = payload; - //this.log(this.matches); + this.log("Received matches: "+this.matches); } else if (notification === 'TEAMS') { this.teams = payload; /*} else if (notification === 'LIVE_MATCHES') { @@ -174,29 +178,46 @@ Module.register('MMM-soccer', { getTemplateData: function() { return { boundaries: (this.tables.hasOwnProperty(this.competition)) ? this.calculateTeamDisplayBoundaries(this.competition) : {}, - competitionName: (Object.keys(this.tables).length > 0) ? this.tables[this.competition].competition.name : "", + matchHeader: this.getMatchHeader(), config: this.config, isModalActive: this.isModalActive(), modals: this.modals, table: this.standing, - matches: (Object.keys(this.matches).length > 0) ? this.prepareMatches(this.matches, this.config.focus_on[this.competition]) : "", - season: (Object.keys(this.tables).length > 0) ? - `${this.translate('MATCHDAY')}: ${this.translate(this.matchDay)}` : this.translate('LOADING'), + comps: (Object.keys(this.matches).length > 0) ? this.prepareMatches(this.matches, this.config.focus_on[this.competition]) : "", showTable: this.showTable, teams: (Object.keys(this.tables).length > 0) ? this.teams : {}, - showMatchDay: (this.config.matchType == "league"), + showMatchDay: this.config.showMatchDay, voice: this.voice }; }, + getMatchHeader: function() { + if (this.config.matchType == "daily") { + return { + competition: this.translate('TODAYS_MATCHES'), + season: (Object.keys(this.tables).length > 0) ? "" : this.translate('LOADING'), + } + } else if (this.config.matchType == "next") { + return { + competition: this.translate('NEXT_MATCHES'), + season: (Object.keys(this.tables).length > 0) ? "" : this.translate('LOADING'), + } + } + return { + competition: (Object.keys(this.tables).length > 0) ? this.tables[this.competition].competition.name : "", + season: (Object.keys(this.tables).length > 0) ? `${this.translate('MATCHDAY')}: ${this.translate(this.matchDay)}` : this.translate('LOADING'), + } + }, + prepareMatches: function(allMatches, focusTeam) { + var returnedMatches = []; if (this.config.matchType === 'league') { var diff = 0; var matches = allMatches[this.competition].matches; var minDiff = Math.abs(moment().diff(matches[0].utcDate)); for (var m = 0; m < matches.length; m++) { - if (!matches[m].matchday) {matches[m].matchday = matches[m].stage; } //for cup modes, copy stage to matchday property + if (!matches[m].matchday) { matches[m].matchday = matches[m].stage; } //for cup modes, copy stage to matchday property diff = Math.abs(moment().diff(matches[m].utcDate)); if (diff < minDiff) { minDiff = diff; @@ -205,11 +226,14 @@ Module.register('MMM-soccer', { } this.log("Current matchday: " + this.matchDay); this.showTable = (!isNaN(this.matchDay)); - - returnedMatches = matches.filter(match => { - return match.matchday == this.matchDay; + returnedMatches.push({ + competition: (Object.keys(this.tables).length > 0) ? this.tables[this.competition].competition.name : "", + season: (Object.keys(this.tables).length > 0) ? `${this.translate('MATCHDAY')}: ${this.translate(this.matchDay)}` : this.translate('LOADING'), + matches: matches.filter(match => { + return match.matchday == this.matchDay; + }) }); - } else if (this.config.matchType === "next") { + } else if (this.config.matchType === 'next') { var teams = []; var nextMatches = []; for (var comp in this.config.focus_on) { @@ -220,7 +244,7 @@ Module.register('MMM-soccer', { return (teams.includes(match.homeTeam.name) || teams.includes(match.awayTeam.name)); }); var index = filteredMatches.findIndex(match => { - return (moment(match.utcDate) > moment()); + return (parseInt(moment(match.utcDate).format("X")) > parseInt(moment().subtract(3, 'days').format("X"))); }); for (var i = index - 1; i < filteredMatches.length; i++) { nextMatches.push(filteredMatches[i]); @@ -229,24 +253,65 @@ Module.register('MMM-soccer', { nextMatches.sort(function (match1, match2) { return (moment(match1.utcDate) - moment(match2.utcDate)); }); - returnedMatches = nextMatches.slice(0, numberOfNextMatches); - } - returnedMatches.forEach(match => { - match.focused = (match.homeTeam.name === focusTeam) ? true : (match.awayTeam.name === focusTeam) ? true : false; - if (match.status == "SCHEDULED" || match.status == "POSTPONED") { - match.state = (moment(match.utcDate).diff(moment(), 'days') > 7) ? moment(match.utcDate).format("D.MM.") : (moment(match.utcDate).startOf('day') > moment()) ? moment(match.utcDate).format("dd") : moment(match.utcDate).format("LT"); - } else { - match.state = match.score.fullTime.homeTeam + " - " + match.score.fullTime.awayTeam; + returnedMatches.push({ + competition: this.translate('NEXT_MATCHES'), + season: (Object.keys(this.tables).length > 0) ? "" : this.translate('LOADING'), + matches: nextMatches.slice(0, this.config.numberOfNextMatches) + }); + + } else if (this.config.matchType === 'daily') { + var today = moment().subtract(this.config.daysOffset, 'days'); + var todaysMatches = []; + for (var league in allMatches) { + var filteredMatches = allMatches[league].matches.filter(match => { + return ( moment(match.utcDate).isSame(today, 'day') ); + }); + this.log("Filtered macthes: "); + this.log(filteredMatches); + if (filteredMatches.length) { + returnedMatches.push({ + competition: (Object.keys(this.tables).length > 0) ? this.tables[league].competition.name : "", + season: (Object.keys(this.tables).length > 0) ? "" : this.translate('LOADING'), + matches: filteredMatches + }); + } } + /*todaysMatches = todaysMatches.flat(); + todaysMatches.sort(function (match1, match2) { + return (match1.season.id - match2.season.id); + }); + returnedMatches.push({ + competition: this.translate('TODAYS_MATCHES'), + season: (Object.keys(this.tables).length > 0) ? "" : this.translate('LOADING'), + matches: todaysMatches + });*/ + } + returnedMatches.forEach(matchset => { + matchset.matches.forEach(match => { + if (this.config.matchType == "league" || this.config.matchType == "daily") { + match.focused = (match.homeTeam.name === focusTeam) ? true : (match.awayTeam.name === focusTeam) ? true : false; + } + if (match.status == "SCHEDULED" || match.status == "POSTPONED") { + match.state = (moment(match.utcDate).diff(moment(), 'days') > 7) ? moment(match.utcDate).format("D.MM.") : (moment(match.utcDate).startOf('day') > moment()) ? moment(match.utcDate).format("dd") : moment(match.utcDate).format("LT"); + } else { + match.state = match.score.fullTime.homeTeam + " - " + match.score.fullTime.awayTeam; + if (match.score.winner == "HOME_TEAM") { + match.homeTeam["status"] = "winner" + } else if (match.score.winner == "AWAY_TEAM") { + match.awayTeam["status"] = "winner" + } + } + }); }); - //this.log("Returned matches: "+JSON.stringify(returnedMatches)); + this.log("Returned matches:"); + this.log(returnedMatches); return returnedMatches; }, filterTables: function(tables, focusTeam) { //filtering out "home" and "away" tables - if (!tables.standings) return ""; + if (tables && !tables.standings) return ""; tableArray = tables.standings.filter(table => { return table.type === "TOTAL"; }); @@ -267,9 +332,9 @@ Module.register('MMM-soccer', { findFocusTeam: function() { this.log("Finding focus team for table..."); - let focusTeamIndex; + let focusTeamIndex = -1; var table = this.standing; - for (let i = 0; i < table.length; i += 1) { + for (let i = 0; i < table.length; i ++) { if (table[i].team.name === this.config.focus_on[this.competition]) { focusTeamIndex = i; this.log("Focus Team found: " + table[i].team.name); @@ -277,7 +342,7 @@ Module.register('MMM-soccer', { } } - if (!focusTeamIndex) { + if (focusTeamIndex < 0) { this.log("No Focus Team found! Please check your entry!"); return { focusTeamIndex: -1, @@ -297,7 +362,7 @@ Module.register('MMM-soccer', { if (this.config.max_teams) { const before = parseInt(this.config.max_teams / 2); - firstTeam = index - before >= 0 ? index - before : 0; + firstTeam = (index - before >= 0) ? (index - before) : 0; if (firstTeam + this.config.max_teams <= this.standing.length) { lastTeam = firstTeam + this.config.max_teams; } else { @@ -309,6 +374,7 @@ Module.register('MMM-soccer', { firstTeam = 0; lastTeam = this.standing.length; } + this.log({firstTeam, lastTeam}); return { firstTeam, lastTeam }; }, diff --git a/MMM-soccer.njk b/MMM-soccer.njk index b2db75c..1d92b54 100644 --- a/MMM-soccer.njk +++ b/MMM-soccer.njk @@ -1,103 +1,116 @@
-
MMM-Soccer
- {% if loading %} - {{'LOADING' | translate}} - {% else %} - - {% if showMatchDay %} -
{{competitionName}}
-
{{season}}
- {% endif %} +
MMM-Soccer
+ +{% if loading %} + {{'LOADING' | translate}} +{% else %} {% if config.showMatches %} -
- - {% for i in range(0, matches.length) %} - - - {% if config.logos %} - - {% endif %} - +
+ {% if comps.length %} + {% for i in range(0, comps.length) %} +
{{matches[i].homeTeam.name | replace}}{{ matches[i].state }} -
+ + {{ comps[i].competition }} + {{ comps[i].season }} + {% for m in range(0, comps[i].matches.length) %} + + + {% if config.logos %} + + {% endif %} + + {% if config.logos %} + + {% endif %} + + + {% endfor %} + +
{{comps[i].matches[m].homeTeam.name | replace}}{{ comps[i].matches[m].state }}{{comps[i].matches[m].awayTeam.name | replace}}
+ {% endfor %} + {% else %} + + {{ 'NO_MATCHES' | translate }} + + {% endif %} +
+ {% endif %} + + {% if showTable %} + + + + {% if config.logos %} - + {% endif %} - + + + - {% endfor %} - -
{{matches[i].awayTeam.name | replace}}{{'TEAM' | translate}}
- {% endif %} - {% if showTable %} - - - - + + + {% for i in range(boundaries.firstTeam, boundaries.lastTeam) %} + + {% if config.logos %} - + {% endif %} - - - + + + - - - {% for i in range(boundaries.firstTeam, boundaries.lastTeam) %} - - - {% if config.logos %} - - {% endif %} - - - - - {% endfor %} - -
{{table[i].position}}{{'TEAM' | translate}}{{table[i].team.name | replace}}{{table[i].points}}{{table[i].goalDifference}}
{{table[i].position}}{{table[i].team.name | replace}}{{table[i].points}}{{table[i].goalDifference}}
- {% endif %} + {% endfor %} + + {% endif %} +{% endif %}
{% if isModalActive %} - {% if modal.standings %} {% endif %} diff --git a/MMM-soccer.njk.save b/MMM-soccer.njk.save new file mode 100644 index 0000000..653bfa2 --- /dev/null +++ b/MMM-soccer.njk.save @@ -0,0 +1,114 @@ +
+
MMM-Soccer
+ +{% if loading %} + {{'LOADING' | translate}} +{% else %} + {% if config.showMatches %} + + + {% if comps.length %} + {% for i in range(0, comps.length) %} + + + {% for m in range(0, comps[i].matches.length) %} + + + {% if config.logos %} + + {% endif %} + + {% if config.logos %} + + {% endif %} + + + {% endfor %} + {% endfor %} + {% else %} + + + + {% endif %} + +
{{ comps[i].competition }}
{{ comps[i].season }}
{{comps[i].matches[m].homeTeam.name | replace}}{{ comps[i].matches[m].state }}{{comps[i].matches[m].awayTeam.name | replace}}
{{ 'NO_MATCHES' | translate }}
+ {% endif %} + + {% if showTable %} + + + + + {% if config.logos %} + + {% endif %} + + + + + + + {% for i in range(boundaries.firstTeam, boundaries.lastTeam) %} + + + {% if config.logos %} + + {% endif %} + + + + + {% endfor %} + +
{{'TEAM' | translate}}
{{table[i].position}}{{table[i].team.name | replace}}{{table[i].points}}{{table[i].goalDifference}}
+ {% endif %} +{% endif %} +
+ + +{% if isModalActive %} + +{% endif %} diff --git a/README.md b/README.md index 1b08e74..2368c88 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,11 @@ A Soccer Standings Module for MagicMirror², based on @fewiedens [MMM-soccer](ht ## Installation 1. Clone this repo into your `~/MagicMirror/modules` directory. -```git clone https://github.com/lavolp3/MMM-soccer``` +``` +git clone https://github.com/lavolp3/MMM-soccer +``` 2. Run command `npm install` in `~/MagicMirror/modules/MMM-soccer` directory. -3. Configure your `~/MagicMirror/config/config.js`: +3. Add the module to your `~/MagicMirror/config/config.js`: ``` { @@ -51,17 +53,17 @@ A Soccer Standings Module for MagicMirror², based on @fewiedens [MMM-soccer](ht | `colored` | true | Boolean to show club logos in color or not. | | `show` | ['BL1', 'PL', 'CL'] | An array of league codes to be displayed. In normal mode, the leagues revolve using below update cycle. With activated touch mode (see below), you can choose one of the leagues via a button (planned) | | `updateInterval` | 60 | The time frame for each league to be shown in seconds. | -| `apiCallInterval` | 10 | The time frame for API calls in normal mode. | +| `apiCallInterval` | 10 | The time frame for API calls (in minutes) in normal mode. | | `showMatches` | true | Show matches of current league | -| `showTables` | true | Show table of current league. *Remark*: For cups like Champions league, this will be set to false in knockout mode. | -| `focus_on` | null | Which team should to focus on per league. This needs to be an object, e.g. {'BL1': 'FC Bayern München', 'CL': 'Liverpool FC'}. See description below. | +| `showTables` | true | Show table of current league. **Note:** For cups like Champions League, this will be set to false in knockout rounds. | +| `focus_on` | null | Which team to focus on per league. This needs to be an object, e.g. {'BL1': 'FC Bayern München', 'CL': 'Liverpool FC'}. **See description below.** | | `fadeFocus` | true | Includes fading the teams out if one is focused. | | `max_teams` | false | How many teams should be displayed when focus is activated. Omit this option or set to false to show the full league table. | -| `replace` | 'default' | Choose between 'default' for a default replacement of original club names or 'short' for a 3-Letter-Code of the teams. Choose anything else (like '') for original team names from the API. See below for further information | +| `replace` | 'default' | Choose between 'default' for a default replacement of original club names or 'short' for a 3-Letter-Code of the teams. Choose anything else (like '') for original team names from the API. **See below** for further information | | `logos` | true | Boolean to show club logos. | -| `liveMode` | true | Activates live mode when games are in play. (see below, not active yet) | -| `matchType` | 'league' | Choose between the following: 'league' for showing the current matchday of selected leagues (in `show`), 'next' for showing the next matches of all your focused clubs (in `focus_on`), 'daily' for showing all of todays matches for selected leagues. | -| `numberOfNextMatches` | 8 | Defines number of next matches of all focused clubs for matchType `next` | +| `liveMode` | true | Activates live mode when games are in play. (see below) | +| `matchType` | 'league' | Choose between the following: `'league'` for showing the current matchday of selected leagues (in `show`), `'next'` for showing the next matches of all your focused clubs (in `focus_on`), `'daily'` for showing all of todays matches for selected leagues. | +| `numberOfNextMatches` | 8 | Defines number of next matches of all focused clubs for matchType `'next'` | | `touchMode` | false | Activates touch mode with touch options (see below, not active yet) | | `debug` | false | Debug mode: additional output on server side (console) and client side (browser) | @@ -76,20 +78,20 @@ focus_on: { 'CL': 'Liverpool FC' }, ``` -Please take care to include all quotation marks, separate with commata, and use the same league codes (find below) you have included in the 'show' array. -The team name needs to correspond to the original name of the team as provided by the API. -Have a look into the ```replace``` object in the config to see if the team name is replaced with a shorter one on the mirror. If that is the case, take the original one (the one on the left for each replace property). +Please take care to include all quotation marks, separate with commata, and use the same league codes (find below) you have included in the 'show' array. +The team name needs to correspond to the original name of the team as provided by the API. +Have a look into the `replace` object in the config to see if the team name is replaced with a shorter one on the mirror. If that is the case, take the original one (the one on the left for each replace property). -Omitting a league code from 'show' in this array will show the full league table and not include any focus. -Any league included here need to be included in 'show' as well to show the league on your mirror. +Omitting a league code from `'show'` in this array will show the full league table and not include any focus. +Any league included here need to be included in `'show'` as well to show the league on your mirror. ## Replacements There is a `replacements.json` file in the directory including all teams of the free plan. By default, the default replacement for the original team name will be used in the module. You can choose between 'default' mode or 'short' mode showing the 3-letter ID code for the team for a super slim module. ## Live Mode -The module calls all requested matches every X minutes (see config option apiCallInterval). Whenever one or more matches are scheduled in less than this interval, a Live Mode will activate. -All matches currently played will be included in an array and requested every minute. +The module calls all requested matches every X minutes (see config option `apiCallInterval`). Whenever one or more matches are scheduled in less than this interval, a Live Mode will activate. +All matches currently played will be included in an array and requested once every minute. ~Additional informations like game minute and scorers will be provided for these games.~ (another API is needed for this) Also, only the leagues with current matches will be shown. When no game is live, the module will return back to normal mode. @@ -105,7 +107,7 @@ It is also planned to include more detailed information like scorers per league Can be switched off in config. -## OPTIONAL: Voice Control (may be buggy!) +## OPTIONAL: Voice Control (may be bugged!) This module supports voice control by @fewiedens [MMM-voice](https://github.com/fewieden/MMM-voice). In order to use this feature, it's required to install the voice module. There are no extra config options for voice control needed. @@ -133,8 +135,8 @@ As per the [Football-data API Docs](https://www.football-data.org/documentation/ | **League** | **Code** | | --- | --- | -| (Europe) Champions League | 'CL1' | -| (Europe) European Championships 2020 | 'EC' | +| (Europe) Champions League | 'CL' | +| (Europe) European Championship 2020 | 'EC' | | (English) Premier League | 'PL' | | (English) Championship | 'ELC' | | (German) Bundesliga | 'BL1' | @@ -152,7 +154,7 @@ As per the [Football-data API Docs](https://www.football-data.org/documentation/ - [ ] Touch mode - [ ] Tap additional API (presumably API-football) for further competitions (e.g. DFB cup) - [ ] Option to show fixed table head with focus on. -- [ ] Highlight currently playing teams in table. +- [x] Highlight currently playing teams in table. Add team specific data, e.g. diff --git a/node_helper.js b/node_helper.js index 11e96e5..db8cfd2 100644 --- a/node_helper.js +++ b/node_helper.js @@ -21,6 +21,7 @@ module.exports = NodeHelper.create({ teamList: {}, liveMatches: [], liveLeagues: [], + isRunning: false, start: function() { console.log(`Starting module: ${this.name}`); @@ -30,14 +31,17 @@ module.exports = NodeHelper.create({ socketNotificationReceived: function(notification, payload) { if (notification === 'GET_SOCCER_DATA') { this.log("Socket notification received: " + notification + " Payload: " + JSON.stringify(payload)); - this.log("Starting API call cycle"); this.config = payload; + this.leagues = this.config.show; this.headers = payload.api_key ? { 'X-Auth-Token': payload.api_key } : {}; - this.leagues = this.config.show; this.getTables(this.leagues); this.getMatches(this.leagues); - this.liveMode = false; - this.scheduleAPICalls(false); + if (!this.isRunning) { + this.log("Starting API call cycle"); + this.liveMode = false; + this.isRunning = true; + this.scheduleAPICalls(false); + } } }, @@ -98,7 +102,7 @@ module.exports = NodeHelper.create({ }, getMatches: function(leagues) { - var now = moment().subtract(0, "minutes"); + var now = moment().subtract(60*13, "minutes"); //subtract minutes or hours to test live mode this.log("Collecting matches for leagues: " + leagues); var urlArray = leagues.map(league => { return `http://api.football-data.org/v2/competitions/${league}/matches`; }); this.liveLeagues = []; @@ -111,7 +115,7 @@ module.exports = NodeHelper.create({ var currentLeague = matchesData.competition.code; matchesData.matches.forEach(match => { delete match.referees; - + //check for live matches if (match.status == "IN_PLAY" || Math.abs(moment(match.utcDate).diff(now, 'seconds')) < self.config.apiCallInterval * 2) { if (self.liveMatches.indexOf(match.id) === -1) { diff --git a/replacements.json b/replacements.json index 2431790..565f672 100644 --- a/replacements.json +++ b/replacements.json @@ -44,6 +44,7 @@ "Hertha BSC":"Hertha BSC", "1. FSV Mainz 05":"FSV Mainz", "TSV Fortuna 95 Düsseldorf":"Fortuna Düsseldorf", + "DSC Arminia Bielefeld": "Arminia Bielefeld", "SV Werder Bremen":"Werder Bremen", "SC Paderborn 07":"SC Paderborn", "Leicester City FC":"Leicester City", @@ -341,4 +342,4 @@ "ADO Den Haag":"ADO", "RKC Waalwijk":"WAA" } -} \ No newline at end of file +} diff --git a/translations/de.json b/translations/de.json index debbaa2..3ac7dfd 100644 --- a/translations/de.json +++ b/translations/de.json @@ -1,13 +1,17 @@ { "LOADING": "Lade...", "NO_DATA_AVAILABLE": "Keine Daten verfügbar!", + "NO_MATCHES": "Keine Spiele", + "TODAYS_MATCHES": "Heute", + "NEXT_MATCHES": "Nächste Spiele", "MATCHDAY": "Spieltag", "TEAM": "Mannschaft", "COMMAND_LIST": "Liste aller Sprachbefehle", "MODE": "Modus", "VOICE_COMMANDS": "Sprachbefehle", + "PLAY_OFF_ROUND": "Play-Off-Runde", "ROUND_OF_16": "Achtelfinale", - "ROUND_OF_8": "Viertelfinale", - "ROUND_OF_4": "Halbfinale", + "QUARTER_FINALS": "Viertelfinale", + "SEMI_FINALS": "Halbfinale", "FINAL": "Finale" -} \ No newline at end of file +} diff --git a/translations/en.json b/translations/en.json index 34613e5..1d42126 100644 --- a/translations/en.json +++ b/translations/en.json @@ -1,13 +1,17 @@ { - "LOADING": "loading...", + "LOADING": "Loading...", "NO_DATA_AVAILABLE": "No data available!", + "NO_MATCHES": "No matches", + "TODAYS_MATCHES": "Today", + "NEXT_MATCHES": "Next Matches", "MATCHDAY": "Matchday", "TEAM": "Team", "COMMAND_LIST": "List of all Voice Commands", "MODE": "Mode", "VOICE_COMMANDS": "Voice Commands", + "PLAY_OFF_ROUND": "Play-off round", "ROUND_OF_16": "Round of 16", "ROUND_OF_8": "Round of 8", "ROUND_OF_4": "Semi Finals", "FINAL": "Finals" -} \ No newline at end of file +} From 378b472c54129617977247243d4c48ff6d2e3687 Mon Sep 17 00:00:00 2001 From: lavolp3 Date: Mon, 22 Mar 2021 14:57:53 +0100 Subject: [PATCH 24/31] deleted unnecessary file --- MMM-soccer.njk.save | 114 -------------------------------------------- 1 file changed, 114 deletions(-) delete mode 100644 MMM-soccer.njk.save diff --git a/MMM-soccer.njk.save b/MMM-soccer.njk.save deleted file mode 100644 index 653bfa2..0000000 --- a/MMM-soccer.njk.save +++ /dev/null @@ -1,114 +0,0 @@ -
-
MMM-Soccer
- -{% if loading %} - {{'LOADING' | translate}} -{% else %} - {% if config.showMatches %} - - - {% if comps.length %} - {% for i in range(0, comps.length) %} - - - {% for m in range(0, comps[i].matches.length) %} - - - {% if config.logos %} - - {% endif %} - - {% if config.logos %} - - {% endif %} - - - {% endfor %} - {% endfor %} - {% else %} - - - - {% endif %} - -
{{ comps[i].competition }}
{{ comps[i].season }}
{{comps[i].matches[m].homeTeam.name | replace}}{{ comps[i].matches[m].state }}{{comps[i].matches[m].awayTeam.name | replace}}
{{ 'NO_MATCHES' | translate }}
- {% endif %} - - {% if showTable %} - - - - - {% if config.logos %} - - {% endif %} - - - - - - - {% for i in range(boundaries.firstTeam, boundaries.lastTeam) %} - - - {% if config.logos %} - - {% endif %} - - - - - {% endfor %} - -
{{'TEAM' | translate}}
{{table[i].position}}{{table[i].team.name | replace}}{{table[i].points}}{{table[i].goalDifference}}
- {% endif %} -{% endif %} -
- - -{% if isModalActive %} - -{% endif %} From 28810e9abced93f5f7b9934fb8cbf01bab724645 Mon Sep 17 00:00:00 2001 From: lavolp3 Date: Mon, 22 Mar 2021 17:10:28 +0100 Subject: [PATCH 25/31] fixed results table --- MMM-soccer.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MMM-soccer.css b/MMM-soccer.css index f329964..46f01d3 100644 --- a/MMM-soccer.css +++ b/MMM-soccer.css @@ -21,7 +21,6 @@ } .MMM-soccer .games { - table-layout: fixed; margin-bottom: 20px; } @@ -46,8 +45,9 @@ } .MMM-soccer .logo { + max-width: 25px; width: 25px; - padding: 0px 3px; + padding: 0px 8px; vertical-align: middle; } From 77f64cf810b9acb75fab995deba17ce48840dd47 Mon Sep 17 00:00:00 2001 From: lavolp3 Date: Mon, 22 Mar 2021 17:14:15 +0100 Subject: [PATCH 26/31] rewind nextmatches date subtraction --- MMM-soccer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MMM-soccer.js b/MMM-soccer.js index c739bc9..c658f76 100644 --- a/MMM-soccer.js +++ b/MMM-soccer.js @@ -244,7 +244,7 @@ Module.register('MMM-soccer', { return (teams.includes(match.homeTeam.name) || teams.includes(match.awayTeam.name)); }); var index = filteredMatches.findIndex(match => { - return (parseInt(moment(match.utcDate).format("X")) > parseInt(moment().subtract(3, 'days').format("X"))); + return (parseInt(moment(match.utcDate).format("X")) > parseInt(moment().format("X"))); }); for (var i = index - 1; i < filteredMatches.length; i++) { nextMatches.push(filteredMatches[i]); From 33b6ee732262192a6af792c213467e0876a76b28 Mon Sep 17 00:00:00 2001 From: lavolp3 Date: Wed, 24 Mar 2021 10:09:23 +0100 Subject: [PATCH 27/31] added games and positive scoring in table --- MMM-soccer.njk | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/MMM-soccer.njk b/MMM-soccer.njk index 1d92b54..cc84225 100644 --- a/MMM-soccer.njk +++ b/MMM-soccer.njk @@ -48,20 +48,23 @@ {% endif %} {{'TEAM' | translate}} - + + {% for i in range(boundaries.firstTeam, boundaries.lastTeam) %} + {{table[i].position}} {% if config.logos %} {% endif %} {{table[i].team.name | replace}} + {{table[i].playedGames}} {{table[i].points}} - {{table[i].goalDifference}} + {% if table[i].goalDifference > 0 %}+{% endif %}{{table[i].goalDifference}} {% endfor %} From 8ce42ea768014ba927d2afde4cab73ec4787e896 Mon Sep 17 00:00:00 2001 From: lavolp3 Date: Mon, 10 May 2021 13:00:21 +0200 Subject: [PATCH 28/31] pushed axios to 0.21 --- package-lock.json | 3197 +-------------------------------------------- package.json | 2 +- 2 files changed, 38 insertions(+), 3161 deletions(-) diff --git a/package-lock.json b/package-lock.json index 545d6d5..eef4e56 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,3181 +1,58 @@ { "name": "mmm-soccer", - "version": "1.0.1", - "lockfileVersion": 1, + "version": "1.0.0", + "lockfileVersion": 2, "requires": true, - "dependencies": { - "JSONStream": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.8.4.tgz", - "integrity": "sha1-kWV9/m/4V0gwZhMrRhi2Lo9Ih70=", - "dev": true, - "requires": { - "jsonparse": "0.0.5", - "through": ">=2.2.7 <3" - } - }, - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "requires": { - "acorn": "^3.0.4" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - } - } - }, - "ajv": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", - "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", - "dev": true - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, - "ansi-escapes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, - "array-includes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", - "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0", - "is-string": "^1.0.5" - } - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "array.prototype.flat": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", - "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - } - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "autoprefixer": { - "version": "6.7.7", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", - "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", - "dev": true, - "requires": { - "browserslist": "^1.7.6", - "caniuse-db": "^1.0.30000634", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^5.2.16", - "postcss-value-parser": "^3.2.3" - } - }, - "axios": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", - "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", - "requires": { - "follow-redirects": "1.5.10" - } - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - } - }, - "balanced-match": { + "packages": { + "": { + "name": "mmm-soccer", "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - } - }, - "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", - "dev": true, - "requires": { - "caniuse-db": "^1.0.30000639", - "electron-to-chromium": "^1.2.7" - } - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "^0.2.0" - } - }, - "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, - "caniuse-db": { - "version": "1.0.30001024", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30001024.tgz", - "integrity": "sha512-dmwZ7u58E68UCexHf92QERFL8kwwCv0TVS1LCNluhZo+565AXU5uNtnPF+J5E2MExwWJeNnhTD63BH8ncMV09g==", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true - }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, - "requires": { - "restore-cursor": "^1.0.1" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "clone-regexp": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-1.0.1.tgz", - "integrity": "sha512-Fcij9IwRW27XedRIJnSOEupS7RVcXtObJXbcUOX93UCLqqOdRpkvzKywOOSizmEK/Is3S/RHX9dLdfo6R1Q1mw==", - "dev": true, - "requires": { - "is-regexp": "^1.0.0", - "is-supported-regexp-flag": "^1.0.0" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-diff": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/color-diff/-/color-diff-0.1.7.tgz", - "integrity": "sha1-bbeM2UgqjkWdQIIer0tQMoPcuOI=", - "dev": true - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "colorguard": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/colorguard/-/colorguard-1.2.1.tgz", - "integrity": "sha512-qYVKTg626qpDg4/eBnPXidEPXn5+krbYqHVfyyEFBWV5z3IF4p44HKY/eE2t1ohlcrlIkDgHmFJMfQ8qMLnSFw==", - "dev": true, - "requires": { - "chalk": "^1.1.1", - "color-diff": "^0.1.3", - "log-symbols": "^1.0.2", - "object-assign": "^4.0.1", - "pipetteur": "^2.0.0", - "plur": "^2.0.0", - "postcss": "^5.0.4", - "postcss-reporter": "^1.2.1", - "text-table": "^0.2.0", - "yargs": "^1.2.6" - }, - "dependencies": { - "postcss-reporter": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-1.4.1.tgz", - "integrity": "sha1-wTbwpbFhkV83ndN2XGEHX357mvI=", - "dev": true, - "requires": { - "chalk": "^1.0.0", - "lodash": "^4.1.0", - "log-symbols": "^1.0.2", - "postcss": "^5.0.0" - } - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cosmiconfig": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.2.2.tgz", - "integrity": "sha512-GiNXLwAFPYHy25XmTPpafYvn3CLAkJ8FLsscq78MQd1Kh0OU6Yzhn4eV2MVF4G9WEQZoWEGltatdR+ntGPMl5A==", - "dev": true, - "requires": { - "is-directory": "^0.3.1", - "js-yaml": "^3.4.3", - "minimist": "^1.2.0", - "object-assign": "^4.1.0", - "os-homedir": "^1.0.1", - "parse-json": "^2.2.0", - "require-from-string": "^1.1.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "css-color-names": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.3.tgz", - "integrity": "sha1-3gzvFvTYqoIioyDVttfpu62nufY=", - "dev": true - }, - "css-rule-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/css-rule-stream/-/css-rule-stream-1.1.0.tgz", - "integrity": "sha1-N4bnGYmD2WWibjGVfgkHjLt3BaI=", - "dev": true, - "requires": { - "css-tokenize": "^1.0.1", - "duplexer2": "0.0.2", - "ldjson-stream": "^1.2.1", - "through2": "^0.6.3" - } - }, - "css-tokenize": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/css-tokenize/-/css-tokenize-1.0.1.tgz", - "integrity": "sha1-RiXLHtohwUOFi3+B1oA8HSb8FL4=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^1.0.33" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "doiuse": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/doiuse/-/doiuse-2.6.0.tgz", - "integrity": "sha1-GJLRC2Gpo1at2/K2FJM+gfi7ODQ=", - "dev": true, - "requires": { - "browserslist": "^1.1.1", - "caniuse-db": "^1.0.30000187", - "css-rule-stream": "^1.1.0", - "duplexer2": "0.0.2", - "jsonfilter": "^1.1.2", - "ldjson-stream": "^1.2.1", - "lodash": "^4.0.0", - "multimatch": "^2.0.0", - "postcss": "^5.0.8", - "source-map": "^0.4.2", - "through2": "^0.6.3", - "yargs": "^3.5.4" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - }, - "yargs": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", - "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", - "dev": true, - "requires": { - "camelcase": "^2.0.1", - "cliui": "^3.0.3", - "decamelize": "^1.1.1", - "os-locale": "^1.4.0", - "string-width": "^1.0.1", - "window-size": "^0.1.4", - "y18n": "^3.2.0" - } - } - } - }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", - "dev": true - }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "~1.1.9" - }, + "license": "MIT", "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "electron-to-chromium": { - "version": "1.3.344", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.344.tgz", - "integrity": "sha512-tvbx2Wl8WBR+ym3u492D0L6/jH+8NoQXqe46+QhbWH3voVPauGuZYeb1QAXYoOAWuiP2dbSvlBx0kQ1F3hu/Mw==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.17.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", - "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" + "axios": "^0.21.1" } }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-map": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-set": "~0.1.5", - "es6-symbol": "~3.1.1", - "event-emitter": "~0.3.5" - } - }, - "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "~0.3.5" - }, + "node_modules/axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", "dependencies": { - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - } - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "escope": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true, - "requires": { - "es6-map": "^0.1.3", - "es6-weak-map": "^2.0.1", - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "eslint": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", - "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", - "dev": true, - "requires": { - "babel-code-frame": "^6.16.0", - "chalk": "^1.1.3", - "concat-stream": "^1.5.2", - "debug": "^2.1.1", - "doctrine": "^2.0.0", - "escope": "^3.6.0", - "espree": "^3.4.0", - "esquery": "^1.0.0", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "glob": "^7.0.3", - "globals": "^9.14.0", - "ignore": "^3.2.0", - "imurmurhash": "^0.1.4", - "inquirer": "^0.12.0", - "is-my-json-valid": "^2.10.0", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.5.1", - "json-stable-stringify": "^1.0.0", - "levn": "^0.3.0", - "lodash": "^4.0.0", - "mkdirp": "^0.5.0", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.1", - "pluralize": "^1.2.1", - "progress": "^1.1.8", - "require-uncached": "^1.0.2", - "shelljs": "^0.7.5", - "strip-bom": "^3.0.0", - "strip-json-comments": "~2.0.1", - "table": "^3.7.8", - "text-table": "~0.2.0", - "user-home": "^2.0.0" - } - }, - "eslint-config-airbnb-base": { - "version": "11.3.2", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.3.2.tgz", - "integrity": "sha512-/fhjt/VqzBA2SRsx7ErDtv6Ayf+XLw9LIOqmpBuHFCVwyJo2EtzGWMB9fYRFBoWWQLxmNmCpenNiH0RxyeS41w==", - "dev": true, - "requires": { - "eslint-restricted-globals": "^0.1.1" - } - }, - "eslint-import-resolver-node": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz", - "integrity": "sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" + "follow-redirects": "^1.10.0" } }, - "eslint-module-utils": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz", - "integrity": "sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.0" - } - }, - "eslint-plugin-import": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz", - "integrity": "sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw==", - "dev": true, - "requires": { - "array-includes": "^3.0.3", - "array.prototype.flat": "^1.2.1", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.2", - "eslint-module-utils": "^2.4.1", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.0", - "read-pkg-up": "^2.0.0", - "resolve": "^1.12.0" - }, - "dependencies": { - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } + "node_modules/follow-redirects": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", + "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" } - } - }, - "eslint-restricted-globals": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz", - "integrity": "sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc=", - "dev": true - }, - "espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true, - "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "dev": true, - "requires": { - "estraverse": "^4.0.0" - } - }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "execall": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execall/-/execall-1.0.0.tgz", - "integrity": "sha1-c9CQTjlbPKsGWLCNCewlMH8pu3M=", - "dev": true, - "requires": { - "clone-regexp": "^1.0.0" - } - }, - "exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", - "dev": true - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "^0.1.0" - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, - "requires": { - "fill-range": "^2.1.0" - } - }, - "ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "requires": { - "type": "^2.0.0" + ], + "engines": { + "node": ">=4.0" }, - "dependencies": { - "type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", - "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", - "dev": true + "peerDependenciesMeta": { + "debug": { + "optional": true } } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } - }, - "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true, - "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" - } - }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, - "fill-range": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", - "dev": true, - "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "flat-cache": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", - "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", - "dev": true, + } + }, + "dependencies": { + "axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", "requires": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" + "follow-redirects": "^1.10.0" } }, - "flatten": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", - "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", - "dev": true - }, "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "requires": { - "debug": "=3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - } - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "gather-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gather-stream/-/gather-stream-1.0.0.tgz", - "integrity": "sha1-szmUr0V6gRVwDUEPMXczy+egkEs=", - "dev": true - }, - "generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "dev": true, - "requires": { - "is-property": "^1.0.2" - } - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "^1.0.0" - } - }, - "get-stdin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", - "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", - "dev": true - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" - } - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "^2.0.0" - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "globjoin": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", - "integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=", - "dev": true - }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "hosted-git-info": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", - "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", - "dev": true - }, - "html-tags": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", - "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", - "dev": true - }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, - "indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "inquirer": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", - "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", - "dev": true, - "requires": { - "ansi-escapes": "^1.1.0", - "ansi-regex": "^2.0.0", - "chalk": "^1.0.0", - "cli-cursor": "^1.0.1", - "cli-width": "^2.0.0", - "figures": "^1.3.5", - "lodash": "^4.3.0", - "readline2": "^1.0.1", - "run-async": "^0.1.0", - "rx-lite": "^3.1.2", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.0", - "through": "^2.3.6" - } - }, - "interpret": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", - "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "irregular-plurals": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-1.4.0.tgz", - "integrity": "sha1-LKmwM2UREYVUEvFr5dd8YqRYp2Y=", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", - "dev": true - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, - "requires": { - "is-primitive": "^2.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "is-my-ip-valid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", - "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", - "dev": true - }, - "is-my-json-valid": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz", - "integrity": "sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA==", - "dev": true, - "requires": { - "generate-function": "^2.0.0", - "generate-object-property": "^1.1.0", - "is-my-ip-valid": "^1.0.0", - "jsonpointer": "^4.0.0", - "xtend": "^4.0.0" - } - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, - "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", - "dev": true - }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true - }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true - }, - "is-supported-regexp-flag": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.1.tgz", - "integrity": "sha512-3vcJecUUrpgCqc/ca0aWeNu64UGgxcvO60K/Fkr1N6RSvfGCTU60UKN68JDmKokgba0rFFJs12EnzOQa14ubKQ==", - "dev": true - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - }, - "js-base64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", - "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==", - "dev": true - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "~0.0.0" - } - }, - "jsonfilter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/jsonfilter/-/jsonfilter-1.1.2.tgz", - "integrity": "sha1-Ie987cdRk4E8dZMulqmL4gW6WhE=", - "dev": true, - "requires": { - "JSONStream": "^0.8.4", - "minimist": "^1.1.0", - "stream-combiner": "^0.2.1", - "through2": "^0.6.3" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonparse": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", - "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=", - "dev": true - }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "known-css-properties": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.2.0.tgz", - "integrity": "sha512-UTCzU28rRI9wkb8qSGoZa9pgWvxr4LjP2MEhi9XHb/1XMOJy0uTnIxaxzj8My/PORG+kQG6VzAcGvRw66eIOfA==", - "dev": true - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "ldjson-stream": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ldjson-stream/-/ldjson-stream-1.2.1.tgz", - "integrity": "sha1-kb7O2lrE7SsX5kn7d356v6AYnCs=", - "dev": true, - "requires": { - "split2": "^0.2.1", - "through2": "^0.6.1" - } - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "log-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", - "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "dev": true, - "requires": { - "chalk": "^1.0.0" - } - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, - "math-random": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", - "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", - "dev": true - }, - "mathml-tag-names": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", - "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", - "dev": true - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - } - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "multimatch": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", - "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", - "dev": true, - "requires": { - "array-differ": "^1.0.0", - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "minimatch": "^3.0.0" - } - }, - "mute-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true - }, - "normalize-selector": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz", - "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=", - "dev": true - }, - "num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", - "dev": true - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "requires": { - "for-own": "^0.1.4", - "is-extendable": "^0.1.1" - } - }, - "object.values": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", - "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onecolor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/onecolor/-/onecolor-3.1.0.tgz", - "integrity": "sha512-YZSypViXzu3ul5LMu/m6XjJ9ol8qAy9S2VjHl5E6UlhUH1KGKWabyEJifn0Jjpw23bYDzC2ucKMPGiH5kfwSGQ==", - "dev": true - }, - "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, - "requires": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pipetteur": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pipetteur/-/pipetteur-2.0.3.tgz", - "integrity": "sha1-GVV2CVno0aEcsqUOyD7sRwYz5J8=", - "dev": true, - "requires": { - "onecolor": "^3.0.4", - "synesthesia": "^1.0.1" - } - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - }, - "plur": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/plur/-/plur-2.1.2.tgz", - "integrity": "sha1-dIJFLBoPUI4+NE6uwxLJHCncZVo=", - "dev": true, - "requires": { - "irregular-plurals": "^1.0.0" - } - }, - "pluralize": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", - "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - }, - "dependencies": { - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-less": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-0.14.0.tgz", - "integrity": "sha1-xjGwicbM5CK5oQ86lY0r7dOBkyQ=", - "dev": true, - "requires": { - "postcss": "^5.0.21" - } - }, - "postcss-media-query-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", - "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", - "dev": true - }, - "postcss-reporter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-3.0.0.tgz", - "integrity": "sha1-CeoPN6RExWk4eGBuCbAY6+/3z48=", - "dev": true, - "requires": { - "chalk": "^1.0.0", - "lodash": "^4.1.0", - "log-symbols": "^1.0.2", - "postcss": "^5.0.0" - } - }, - "postcss-resolve-nested-selector": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", - "integrity": "sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4=", - "dev": true - }, - "postcss-scss": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-0.4.1.tgz", - "integrity": "sha1-rXcbgfD3L19IRdCKpg+TVXZT1Uw=", - "dev": true, - "requires": { - "postcss": "^5.2.13" - } - }, - "postcss-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", - "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", - "dev": true, - "requires": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "progress": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", - "dev": true - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "randomatic": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", - "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", - "dev": true, - "requires": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - } - } - }, - "read-file-stdin": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/read-file-stdin/-/read-file-stdin-0.2.1.tgz", - "integrity": "sha1-JezP86FTtoCa+ssj7hU4fbng7mE=", - "dev": true, - "requires": { - "gather-stream": "^1.0.0" - } - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "readline2": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", - "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "mute-stream": "0.0.5" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - } - }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "dev": true, - "requires": { - "is-equal-shallow": "^0.1.3" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, - "require-from-string": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", - "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", - "dev": true - }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - } - }, - "resolve": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz", - "integrity": "sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, - "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-async": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", - "dev": true, - "requires": { - "once": "^1.3.0" - } - }, - "rx-lite": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", - "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "shelljs": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", - "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", - "dev": true, - "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - } - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "specificity": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.3.2.tgz", - "integrity": "sha512-Nc/QN/A425Qog7j9aHmwOrlwX2e7pNI47ciwxwy4jOlvbbMHkNNJchit+FX+UjF3IAdiaaV5BKeWuDUnws6G1A==", - "dev": true - }, - "split2": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/split2/-/split2-0.2.1.tgz", - "integrity": "sha1-At2smtwD7Au3jBKC7Aecpuha6QA=", - "dev": true, - "requires": { - "through2": "~0.6.1" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", - "dev": true, - "requires": { - "duplexer": "~0.1.1", - "through": "~2.3.4" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string.prototype.trimleft": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", - "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - } - }, - "string.prototype.trimright": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", - "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1" - }, - "dependencies": { - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - } - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "style-search": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", - "integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=", - "dev": true - }, - "stylehacks": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-2.3.2.tgz", - "integrity": "sha1-ZMg+BDimjJ7fRJ6MVSp9mrYAmws=", - "dev": true, - "requires": { - "browserslist": "^1.1.3", - "chalk": "^1.1.1", - "log-symbols": "^1.0.2", - "minimist": "^1.2.0", - "plur": "^2.1.2", - "postcss": "^5.0.18", - "postcss-reporter": "^1.3.3", - "postcss-selector-parser": "^2.0.0", - "read-file-stdin": "^0.2.1", - "text-table": "^0.2.0", - "write-file-stdout": "0.0.2" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "postcss-reporter": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-1.4.1.tgz", - "integrity": "sha1-wTbwpbFhkV83ndN2XGEHX357mvI=", - "dev": true, - "requires": { - "chalk": "^1.0.0", - "lodash": "^4.1.0", - "log-symbols": "^1.0.2", - "postcss": "^5.0.0" - } - } - } - }, - "stylelint": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-7.13.0.tgz", - "integrity": "sha1-ER+Xttpy53XICADWu29fhpmXeF0=", - "dev": true, - "requires": { - "autoprefixer": "^6.0.0", - "balanced-match": "^0.4.0", - "chalk": "^2.0.1", - "colorguard": "^1.2.0", - "cosmiconfig": "^2.1.1", - "debug": "^2.6.0", - "doiuse": "^2.4.1", - "execall": "^1.0.0", - "file-entry-cache": "^2.0.0", - "get-stdin": "^5.0.0", - "globby": "^6.0.0", - "globjoin": "^0.1.4", - "html-tags": "^2.0.0", - "ignore": "^3.2.0", - "imurmurhash": "^0.1.4", - "known-css-properties": "^0.2.0", - "lodash": "^4.17.4", - "log-symbols": "^1.0.2", - "mathml-tag-names": "^2.0.0", - "meow": "^3.3.0", - "micromatch": "^2.3.11", - "normalize-selector": "^0.2.0", - "pify": "^2.3.0", - "postcss": "^5.0.20", - "postcss-less": "^0.14.0", - "postcss-media-query-parser": "^0.2.0", - "postcss-reporter": "^3.0.0", - "postcss-resolve-nested-selector": "^0.1.1", - "postcss-scss": "^0.4.0", - "postcss-selector-parser": "^2.1.1", - "postcss-value-parser": "^3.1.1", - "resolve-from": "^3.0.0", - "specificity": "^0.3.0", - "string-width": "^2.0.0", - "style-search": "^0.1.0", - "stylehacks": "^2.3.2", - "sugarss": "^0.2.0", - "svg-tags": "^1.0.0", - "table": "^4.0.1" - }, - "dependencies": { - "ajv-keywords": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", - "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", - "dev": true - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - }, - "slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0" - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "table": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", - "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", - "dev": true, - "requires": { - "ajv": "^6.0.1", - "ajv-keywords": "^3.0.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" - } - } - } - }, - "stylelint-config-standard": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-16.0.0.tgz", - "integrity": "sha1-u3OHv/HX3XGGpSs+v4hbJAXWkb8=", - "dev": true - }, - "sugarss": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-0.2.0.tgz", - "integrity": "sha1-rDQjdWMyfG/4l7ZHQr9q7BkK054=", - "dev": true, - "requires": { - "postcss": "^5.2.4" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "svg-tags": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", - "dev": true - }, - "synesthesia": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/synesthesia/-/synesthesia-1.0.1.tgz", - "integrity": "sha1-XvlepUjA1cbm+btLDQcx3/hkp3c=", - "dev": true, - "requires": { - "css-color-names": "0.0.3" - } - }, - "table": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", - "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", - "dev": true, - "requires": { - "ajv": "^4.7.0", - "ajv-keywords": "^1.0.0", - "chalk": "^1.1.1", - "lodash": "^4.0.0", - "slice-ansi": "0.0.4", - "string-width": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "requires": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" - } - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "user-home": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", - "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "window-size": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", - "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", - "dev": true - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - }, - "write-file-stdout": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/write-file-stdout/-/write-file-stdout-0.0.2.tgz", - "integrity": "sha1-wlLXx8WxtAKJdjDjRTx7/mkNnKE=", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yargs": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.3.3.tgz", - "integrity": "sha1-BU3oth8i7v23IHBZ6u+da4P7kxo=", - "dev": true + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", + "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==" } } } diff --git a/package.json b/package.json index f1afb39..16cf2fa 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,6 @@ }, "homepage": "https://github.com/lavolp3/MMM-soccer#readme", "dependencies": { - "axios": "^0.19.2" + "axios": "^0.21.1" } } From 95e2fa6bc576841faa58de55a6ee3d936d425f73 Mon Sep 17 00:00:00 2001 From: lavolp3 Date: Wed, 30 Aug 2023 14:03:14 +0200 Subject: [PATCH 29/31] update to API v4 incl fix of logo missing --- MMM-soccer.css | 13 +++++++++++-- MMM-soccer.js | 7 ++++--- MMM-soccer.njk | 20 ++++++++++++++------ node_helper.js | 22 +++++++++++----------- 4 files changed, 40 insertions(+), 22 deletions(-) diff --git a/MMM-soccer.css b/MMM-soccer.css index 46f01d3..8a2b349 100644 --- a/MMM-soccer.css +++ b/MMM-soccer.css @@ -7,6 +7,10 @@ height: 24px; } +.MMM-soccer .big-icon { + width: 48px; +} + .MMM-soccer .no-color { -webkit-filter: grayscale(100%); } @@ -29,10 +33,15 @@ border: 4px solid black; background-color: #99aacc; color: black; - border-radius: 10px; + border-radius: 5px; text-align: center; font-size: 100%; - width: 50px; + width: 55px; + min-width: 55px; +} + +.MMM-soccer .games .status.TIMED{ + font-size: 90%; } .MMM-soccer .games .IN_PLAY { diff --git a/MMM-soccer.js b/MMM-soccer.js index c658f76..8ef21ee 100644 --- a/MMM-soccer.js +++ b/MMM-soccer.js @@ -228,6 +228,7 @@ Module.register('MMM-soccer', { this.showTable = (!isNaN(this.matchDay)); returnedMatches.push({ competition: (Object.keys(this.tables).length > 0) ? this.tables[this.competition].competition.name : "", + emblem: (Object.keys(this.tables).length > 0) ? this.tables[this.competition].competition.emblem : "", season: (Object.keys(this.tables).length > 0) ? `${this.translate('MATCHDAY')}: ${this.translate(this.matchDay)}` : this.translate('LOADING'), matches: matches.filter(match => { return match.matchday == this.matchDay; @@ -291,10 +292,10 @@ Module.register('MMM-soccer', { if (this.config.matchType == "league" || this.config.matchType == "daily") { match.focused = (match.homeTeam.name === focusTeam) ? true : (match.awayTeam.name === focusTeam) ? true : false; } - if (match.status == "SCHEDULED" || match.status == "POSTPONED") { - match.state = (moment(match.utcDate).diff(moment(), 'days') > 7) ? moment(match.utcDate).format("D.MM.") : (moment(match.utcDate).startOf('day') > moment()) ? moment(match.utcDate).format("dd") : moment(match.utcDate).format("LT"); + if (match.status == "TIMED" || match.status == "SCHEDULED" || match.status == "POSTPONED") { + match.state = (moment(match.utcDate).diff(moment(), 'days') > 7) ? moment(match.utcDate).format("D.MM.") : (moment(match.utcDate).startOf('day') > moment()) ? moment(match.utcDate).format("dd HH:mm") : moment(match.utcDate).format("LT"); } else { - match.state = match.score.fullTime.homeTeam + " - " + match.score.fullTime.awayTeam; + match.state = match.score.fullTime.home + " - " + match.score.fullTime.away; if (match.score.winner == "HOME_TEAM") { match.homeTeam["status"] = "winner" } else if (match.score.winner == "AWAY_TEAM") { diff --git a/MMM-soccer.njk b/MMM-soccer.njk index cc84225..28e61cd 100644 --- a/MMM-soccer.njk +++ b/MMM-soccer.njk @@ -8,22 +8,30 @@
{% if comps.length %} {% for i in range(0, comps.length) %} + + + + + + + + +
+ + {{ comps[i].competition }}
{{ comps[i].season }}
- {{ comps[i].competition }} - {{ comps[i].season }} {% for m in range(0, comps[i].matches.length) %} {% if config.logos %} {% endif %} {% if config.logos %} - + {% endif %} @@ -59,7 +67,7 @@ {% if config.logos %} - + {% endif %} diff --git a/node_helper.js b/node_helper.js index db8cfd2..d2ce5e0 100644 --- a/node_helper.js +++ b/node_helper.js @@ -59,18 +59,18 @@ module.exports = NodeHelper.create({ getTables: function(leagues) { var self = this; this.log("Collecting league tables for leagues: "+leagues); - var urlArray = leagues.map(league => { return `http://api.football-data.org/v2/competitions/${league}/standings`; }); + var urlArray = leagues.map(league => { return `http://api.football-data.org/v4/competitions/${league}/standings`; }); Promise.all(urlArray.map(url => { return axios.get(url, { headers: self.headers }) .then(function (response) { - console.log("Requests available: " + response.headers["x-requests-available-minute"]); + self.log("Requests available: " + response.headers["x-requests-available-minute"]); var tableData = response.data; var tables = { competition: tableData.competition, season: tableData.season, standings: tableData.standings, }; - //self.log(tables); + self.log(tables); return(tables); }) .catch(function (error) { @@ -91,8 +91,7 @@ module.exports = NodeHelper.create({ } }); //self.log("Collected Tables: " + self.tables); - //self.log("Collected Teams: " + JSON.stringify(self.teams)); - //self.log("TableArray: " + tableArray); + self.log("Collected Teams: " + JSON.stringify(self.teams)); self.sendSocketNotification("TABLES", self.tables); self.sendSocketNotification("TEAMS", self.teams); }) @@ -101,16 +100,16 @@ module.exports = NodeHelper.create({ });*/ }, - getMatches: function(leagues) { + getMatches:function(leagues) { var now = moment().subtract(60*13, "minutes"); //subtract minutes or hours to test live mode this.log("Collecting matches for leagues: " + leagues); - var urlArray = leagues.map(league => { return `http://api.football-data.org/v2/competitions/${league}/matches`; }); + var urlArray = leagues.map(league => { return `http://api.football-data.org/v4/competitions/${league}/matches`; }); this.liveLeagues = []; var self = this; Promise.all(urlArray.map(url => { return axios.get(url, { headers: self.headers }) .then(function (response) { - //console.log("Requests available: " + response.headers["x-requests-available-minute"]); + //self.log("Requests available: " + response.headers["x-requests-available-minute"]); var matchesData = response.data; var currentLeague = matchesData.competition.code; matchesData.matches.forEach(match => { @@ -135,6 +134,7 @@ module.exports = NodeHelper.create({ } }); return(matchesData); + self.log(matchesData); }) .catch(function (error) { self.handleErrors(error, url); @@ -147,7 +147,7 @@ module.exports = NodeHelper.create({ self.matches[comp.competition.code] = comp; } }); - //self.log("Collected Matches: "+self.matches); + //self.log(self.matches); self.log("Live matches: "+JSON.stringify(self.liveMatches)); self.log("Live leagues: "+JSON.stringify(self.liveLeagues)); self.sendSocketNotification("MATCHES", self.matches); @@ -166,7 +166,7 @@ module.exports = NodeHelper.create({ Promise.all(urlArray.map(url => { return axios.get(url, { headers: self.headers }) .then(function (response) { - console.log("Requests available: " + response.headers["x-requests-available-minute"]); + self.log("Requests available: " + response.headers["x-requests-available-minute"]); var matchData = response.data; self.log(matchData); if (matchData.match.status != "IN_PLAY" && self.liveMatches.indexOf(matchData.match.id)!= -1) { @@ -195,7 +195,7 @@ module.exports = NodeHelper.create({ if (error.response && error.response.status === 429) { console.log(error.response.status + ": API Request Quota of 10 calls per minute exceeded. Try selecting less leagues."); } else if (error.request) { - console.log(error.request); + //console.log(error.request); } else { // Something happened in setting up the request that triggered an Error console.log('Error: ', error.message); From 89d64491eb6c113b45628f3682671f628d64175d Mon Sep 17 00:00:00 2001 From: Dirk Date: Thu, 31 Aug 2023 08:58:04 +0200 Subject: [PATCH 30/31] Create fr.json --- translations/fr.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 translations/fr.json diff --git a/translations/fr.json b/translations/fr.json new file mode 100644 index 0000000..7860e3e --- /dev/null +++ b/translations/fr.json @@ -0,0 +1,17 @@ +{ + "LOADING": "Chargement...", + "NO_DATA_AVAILABLE": "Aucune donnée disponible !", + "NO_MATCHES": "Aucune correspondance", + "TODAYS_MATCHES": "Aujourd'hui", + "NEXT_MATCHES": "Prochains matchs", + "MATCHDAY": "Jour de match", + "TEAM": "Équipe", + "COMMAND_LIST": "Liste de toutes les commandes vocales", + "MODE": "Mode", + "VOICE_COMMANDS": "Commandes vocales", + "PLAY_OFF_ROUND": "Tour de barrages", + "ROUND_OF_16": "Huitièmes de finale", + "ROUND_OF_8": "Quarts de finale", + "ROUND_OF_4": "Demi-finales", + "FINAL": "Finales" +} From f13fd8ec6ce0796810d6403b3851eaf8a086cdd9 Mon Sep 17 00:00:00 2001 From: Dirk Date: Thu, 31 Aug 2023 08:59:50 +0200 Subject: [PATCH 31/31] Update MMM-soccer.js include fr translation --- MMM-soccer.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MMM-soccer.js b/MMM-soccer.js index 8ef21ee..0139e05 100644 --- a/MMM-soccer.js +++ b/MMM-soccer.js @@ -166,7 +166,8 @@ Module.register('MMM-soccer', { en: 'translations/en.json', de: 'translations/de.json', id: 'translations/id.json', - sv: 'translations/sv.json' + sv: 'translations/sv.json', + fr: 'translations/fr.json' }; },
{{comps[i].matches[m].homeTeam.name | replace}}{{ comps[i].matches[m].state }}{{comps[i].matches[m].awayTeam.name | replace}}
{{table[i].position}}{{table[i].team.name | replace}} {{table[i].playedGames}}