diff --git a/CHANGELOG.md b/CHANGELOG.md index 96601b3..8f81274 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # MMM-Fuel Changelog +## [2.4.0] + +### Added + +* [Provider: `gasbuddy`](https://github.com/fewieden/MMM-Fuel/pull/97) +* [Config option: `fade`](https://github.com/fewieden/MMM-Fuel/issues/7) +* [Config option: `showAddressCity`](https://github.com/fewieden/MMM-Fuel/pull/64) + +### Changed + +* [Migrated provider `nsw` from API v1 to v2 in order to support new region Tasmania (Australia)](https://github.com/fewieden/MMM-Fuel/issues/68#issuecomment-916505199) +* Dependency update + ## [2.3.1] ### Fixed diff --git a/MMM-Fuel.js b/MMM-Fuel.js index a49aa8a..843805e 100644 --- a/MMM-Fuel.js +++ b/MMM-Fuel.js @@ -49,7 +49,8 @@ Module.register('MMM-Fuel', { * @property {boolean} colored - Flag to render map in colour or greyscale. * @property {boolean} open - Flag to render column to indicate if the gas stations are open or closed. * @property {boolean|int} shortenText - Max characters to be shown for name and address. - * @property {boolean} showAddress - Flag to show the gas stations address. + * @property {boolean} showAddress - Flag to show the gas station's address. + * @property {boolean} showAddressCity - Flag to show the gas station's city. * @property {boolean} showOpenOnly - Flag to show only open gas stations or all. * @property {boolean} showDistance - Flag to show the distance to your specified position. * @property {boolean} showBrand - Flag to show the brand instead of the name. @@ -61,6 +62,7 @@ Module.register('MMM-Fuel', { * @property {int} updateInterval - Speed of update. * @property {string} provider - API provider of the data. * @property {boolean} toFixed - Flag to show price with only 2 decimals. + * @property {boolean} fade - Fade the list of gas stations. */ defaults: { radius: 5, @@ -73,6 +75,7 @@ Module.register('MMM-Fuel', { open: false, shortenText: false, showAddress: true, + showAddressCity: true, showOpenOnly: false, showDistance: true, showBrand: false, @@ -85,7 +88,8 @@ Module.register('MMM-Fuel', { provider: 'tankerkoenig', toFixed: false, stationIds: [], - excludeStationIds: [] + excludeStationIds: [], + fade: true }, /** @@ -430,5 +434,14 @@ Module.register('MMM-Fuel', { unit: this.priceList.unit, maximumFractionDigits: 1 }).format(distance)); + this.nunjucksEnvironment().addFilter('fade', (index, total) => { + if (this.config.fade) { + const percentage = (1 - 1 / total * index).toFixed(2); + + return `opacity: ${percentage}`; + } + + return ''; + }); } }); diff --git a/README.md b/README.md index 22179bc..4172a53 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ Gas Station Price Module for MagicMirror2 | `width` | `600` | Width of the map in pixel. | | `colored` | `false` | Boolean to show the gas stations map colored or not. | | `shortenText` | `false` | Integer of characters to be shown for name and address. Default shows all. | -| `showAddress` | `true` | Boolean to show the gas stations address. | +| `showAddress` | `true` | Boolean to show the gas station's address. | | `showOpenOnly` | `false` | Boolean to show only open gas stations or all. | | `showDistance` | `true` | Boolean to show the distance to your specified position. | | `showBrand` | `false` | Boolean to show the brand instead of the name. | @@ -64,6 +64,7 @@ Gas Station Price Module for MagicMirror2 | `rotate` | `true` | Boolean to enable/disable rotation between sort by price and distance. | | `rotateInterval` | `60000` (1 min) | How fast the sorting should be switched between byPrice and byDistance. | | `updateInterval` | `900000` (15 mins) | How often should the data be fetched. **If your value is to small, you risk to get banned from the API provider. I suggest a minimum of 15mins** | +| `fade` | `true` | Boolean to fade out the list of gas stations. | ## Global config @@ -85,6 +86,7 @@ or your API access will be suspended. | `api_key` | REQUIRED | Get an API key for free access to the data of [tankerkoenig.de](https://creativecommons.tankerkoenig.de/#register). | | `types` | `["diesel"]` | Valid options are `diesel`, `e5` and `e10`. | | `radius` | `5` | Valid range is 0-25. Set to 0 to disable. Not required if `stationIds` are provided. | +| `showAddressCity` | `true` | Boolean to show the gas station's city. | | `stationIds` | `[]` | Optional array of fuel station ids to fetch instead of the radius. You can only specify a maximum of 10 and you can find the ids [here](https://creativecommons.tankerkoenig.de/TankstellenFinder/index.html). Using radius and station ids in parallel will result in more API calls. If you run into issues increase the `updateInterval`. | | `excludeStationIds` | `[]` | Optional array of fuel station ids to exclude from the radius. This is useful e.g. if you got a non public or truck exclusive station in the radius. You can find the ids [here](https://creativecommons.tankerkoenig.de/TankstellenFinder/index.html).| @@ -98,6 +100,7 @@ No API key required. | `types` | `["diesel"]` | Valid options are `diesel`, `e5` and `gas`. | | `radius` | `5` | Valid range not tested yet. | | `max` | `5` | The API provider returns maximum of 5 valid datasets. | +| `showAddressCity` | `true` | Boolean to show the gas station's city. | | `showBrand` | `false` | The API provider does not return brand information. | ### autoblog (USA only) @@ -116,7 +119,24 @@ No API key required. The displayed distance is not based on your coordinates but | `showOpenOnly` | `false` | Not supported | | `showBrand` | `false` | Not supported | -### nsw (Australia NSW only) +### gasbuddy (USA and Canada only) + +No API key required. The displayed distance is not based on your coordinates but on the zip code. + +| **Option** | **Default** | **Description** | +| --- | --- | --- | +| `provider` | `"tankerkoenig"` | Make sure you set it to `"gasbuddy"`. | +| `zip` | REQUIRED | The zip code of your address, e.g. `"12345"` | +| `types` | `["regular"]` | Valid options are `regular`, `midgrade`, `premium`, `diesel`, `e85`, and `unl88`. | +| `showDistance` | `false` | Not supported | +| `radius` | `5` | Not supported | +| `lat` | `undefined` | Not supported | +| `lng` | `undefined` | Not supported | +| `open` | `false` | Not supported | +| `showOpenOnly` | `false` | Not supported | +| `showBrand` | `false` | Not supported | + +### nsw (Australia NSW and TAS only) This provider gives no information if the gas stations are open or closed. Config options should be set accordingly `open`: false and `showOpenOnly`: false. diff --git a/apis/autoblog.js b/apis/autoblog.js index 7d505d3..d95d60c 100644 --- a/apis/autoblog.js +++ b/apis/autoblog.js @@ -19,6 +19,8 @@ const fetch = require('node-fetch'); */ const { parse } = require('node-html-parser'); +const { fillMissingPrices, sortByDistance, sortByPrice, mergePrices } = require('./utils'); + const BASE_URL = 'https://www.autoblog.com'; const MAX_PAGE = 2; @@ -59,43 +61,6 @@ function mapGasStation(htmlGasStation, type) { }; } -/** - * @function fillMissingPrices - * @description Replaces missing price information with max price for type. - * - * @param {Object} station - Gas Station - * @param {Object} maxPricesByType - Maximum price per fuel type. - * - * @returns {void} - */ -function fillMissingPrices(station, maxPricesByType) { - for (const type of config.types) { - if (!station.prices[type]) { - station.prices[type] = `>${maxPricesByType[type]}`; - } - } -} - -/** - * @function sortByPrice - * @description Helper function to sort gas stations by price. - * - * @param {Object} a - Gas Station - * @param {Object} b - Gas Station - * - * @returns {number} Sorting weight. - */ -function sortByPrice(a, b) { - const aPrice = a.prices[config.sortBy]; - const bPrice = b.prices[config.sortBy]; - - if (!isNaN(aPrice) || !isNaN(bPrice)) { - return isNaN(aPrice) ? 1 : -1; - } - - return 0; -} - /** * @function fetchPaginatedStations * @description Paginated API requests for specified type. @@ -160,31 +125,17 @@ async function getAllStations() { } /** - * @function mergePrices - * @description Merges fuel prices of different types of gas station + * @function getStationKey + * @description Helper to retrieve unique station key. + * + * @param {Object} station - Station * - * @param {Object[]} responses - List of gas stations with prices of single fuel type. + * @returns {string} Returns unique station key. * - * @returns {Object} Returns gas stations with merged prices and max prices per fuel type. + * @see apis/README.md */ -function mergePrices(responses) { - const { indexedStations, maxPricesByType } = responses.reduce(({ indexedStations, maxPricesByType }, station) => { - const stationKey = `${station.name}-${station.address}`; - - if (!indexedStations[stationKey]) { - indexedStations[stationKey] = station; - } else { - indexedStations[stationKey].prices[station.fuelType] = station.prices[station.fuelType]; - } - - if (!maxPricesByType[station.fuelType] || maxPricesByType[station.fuelType] < station.prices[station.fuelType]) { - maxPricesByType[station.fuelType] = station.prices[station.fuelType]; - } - - return { indexedStations, maxPricesByType }; - }, { indexedStations: {}, maxPricesByType: {} }); - - return { stations: Object.values(indexedStations), maxPricesByType }; +function getStationKey(station) { + return `${station.name}-${station.address}`; } /** @@ -199,14 +150,14 @@ function mergePrices(responses) { async function getData() { const responses = await getAllStations(); - const { stations, maxPricesByType } = mergePrices(responses); + const { stations, maxPricesByType } = mergePrices(responses, getStationKey); - stations.forEach(station => fillMissingPrices(station, maxPricesByType)); + stations.forEach(station => fillMissingPrices(config, station, maxPricesByType)); const filteredStations = stations.filter(station => station.distance <= config.radius); - const stationsSortedByDistance = filteredStations.sort((a, b) => a.distance - b.distance); - const stationsSortedByPrice = [...stationsSortedByDistance].sort(sortByPrice); + const stationsSortedByDistance = filteredStations.sort(sortByDistance); + const stationsSortedByPrice = [...stationsSortedByDistance].sort(sortByPrice.bind(null, config)); return { types: ['regular', 'premium', 'mid-grade', 'diesel'], diff --git a/apis/gasbuddy.js b/apis/gasbuddy.js new file mode 100644 index 0000000..c0008a7 --- /dev/null +++ b/apis/gasbuddy.js @@ -0,0 +1,193 @@ +/** + * @file apis/gasbuddy.js + * + * @author fewieden + * @license MIT + * + * @see https://github.com/fewieden/MMM-Fuel + */ + +/** + * @external node-fetch + * @see https://www.npmjs.com/package/node-fetch + */ +const fetch = require('node-fetch'); + +/** + * @external node-html-parser + * @see https://www.npmjs.com/package/node-html-parser + */ +const { parse } = require('node-html-parser'); + +/** + * @external logger + * @see https://github.com/MichMich/MagicMirror/blob/master/js/logger.js + */ +const Log = require('logger'); + +const { fillMissingPrices, mergePrices, sortByPrice } = require('./utils'); + +const BASE_URL = 'https://www.gasbuddy.com'; +const TYPES = { + regular: 1, + midgrade: 2, + premium: 3, + diesel: 4, + e85: 5, + unl88: 12 +}; + +let config; + +/** + * @function getRequestPath + * + * @description URL path for fuel type to request data. + * + * @param {string} type - Fuel type. + * + * @returns {string} URL path for fuel type. + */ +function getRequestPath(type) { + return `/home?search=${config.zip}&fuel=${TYPES[type]}&maxAge=0&method=all`; +} + +/** + * @function mapGasStation + * @description Maps HTML gas station to reguilar object. + * + * @param {Object} htmlGasStation - HTML node of gas station. + * @param {string} type - Fuel type. + * + * @returns {Object} Gas station + */ +function mapGasStation(htmlGasStation, type) { + return { + name: htmlGasStation.querySelector('[class*=header__header3___] a[href*=station]').text, + address: htmlGasStation.querySelector('[class*=StationDisplay-module__address___]').innerHTML.replace('
', ' '), + prices: { [type]: parseFloat(htmlGasStation.querySelector('[class*=StationDisplayPrice-module__price___]').text.replace('$', '')) }, + distance: 0, + stationId: htmlGasStation.querySelector('[class*=header__header3___] a[href*=station]').rawAttributes.href.replace('/station/', '') + }; + +} + +/** + * @function fetchStations + * @description API requests for specified type. + * @async + * + * @param {string} type - Fuel type. + * @param {string} path - URL path. + * + * @returns {Promise} Array with stations including fuelType. + */ +async function fetchStations(type, path) { + let stations = []; + try { + const response = await fetch(`${BASE_URL}${path}`, { + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36', + } + }); + const html = await response.text(); + const parsedHtml = parse(html); + + const htmlStations = parsedHtml.querySelectorAll('[class*=GenericStationListItem-module__stationListItem___]'); + + const parsedStations = htmlStations.map(station => mapGasStation(station, type)); + + stations = stations.concat(parsedStations); + } catch (error) { + Log.error(`MMM-Fuel: Failed to fetch stations for type ${type}`, error); + } + + stations.forEach(station => { + station.fuelType = type; + }); + + return stations; +} + +/** + * @function getAllStations + * @description Requests all stations and fuel types. + * @async + * + * @returns {Object[]} Returns object described in the provider documentation. + */ +async function getAllStations() { + const promises = config.types.reduce((acc, type) => { + const path = getRequestPath(type); + + acc.push(fetchStations(type, path)); + return acc; + }, []); + + const responses = await Promise.all(promises); + + return responses.flat(); +} + +/** + * @function getStationKey + * @description Helper to retrieve unique station key. + * + * @param {Object} station - Station + * + * @returns {string} Returns unique station key. + * + * @see apis/README.md + */ +function getStationKey(station) { + return station.stationId; +} + +/** + * @function getData + * @description Performs the data query and processing. + * @async + * + * @returns {Object} Returns object described in the provider documentation. + * + * @see apis/README.md + */ +async function getData() { + const responses = await getAllStations(); + + const { stations, maxPricesByType } = mergePrices(responses, getStationKey); + + stations.forEach(station => fillMissingPrices(config, station, maxPricesByType)); + + // Webpage doesn't support distance (only zip code). + const stationsSortedByPrice = stations.sort(sortByPrice.bind(null, config)); + const stationsSortedByDistance = stationsSortedByPrice; + + return { + types: ['regular', 'midgrade', 'premium', 'diesel', 'e85', 'unl88'], + unit: 'mile', + currency: 'USD', + byPrice: stationsSortedByPrice, + byDistance: stationsSortedByDistance + }; +} + +/** + * @module apis/gasbuddy + * @description Queries data from https://www.gasbuddy.com + * + * @requires external:node-fetch + * @requires external:node-html-parser + * @requires external:logger + * + * @param {Object} options - Configuration. + * @param {string} options.zip - Zip code of address. + * @param {string} options.sortBy - Type to sort by price. + * @param {string[]} options.types - Requested fuel types. + * + * @returns {Object} Object with function getData. + */ +module.exports = options => { + config = options; + return { getData }; +}; diff --git a/apis/nsw.js b/apis/nsw.js index 96c4745..0c697d1 100644 --- a/apis/nsw.js +++ b/apis/nsw.js @@ -148,7 +148,7 @@ async function getData() { * @returns {Promise} Object with fuel type and data. */ async function requestFuelType(type) { - const response = await fetch(`${BASE_URL}/FuelPriceCheck/v1/fuel/prices/nearby`, { + const response = await fetch(`${BASE_URL}/FuelPriceCheck/v2/fuel/prices/nearby`, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -160,11 +160,11 @@ async function requestFuelType(type) { }, body: JSON.stringify({ fueltype: TYPES[type], - latitude: config.lat, - longitude: config.lng, - radius: config.radius, - sortby: 'price', - sortascending: true + latitude: `${config.lat}`, + longitude: `${config.lng}`, + radius: `${config.radius}`, + sortby: 'Price', + sortascending: 'true' }) }); diff --git a/apis/spritpreisrechner.js b/apis/spritpreisrechner.js index be1e3c9..186d35c 100644 --- a/apis/spritpreisrechner.js +++ b/apis/spritpreisrechner.js @@ -110,7 +110,8 @@ function normalizeStations(stations, keys) { stations[index].prices[type] = -1; }); stations[index].isOpen = value.open; - stations[index].address = `${value.location.postalCode} ${value.location.city} - ${value.location.address}`; + stations[index].street = value.location.address; + stations[index].address = `${value.location.postalCode} ${value.location.city} - ${stations[index].street}`; stations[index].lat = parseFloat(value.location.latitude); stations[index].lng = parseFloat(value.location.longitude); stations[index].distance = value.distance.toFixed(2); diff --git a/apis/tankerkoenig.js b/apis/tankerkoenig.js index cd1fe80..eb1f685 100644 --- a/apis/tankerkoenig.js +++ b/apis/tankerkoenig.js @@ -137,8 +137,9 @@ function normalizeStations(value, index, stations) { e10: value.e10 }; stations[index].distance = value.dist; + stations[index].street = `${value.street} ${value.houseNumber}`; stations[index].address = `${`0${value.postCode}`.slice(-5)} ${ - value.place} - ${value.street} ${value.houseNumber}`; + value.place} - ${stations[index].street}`; /* eslint-enable no-param-reassign */ } diff --git a/apis/utils/index.js b/apis/utils/index.js index 69898a5..f2b7b5b 100644 --- a/apis/utils/index.js +++ b/apis/utils/index.js @@ -34,11 +34,80 @@ function sortByDistance(a, b) { return a.distance - b.distance; } +/** + * @function fillMissingPrices + * @description Replaces missing price information with max price for type. + * + * @param {Object} station - Gas Station + * @param {Object} maxPricesByType - Maximum price per fuel type. + * + * @returns {void} + */ +function fillMissingPrices(config, station, maxPricesByType) { + for (const type of config.types) { + if (!station.prices[type]) { + station.prices[type] = `>${maxPricesByType[type]}`; + } + } +} + +/** + * @function sortByPrice + * @description Helper function to sort gas stations by price. + * + * @param {Object} a - Gas Station + * @param {Object} b - Gas Station + * + * @returns {number} Sorting weight. + */ +function sortByPrice(config, a, b) { + const aPrice = a.prices[config.sortBy]; + const bPrice = b.prices[config.sortBy]; + + if (!isNaN(aPrice) || !isNaN(bPrice)) { + return isNaN(aPrice) ? 1 : -1; + } + + return 0; +} + +/** + * @function mergePrices + * @description Merges fuel prices of different types of gas station + * + * @param {Object[]} responses - List of gas stations with prices of single fuel type. + * @param {function} getStationKeyFunc - Helper to retrieve unique station key. + * + * @returns {Object} Returns gas stations with merged prices and max prices per fuel type. + */ +function mergePrices(responses, getStationKeyFunc) { + const { indexedStations, maxPricesByType } = responses.reduce(({ indexedStations, maxPricesByType }, station) => { + const stationKey = getStationKeyFunc(station); + + if (!indexedStations[stationKey]) { + indexedStations[stationKey] = station; + } else { + indexedStations[stationKey].prices[station.fuelType] = station.prices[station.fuelType]; + } + + if (!maxPricesByType[station.fuelType] || maxPricesByType[station.fuelType] < station.prices[station.fuelType]) { + maxPricesByType[station.fuelType] = station.prices[station.fuelType]; + } + + return { indexedStations, maxPricesByType }; + }, { indexedStations: {}, maxPricesByType: {} }); + + return { stations: Object.values(indexedStations), maxPricesByType }; +} + /** * @module apis/utils * @description Utility functions for API integrations. */ module.exports = { + fillMissingPrices, filterStations, - sortByDistance + mergePrices, + sortByDistance, + sortByPrice }; diff --git a/package-lock.json b/package-lock.json index 5ccd5ec..1794753 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mmm-fuel", - "version": "2.3.1", + "version": "2.4.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -191,6 +191,12 @@ } } }, + "@csstools/selector-specificity": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz", + "integrity": "sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==", + "dev": true + }, "@eslint/eslintrc": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", @@ -430,7 +436,7 @@ "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", "dev": true }, "astral-regex": { @@ -468,7 +474,7 @@ "boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, "brace-expansion": { "version": "1.1.11", @@ -563,15 +569,6 @@ "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", "dev": true }, - "clone-regexp": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-2.2.0.tgz", - "integrity": "sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q==", - "dev": true, - "requires": { - "is-regexp": "^2.0.0" - } - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -588,9 +585,9 @@ "dev": true }, "colord": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz", - "integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==", + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", "dev": true }, "concat-map": { @@ -661,27 +658,27 @@ } }, "css-functions-list": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.0.1.tgz", - "integrity": "sha512-PriDuifDt4u4rkDgnqRCLnjfMatufLmWNfQnGCq34xZwpY3oabwhB9SqRBmuvWUgndbemCFlKqg+nO7C2q0SBw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.1.0.tgz", + "integrity": "sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==", "dev": true }, "css-select": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", - "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", "requires": { "boolbase": "^1.0.0", - "css-what": "^5.1.0", - "domhandler": "^4.3.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", "domutils": "^2.8.0", "nth-check": "^2.0.1" } }, "css-what": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", - "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==" + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" }, "cssesc": { "version": "3.0.0", @@ -701,13 +698,13 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true }, "decamelize-keys": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "integrity": "sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==", "dev": true, "requires": { "decamelize": "^1.1.0", @@ -717,7 +714,7 @@ "map-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", "dev": true } } @@ -764,9 +761,9 @@ } }, "dom-serializer": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", - "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", "requires": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", @@ -774,14 +771,14 @@ } }, "domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" }, "domhandler": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz", - "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", "requires": { "domelementtype": "^2.2.0" } @@ -812,9 +809,9 @@ } }, "entities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" }, "error-ex": { "version": "1.3.2", @@ -2457,15 +2454,6 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, - "execall": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/execall/-/execall-2.0.0.tgz", - "integrity": "sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow==", - "dev": true, - "requires": { - "clone-regexp": "^2.1.0" - } - }, "external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -2494,17 +2482,6 @@ "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } } }, "fast-json-stable-stringify": { @@ -2520,9 +2497,9 @@ "dev": true }, "fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true }, "fastq": { @@ -2615,12 +2592,6 @@ "has-symbols": "^1.0.1" } }, - "get-stdin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", - "dev": true - }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -2695,7 +2666,7 @@ "globjoin": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", - "integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", "dev": true }, "graceful-fs": { @@ -2743,9 +2714,9 @@ "dev": true }, "html-tags": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", - "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", + "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", "dev": true }, "iconv-lite": { @@ -2986,7 +2957,7 @@ "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", "dev": true }, "is-plain-object": { @@ -3004,12 +2975,6 @@ "has-symbols": "^1.0.1" } }, - "is-regexp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-2.1.0.tgz", - "integrity": "sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA==", - "dev": true - }, "is-string": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", @@ -3063,9 +3028,9 @@ } }, "jsdoc": { - "version": "3.6.10", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.10.tgz", - "integrity": "sha512-IdQ8ppSo5LKZ9o3M+LKIIK8i00DIe5msDvG3G81Km+1dhy0XrOWD0Ji8H61ElgyEj/O9KRLokgKbAM9XX9CJAg==", + "version": "3.6.11", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.11.tgz", + "integrity": "sha512-8UCU0TYeIYD9KeLzEcAu2q8N/mx9O3phAGl32nmHlE0LpaJL71mMkP4d+QE5zWfNt50qheHtOZ0qoxVrsX5TUg==", "dev": true, "requires": { "@babel/parser": "^7.9.4", @@ -3074,7 +3039,7 @@ "catharsis": "^0.9.0", "escape-string-regexp": "^2.0.0", "js2xmlparser": "^4.0.2", - "klaw": "^4.0.1", + "klaw": "^3.0.0", "markdown-it": "^12.3.2", "markdown-it-anchor": "^8.4.1", "marked": "^4.0.10", @@ -3149,15 +3114,18 @@ "dev": true }, "klaw": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-4.0.1.tgz", - "integrity": "sha512-pgsE40/SvC7st04AHiISNewaIMUbY5V/K8b21ekiPiFoYs/EYSdsGa+FJArB1d441uq4Q8zZyIxvAzkGNlBdRw==", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.9" + } }, "known-css-properties": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.24.0.tgz", - "integrity": "sha512-RTSoaUAfLvpR357vWzAz/50Q/BmHfmE6ETSWfutT0AJiw10e6CmcdYRQJlLRd95B53D0Y2aD1jSxD3V3ySF+PA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.25.0.tgz", + "integrity": "sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==", "dev": true }, "levn": { @@ -3267,19 +3235,25 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true + }, + "entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true } } }, "markdown-it-anchor": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.4.1.tgz", - "integrity": "sha512-sLODeRetZ/61KkKLJElaU3NuU2z7MhXf12Ml1WJMSdwpngeofneCRF+JBbat8HiSqhniOMuTemXMrsI7hA6XyA==", + "version": "8.6.4", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.4.tgz", + "integrity": "sha512-Ul4YVYZNxMJYALpKtu+ZRdrryYt/GlQ5CK+4l1bp/gWXOG2QWElt6AqF3Mih/wfUKdZbNAZVXGR73/n6U/8img==", "dev": true }, "marked": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", - "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.18.tgz", + "integrity": "sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw==", "dev": true }, "mathml-tag-names": { @@ -3291,7 +3265,7 @@ "mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", "dev": true }, "meow": { @@ -3334,9 +3308,9 @@ } }, "is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", "dev": true, "requires": { "has": "^1.0.3" @@ -3469,9 +3443,9 @@ } }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -3492,13 +3466,13 @@ "dev": true }, "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "braces": "^3.0.2", + "picomatch": "^2.3.1" } }, "mimic-fn": { @@ -3549,9 +3523,9 @@ } }, "moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" }, "ms": { "version": "2.1.2", @@ -3566,9 +3540,9 @@ "dev": true }, "nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", "dev": true }, "natural-compare": { @@ -3592,9 +3566,9 @@ } }, "node-html-parser": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-5.3.3.tgz", - "integrity": "sha512-ncg1033CaX9UexbyA7e1N0aAoAYRDiV8jkTvzEnfd1GDvzFdrsXLzR4p4ik8mwLgnaKP/jyUFWDy9q3jvRT2Jw==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-5.4.1.tgz", + "integrity": "sha512-xy/O2wOEBJsIRLs4avwa1lVY7tIpXXOoHHUJLa0GvnoPPqMG1hgBVl1tNI3GHOwRktTVZy+Y6rjghk4B9/NLyg==", "requires": { "css-select": "^4.2.1", "he": "1.2.0" @@ -3618,16 +3592,10 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "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 - }, "nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "requires": { "boolbase": "^1.0.0" } @@ -3839,12 +3807,12 @@ } }, "postcss": { - "version": "8.4.12", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz", - "integrity": "sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==", + "version": "8.4.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", + "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", "dev": true, "requires": { - "nanoid": "^3.3.1", + "nanoid": "^3.3.4", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } @@ -3852,13 +3820,13 @@ "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=", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", "dev": true }, "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=", + "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", "dev": true }, "postcss-safe-parser": { @@ -3868,9 +3836,9 @@ "dev": true }, "postcss-selector-parser": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", - "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", "dev": true, "requires": { "cssesc": "^3.0.0", @@ -4208,12 +4176,6 @@ "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", "dev": true }, - "specificity": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz", - "integrity": "sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==", - "dev": true - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -4299,48 +4261,45 @@ "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=", + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", "dev": true }, "stylelint": { - "version": "14.6.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.6.0.tgz", - "integrity": "sha512-Xk2sqXYPi9nXgq70nBiZkbQm/QOOKd83NBTaBE1fXEWAEeRlgHnKC/E7kJFlT6K0SaNDOK5yIvR7GFPGsNLuOg==", + "version": "14.10.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.10.0.tgz", + "integrity": "sha512-VAmyKrEK+wNFh9R8mNqoxEFzaa4gsHGhcT4xgkQDuOA5cjF6CaNS8loYV7gpi4tIZBPUyXesotPXzJAMN8VLOQ==", "dev": true, "requires": { + "@csstools/selector-specificity": "^2.0.2", "balanced-match": "^2.0.0", "colord": "^2.9.2", "cosmiconfig": "^7.0.1", - "css-functions-list": "^3.0.1", - "debug": "^4.3.3", - "execall": "^2.0.0", + "css-functions-list": "^3.1.0", + "debug": "^4.3.4", "fast-glob": "^3.2.11", - "fastest-levenshtein": "^1.0.12", + "fastest-levenshtein": "^1.0.16", "file-entry-cache": "^6.0.1", - "get-stdin": "^8.0.0", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", - "html-tags": "^3.1.0", + "html-tags": "^3.2.0", "ignore": "^5.2.0", "import-lazy": "^4.0.0", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.24.0", + "known-css-properties": "^0.25.0", "mathml-tag-names": "^2.1.3", "meow": "^9.0.0", - "micromatch": "^4.0.4", + "micromatch": "^4.0.5", "normalize-path": "^3.0.0", - "normalize-selector": "^0.2.0", "picocolors": "^1.0.0", - "postcss": "^8.4.12", + "postcss": "^8.4.16", "postcss-media-query-parser": "^0.2.3", "postcss-resolve-nested-selector": "^0.1.1", "postcss-safe-parser": "^6.0.0", - "postcss-selector-parser": "^6.0.9", + "postcss-selector-parser": "^6.0.10", "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", - "specificity": "^0.4.1", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", "style-search": "^0.1.0", @@ -4351,60 +4310,12 @@ "write-file-atomic": "^4.0.1" }, "dependencies": { - "ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, "balanced-match": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", "dev": true }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -4414,123 +4325,33 @@ "ms": "2.1.2" } }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", - "dev": true - }, "ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "table": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", - "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", - "dev": true, - "requires": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - } - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true } } }, "stylelint-config-recommended": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-7.0.0.tgz", - "integrity": "sha512-yGn84Bf/q41J4luis1AZ95gj0EQwRX8lWmGmBwkwBNSkpGSpl66XcPTulxGa/Z91aPoNGuIGBmFkcM1MejMo9Q==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-9.0.0.tgz", + "integrity": "sha512-9YQSrJq4NvvRuTbzDsWX3rrFOzOlYBmZP+o513BJN/yfEmGSr0AxdvrWs0P/ilSpVV/wisamAHu5XSk8Rcf4CQ==", "dev": true }, "stylelint-config-standard": { - "version": "25.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-25.0.0.tgz", - "integrity": "sha512-21HnP3VSpaT1wFjFvv9VjvOGDtAviv47uTp3uFmzcN+3Lt+RYRv6oAplLaV51Kf792JSxJ6svCJh/G18E9VnCA==", + "version": "27.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-27.0.0.tgz", + "integrity": "sha512-J+wxyODWQCW2kgdhVzj51a4cFcJkglkMQrjPU/1Jo8w2oKSKK5ZRqHvDDWxEmjYWIYbMhhIMS5dOgVpGUMIACw==", "dev": true, "requires": { - "stylelint-config-recommended": "^7.0.0" + "stylelint-config-recommended": "^9.0.0" } }, "supports-color": { @@ -4572,7 +4393,7 @@ "svg-tags": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", "dev": true }, "table": { @@ -4611,7 +4432,7 @@ "taffydb": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", - "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", + "integrity": "sha512-y3JaeRSplks6NYQuCOj3ZFMO3j60rTwbuKCvZxsAraGYH2epusatvZ0baZYA01WsGqJBq/Dl6vOrMUJqyMj8kA==", "dev": true }, "text-table": { @@ -4701,9 +4522,9 @@ "dev": true }, "underscore": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.2.tgz", - "integrity": "sha512-ekY1NhRzq0B08g4bGuX4wd2jZx5GnKz6mKSqFL4nqBlfyMGiG10gDFhDTMEfYmDL6Jy0FUIZp7wiRB+0BP7J2g==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.4.tgz", + "integrity": "sha512-BQFnUDuAQ4Yf/cYY5LNrK9NCJFKriaRbD9uR1fTeXnBeoa97W0i41qkZfGO9pSo8I5KzjAcSY2XYtdf0oKd7KQ==", "dev": true }, "uri-js": { @@ -4718,7 +4539,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, "v8-compile-cache": { @@ -4789,14 +4610,6 @@ "requires": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" - }, - "dependencies": { - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - } } }, "xmlcreate": { diff --git a/package.json b/package.json index 48efdad..f01df20 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mmm-fuel", - "version": "2.3.1", + "version": "2.4.0", "description": "Gas Station price Module for MagicMirror2", "scripts": { "lint": "eslint . && stylelint **/*.css", @@ -24,13 +24,13 @@ "devDependencies": { "eslint": "^7.32.0", "eslint-config-recommended": "^4.1.0", - "jsdoc": "^3.6.10", - "stylelint": "^14.6.0", - "stylelint-config-standard": "^25.0.0" + "jsdoc": "^3.6.11", + "stylelint": "^14.10.0", + "stylelint-config-standard": "^27.0.0" }, "dependencies": { - "moment": "^2.29.1", + "moment": "^2.29.4", "node-fetch": "^2.6.7", - "node-html-parser": "^5.3.3" + "node-html-parser": "^5.4.1" } } diff --git a/templates/MMM-Fuel.njk b/templates/MMM-Fuel.njk index d85205f..88f6cda 100644 --- a/templates/MMM-Fuel.njk +++ b/templates/MMM-Fuel.njk @@ -39,7 +39,8 @@ {% endif %} {% for gasStation in gasStations %} - + {% set fadeStyle = loop.index0 | fade(loop.length) %} + {{ gasStation.brand if config.showBrand else gasStation.name | shortenText | safe }} {% for type in config.types %} {% if includes(priceList.types, type) %} @@ -56,9 +57,13 @@ {% endif %} {% if config.showAddress %} - + - {{ gasStation.address | shortenText | safe }} + {% if not config.showAddressCity %} + {{ gasStation.street | shortenText | safe }} + {% else %} + {{ gasStation.address | shortenText | safe }} + {% endif %} {% endif %}