From 0c48f96c0cb49f2834a6ef8c5828fe9d307905dd Mon Sep 17 00:00:00 2001 From: Peter deHaan Date: Mon, 5 Nov 2018 08:55:44 -0800 Subject: [PATCH 001/140] Add homepage, author, description to about:addons --- package.json | 15 ++++++++++++--- src/manifest.json | 4 +++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 9f02a2b..3a46c57 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "price-wise", "version": "8.0.0", - "description": "", - "private": "true", + "description": "Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy.", + "private": true, "author": "Mozilla Foundation", "license": "MPL-2.0", "scripts": { @@ -62,5 +62,14 @@ "redux": "4.0.0", "redux-thunk": "2.3.0", "uuid": "3.3.2" - } + }, + "repository": { + "type": "git", + "url": "git+https://github.com/mozilla/price-wise.git" + }, + "keywords": [], + "bugs": { + "url": "https://github.com/mozilla/price-wise/issues" + }, + "homepage": "https://testpilot.firefox.com/experiments/price-wise" } diff --git a/src/manifest.json b/src/manifest.json index 6b05adb..b57f9b2 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -2,7 +2,9 @@ "manifest_version": 2, "name": "Price Wise", "version": "$version", - "description": "", + "author": "$author", + "description": "$description", + "homepage_url": "$homepage", "applications": { "gecko": { "id": "shopping-testpilot@mozilla.org", From d07b508945d888edb2e03e3df1a13c0483169e93 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Mon, 5 Nov 2018 10:58:33 -0800 Subject: [PATCH 002/140] 9.0.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8ed8ab0..69f3358 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "8.0.0", + "version": "9.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 9f02a2b..9af5259 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "8.0.0", + "version": "9.0.0", "description": "", "private": "true", "author": "Mozilla Foundation", From d5c1e662d30074b7d215af8cf8593a7c04b6304e Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Thu, 1 Nov 2018 13:43:58 -0700 Subject: [PATCH 003/140] Document how to release a new version of the add-on. --- README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/README.md b/README.md index 66a2e54..8154cf3 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,34 @@ After this, you can run `pipenv run test` to run the automated test suite. | `npm run package` | Package the extension into an XPI file | | `pipenv run test` | Run test suite (See "Running Tests" for setup) | +## Releasing a New Version + +Price Wise bumps the major version number for every release, similar to Firefox. Releases are created by tagging a commit that bumps the version number and pushing that tag to the repo. This triggers CircleCI automation that packages, tests, and uploads the new version to the Test Pilot S3 bucket. + +It is strongly recommended that developers creating releases [configure Git to +sign their commits and tags][signing]. + +To create a new release of Price Wise: + +1. Increment the version number in `package.json`, create a new commit on the `master` branch with this change, and create a new git tag pointing to the commit with a name of the form `v1.0.0`, where `1.0.0` is the new version number. + + `npm` ships with a command that can perform these steps for you automatically: + + ```sh + npm version major + ``` +2. Push the updated `master` branch and the new tag to the remote for the Mozilla Price Wise repository (named `origin` in the example below): + + ```sh + git push origin master + git push origin v1.0.0 + ``` + +You can follow along with the build and upload progress for the new release on the [CircleCI dashboard][]. Once the build finishes, the new version should be available immediately at https://testpilot.firefox.com/files/shopping-testpilot@mozilla.org/latest. + +[signing]: https://help.github.com/articles/signing-commits/ +[CircleCI dashboard]: https://circleci.com/dashboard + ## Code Organization - `src/background` contains the background scripts that trigger UI elements (such as the page action) and periodically check for price updates. From 754d375f7dd7d958bf5371e9b00a7a9363164622 Mon Sep 17 00:00:00 2001 From: Peter deHaan Date: Mon, 5 Nov 2018 16:14:59 -0800 Subject: [PATCH 004/140] Address review comments --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 3a46c57..5acb9f9 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "name": "price-wise", - "version": "8.0.0", + "version": "9.0.0", "description": "Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy.", "private": true, - "author": "Mozilla Foundation", + "author": "Mozilla", "license": "MPL-2.0", "scripts": { "start": "web-ext run --source-dir build", @@ -65,11 +65,11 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/mozilla/price-wise.git" + "url": "https://github.com/mozilla/price-wise.git" }, "keywords": [], "bugs": { "url": "https://github.com/mozilla/price-wise/issues" }, - "homepage": "https://testpilot.firefox.com/experiments/price-wise" + "homepage": "https://github.com/mozilla/price-wise" } From 7bdfc36ba727ea7e1acdfcd51ceb0041b062a8d3 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Mon, 5 Nov 2018 15:43:23 -0800 Subject: [PATCH 005/140] Fix #230: Constrain width of entire popup with lower and upper bounds In previous PRs (#214, #215 and #218) CSS fixes were added to partially constrain either the whole popup or sections of it, leaving the 'Undo' section out. This patch puts a min-width and max-width on the whole popup, while flexibly sizing all its child containers, ensuring that the fixes applied in previous PRs remain in place. Unfortunately, the Overflow menu has a width greater than our ideal popup width of 320px per the [UX spec](https://mozilla.invisionapp.com/share/UFNSHAIMT4V#/screens/317130676_Artboard_1), and that width cannot be controlled by a Web Extension, so I have set the max-width to 400px which will ensure the width of the popup doesn't change whether the toolbar button is in the overflow menu or not (previously, it would be one width when opened from the overflow menu and another width when opened otherwise). One idea for the future is to try and detect whether the toolbar button is in the overflow menu or not and change classes accordingly via an experimental API, but that seems like overkill for now. --- src/browser_action/components/EmptyOnboarding.css | 3 +-- src/browser_action/components/ProductCard.css | 2 +- src/browser_action/index.css | 2 ++ 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/browser_action/components/EmptyOnboarding.css b/src/browser_action/components/EmptyOnboarding.css index b56fe79..126dbed 100644 --- a/src/browser_action/components/EmptyOnboarding.css +++ b/src/browser_action/components/EmptyOnboarding.css @@ -9,9 +9,8 @@ display: flex; flex-direction: column; gap: 16px; - margin: 16px auto; + margin: 16px; text-align: center; - width: 288px; } .empty-onboarding .hero { diff --git a/src/browser_action/components/ProductCard.css b/src/browser_action/components/ProductCard.css index e35ccc5..a5ff1db 100644 --- a/src/browser_action/components/ProductCard.css +++ b/src/browser_action/components/ProductCard.css @@ -9,7 +9,7 @@ cursor: pointer; display: grid; gap: 8px; - grid-template-columns: 20px minmax(204px, 284px) 64px; + grid-template-columns: 20px auto 64px; grid-template-rows: auto 20px; height: 88px; overflow: hidden; diff --git a/src/browser_action/index.css b/src/browser_action/index.css index 6c78589..7a58ec9 100644 --- a/src/browser_action/index.css +++ b/src/browser_action/index.css @@ -22,6 +22,8 @@ body { #browser-action-app { min-width: 320px; + max-width: 400px; /* Overflow menu popup width exceeds 320px and cannot be changed */ + width: 100%; } /** Links */ From 3743b4cfca3bd446d56375cb41036fd9e04c17cf Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Tue, 30 Oct 2018 16:13:40 -0700 Subject: [PATCH 006/140] #158: Add 'detect_price_change' probe Add 'detect_price_change' probe * Add `price_prev` extra key for `detect_price_change` event. This will be the same value as `price_orig` if there is only one price entry for the product when updating prices. This will help us answer questions around how much prices change in addition to how frequently. Additionally: * Update the name of the extension in METRICS.md to Price Wise. * Add Appendix B to METRICS.md which explains how to view recorded telemetry events in about:telemetry. --- docs/METRICS.md | 21 +++++++++++++++------ src/background/price_updates.js | 21 ++++++++++++++++++--- src/state/prices.js | 10 +++++++++- src/telemetry/extension.js | 1 + 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/docs/METRICS.md b/docs/METRICS.md index 8431d06..f018630 100644 --- a/docs/METRICS.md +++ b/docs/METRICS.md @@ -3,7 +3,7 @@ # Metrics -A summary of the metrics the Price Alerts extension will record. +A summary of the metrics the Price Wise extension will record. ## Definitions @@ -21,7 +21,7 @@ A summary of the metrics the Price Alerts extension will record. ## Analysis -Data collected by the Price Alerts extension will be used to answer the following questions: +Data collected by the Price Wise extension will be used to answer the following questions: Note: For any questions related to general user shopping behavior, the data about what sites users visit is limited to the Supported Sites for the MVP. @@ -84,7 +84,7 @@ While some of these questions may be partially answerable by this extension, ans We will be sending pings using [Event Telemetry](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/events.html) via the [WebExtensions Telemetry API](https://bugzilla.mozilla.org/show_bug.cgi?id=1280234). -Each event will exist as part of the `main` ping under `payload.processes.dynamic.events` as an array in the `events` array. The data types of individual fields for each event follow the Event Telemetry [serialization format](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/events.html#serialization-format). +Each event will exist as part of the `main` ping under `payload.processes.dynamic.events` as an array in the `events` array (see Appendix B for how to view the events in `about:telemetry`). The data types of individual fields for each event follow the Event Telemetry [serialization format](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/events.html#serialization-format). The telemetry category for events is `'extension.price_alerts'`. @@ -144,6 +144,7 @@ Below is a sample ping for the `badge_toolbar_button` and `visit_supported_site` - `'price'`: The price of the product in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only). - `'price_alert'`: 'true' if the product has an active Price Alert; otherwise 'false'. - `'price_orig'`: The original price of the product in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only). +- `'price_prev'`: The previous price of the product when different from the latest price (`price`) in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only). - `'product_index'`: The index of the product in the product listing. The top most list item is index '0'. The list is sorted by date added, descending (#113). - `'product_key'`: A unique identifier for the product relative to other products for a given user. This key is _not_ unique to the product across all users. - `'tracked_prods'`: The number of products the user is tracking. @@ -152,9 +153,9 @@ Below is a sample ping for the `badge_toolbar_button` and `visit_supported_site` - `'best_buy_link'`: Sends the user to Best Buy. - `'ebay_link'`: Sends the user to Ebay. - `'feedback_button'`: Sends the user to a feedback Survey. - - `'help_button'`: Sends the user to a Price Alerts support.mozilla.org page. + - `'help_button'`: Sends the user to a Price Wise support.mozilla.org page. - `'home_depot_link'`: Sends the user to Home Depot. - - `'learn_more_link'`: Sends the user to a Price Alerts support.mozilla.org page. + - `'learn_more_link'`: Sends the user to a Price Wise support.mozilla.org page. - `'product_card'`: Sends the user to the product page for the given Product Card. - `'system_notification'`: Sends the user to the product page for the Price Alert displayed in the notification. - `'walmart_link'`: Sends the user to Walmart. @@ -186,7 +187,7 @@ Fired when the user navigates to a Supported Site. ### `open_popup` -Fired when the user clicks the Price Alerts browserAction toolbar button to open the popup. +Fired when the user clicks the Price Wise browserAction toolbar button to open the popup. #### Payload properties - `methods`: String @@ -303,6 +304,7 @@ Fired whenever a price change (of any magnitude and in any direction) is detecte - `extra_keys`: Object - `'price'` - `'price_orig'` + - `'price_prev'` - `'product_key'` - `'tracked_prods'` @@ -427,3 +429,10 @@ Note: This is a sample ping. The exact value for the extension ID may differ, th // ... } ``` + +### Appendix B: How to view Price Wise events in `about:telemetry` + +1. Navigate to `about:telemetry`. +2. Click 'Events' in the sidebar menu. + - Note: This menu item is not present until an event has been recorded for the current session. If you don't see it, trigger one of the events as described in this document (e.g. `open_popup`) and refresh the page. +3. On the top right corner of the next page, click 'dynamic' in the dropdown menu. \ No newline at end of file diff --git a/src/background/price_updates.js b/src/background/price_updates.js index 2fcf801..162f957 100644 --- a/src/background/price_updates.js +++ b/src/background/price_updates.js @@ -10,9 +10,10 @@ import config from 'commerce/config'; import store from 'commerce/state'; import {shouldUpdatePrices} from 'commerce/privacy'; -import {addPriceFromExtracted, getLatestPriceForProduct} from 'commerce/state/prices'; +import {addPriceFromExtracted, getLatestPriceForProduct, getOldestPriceForProduct} from 'commerce/state/prices'; import {getAllProducts, getProduct, getProductIdFromExtracted} from 'commerce/state/products'; import {wait} from 'commerce/utils'; +import {recordEvent} from 'commerce/telemetry/extension'; /** * Remove the x-frame-options header, so that the product page can load in the @@ -85,11 +86,25 @@ async function fetchLatestPrice(product, delay) { * price history with the latest price. * @param {ExtractedProduct} data */ -export function updateProductWithExtracted(data) { +export async function updateProductWithExtracted(data) { const state = store.getState(); const id = getProductIdFromExtracted(data); const product = getProduct(state, id); if (product) { - store.dispatch(addPriceFromExtracted(data)); + const isPriceChange = await store.dispatch(addPriceFromExtracted(data)); + if (isPriceChange) { + // Record the detect_price_change event + const previousPrice = getLatestPriceForProduct(state, id); + // Need to refetch state, since we just added a price entry for this product + const updatedState = store.getState(); + const latestPrice = getLatestPriceForProduct(updatedState, id); + const originalPrice = getOldestPriceForProduct(updatedState, id); + recordEvent('detect_price_change', 'product_page', null, { + price: latestPrice.amount.getAmount(), + price_prev: previousPrice.amount.getAmount(), + price_orig: originalPrice.amount.getAmount(), + product_key: product.anonId, + }); + } } } diff --git a/src/state/prices.js b/src/state/prices.js index 8e17f9c..6b88719 100644 --- a/src/state/prices.js +++ b/src/state/prices.js @@ -211,7 +211,8 @@ export default function reducer(state = initialState(), action) { // Action Creators /** - * Adds a new price to the store. + * Adds a new price to the store. Returns true if the extracted price + * is different than the last known price in state. * @param {ExtractedProduct} data */ export function addPriceFromExtracted(data) { @@ -227,7 +228,14 @@ export function addPriceFromExtracted(data) { // Potentially trigger an alert since there's a new price in town. dispatch(triggerPriceAlert(price)); + + // If this isn't the first price for this product, record detect_price_change event + const prices = getPricesForProduct(state, price.productId); + if (prices.length >= 1) { + return true; + } } + return false; }; } diff --git a/src/telemetry/extension.js b/src/telemetry/extension.js index fdabec4..be22d5b 100644 --- a/src/telemetry/extension.js +++ b/src/telemetry/extension.js @@ -115,6 +115,7 @@ const EVENTS = { objects: ['product_page'], extra_keys: [ 'price', + 'price_prev', 'price_orig', 'product_key', ...DEFAULT_EXTRAS, From 16a8fa37913159e51686e3c2250338f459aad2f1 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Wed, 31 Oct 2018 10:34:26 -0700 Subject: [PATCH 007/140] #158: Add badge_toolbar_button and send_notification probes Add badge_toolbar_button and send_notification probes: * Add an additional extra key, 'price_last_high' to 'send_notification' and 'open_external_page' (with 'element' value of 'system_notification') and update METRICS.md. * Add a 'sendTelemetry' flag for the 'sendProductToBackground' function to also be removed when the 'resend' code is removed in './src/extraction/index.js'. * Due to the fix for Issue #192, I was seeing some extra 'badge_toolbar_button' events (with 'badge_type' of 'add') as we are resending extracted product information 5 and 10 seconds after the product page loads. * Update METRICS.md to clarify when 'badge_toolbar_button' with a 'badge_type' of 'price_alert' fires, since it will continue to fire for the same price alert until that alert is dismissed which is not obvious. --- docs/METRICS.md | 6 ++++++ src/background/extraction.js | 8 +++++++- src/background/price_alerts.js | 13 ++++++++++++- src/background/price_updates.js | 2 +- src/extraction/index.js | 8 +++++--- src/telemetry/extension.js | 3 +++ 6 files changed, 34 insertions(+), 6 deletions(-) diff --git a/docs/METRICS.md b/docs/METRICS.md index f018630..d394729 100644 --- a/docs/METRICS.md +++ b/docs/METRICS.md @@ -143,6 +143,8 @@ Below is a sample ping for the `badge_toolbar_button` and `visit_supported_site` - `method`: The extraction method that was successful, if any. One of: 'fathom', 'fallback' or 'neither'. A value of 'neither' means that extraction failed. - `'price'`: The price of the product in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only). - `'price_alert'`: 'true' if the product has an active Price Alert; otherwise 'false'. +- `'price_last_high'`: The last high price of the product in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only). + - A high price is, semantically, the price that there's been an interesting drop from to warrant alerting the user. Practically, it is the highest price since the previous price alert. - `'price_orig'`: The original price of the product in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only). - `'price_prev'`: The previous price of the product when different from the latest price (`price`) in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only). - `'product_index'`: The index of the product in the product listing. The top most list item is index '0'. The list is sorted by date added, descending (#113). @@ -216,6 +218,8 @@ Fired when the user clicks on a UI element in the extension that opens a page in - `'price_alert'` - `'price_orig'` - `'product_key'` + - `'system_notification'` only: + - `'price_last_high'` - `'product_card'` only: - `'product_index'` @@ -313,6 +317,7 @@ Fired whenever a price change (of any magnitude and in any direction) is detecte Fired whenever the toolbar is badged in response to: 1. A successful product extraction or 2. A Price Alert + - Note: For Price Alerts, this event will continue to trigger after the initial Price Alert is shown to the user until the Price Alert is dismissed (per the [UX spec](https://mozilla.invisionapp.com/share/UFNSHAIMT4V#/screens/317130676_Artboard_1) and when a system notification is clicked). #### Payload properties @@ -336,6 +341,7 @@ Fired whenever a system notification is sent to the user notifying them of a Pri - `'system_notification'` - `extra_keys`: Object - `'price'` + - `'price_last_high'` - `'price_orig'` - `'product_key'` - `'tracked_prods'` diff --git a/src/background/extraction.js b/src/background/extraction.js index c602064..ac17d7b 100644 --- a/src/background/extraction.js +++ b/src/background/extraction.js @@ -10,6 +10,7 @@ import config from 'commerce/config'; import {updateProductWithExtracted} from 'commerce/background/price_updates'; import {isValidExtractedProduct} from 'commerce/state/products'; +import {recordEvent} from 'commerce/telemetry/extension'; /** * Triggers background tasks when a product is extracted from a webpage. Along @@ -20,7 +21,7 @@ import {isValidExtractedProduct} from 'commerce/state/products'; * @param {MessageSender} sender * The sender for the content script that extracted this product */ -export async function handleExtractedProductData({extractedProduct}, sender) { +export async function handleExtractedProductData({extractedProduct, sendTelemetry = true}, sender) { // Do nothing if the extracted product isn't valid. if (!isValidExtractedProduct(extractedProduct)) { return; @@ -51,6 +52,11 @@ export async function handleExtractedProductData({extractedProduct}, sender) { tabId, }); browser.browserAction.setBadgeText({text: '✚', tabId}); + if (sendTelemetry) { + await recordEvent('badge_toolbar_button', 'toolbar_button', null, { + badge_type: 'add', + }); + } } // Update saved product data if it exists diff --git a/src/background/price_alerts.js b/src/background/price_alerts.js index 82e23fd..361e9c4 100644 --- a/src/background/price_alerts.js +++ b/src/background/price_alerts.js @@ -28,13 +28,16 @@ import {recordEvent} from 'commerce/telemetry/extension'; * Update the extension UI based on the current state of active price alerts. * Should be called whenever price alerts may have changed. */ -export function handlePriceAlerts() { +export async function handlePriceAlerts() { const state = store.getState(); const activeAlerts = getActivePriceAlerts(state); // Show the browser action badge if there are any active alerts. if (activeAlerts.length > 0) { browser.browserAction.setBadgeText({text: `${activeAlerts.length}`}); + await recordEvent('badge_toolbar_button', 'toolbar_button', null, { + badge_type: 'price_alert', + }); } else { browser.browserAction.setBadgeText({text: null}); } @@ -61,6 +64,12 @@ export function handlePriceAlerts() { title: `Price Alert: ${product.title}`, message: `${vendorName} · Originally ${original}, high of ${high}, now ${now}`, }); + await recordEvent('send_notification', 'system_notification', null, { // eslint-disable-line no-await-in-loop + price: alertPrice.amount.getAmount(), + price_last_high: highPriceAmount.getAmount(), + price_orig: originalPrice.amount.getAmount(), + product_key: product.anonId, + }); // Update state now that we've shown it store.dispatch(showPriceAlert(alert)); @@ -86,10 +95,12 @@ export async function handleNotificationClicked(notificationId) { // Record open_external_page event const latestPrice = getLatestPriceForProduct(state, product.id); const originalPrice = getOldestPriceForProduct(state, product.id); + const highPriceAmount = Dinero({amount: alert.highPriceAmount}); await recordEvent('open_external_page', 'ui_element', null, { element: 'system_notification', price: latestPrice.amount.getAmount(), price_alert: alert.active, + price_last_high: highPriceAmount.getAmount(), price_orig: originalPrice.amount.getAmount(), product_key: product.anonId, }); diff --git a/src/background/price_updates.js b/src/background/price_updates.js index 162f957..c25f817 100644 --- a/src/background/price_updates.js +++ b/src/background/price_updates.js @@ -99,7 +99,7 @@ export async function updateProductWithExtracted(data) { const updatedState = store.getState(); const latestPrice = getLatestPriceForProduct(updatedState, id); const originalPrice = getOldestPriceForProduct(updatedState, id); - recordEvent('detect_price_change', 'product_page', null, { + await recordEvent('detect_price_change', 'product_page', null, { price: latestPrice.amount.getAmount(), price_prev: previousPrice.amount.getAmount(), price_orig: originalPrice.amount.getAmount(), diff --git a/src/extraction/index.js b/src/extraction/index.js index e51176b..f5dbff5 100644 --- a/src/extraction/index.js +++ b/src/extraction/index.js @@ -42,9 +42,10 @@ function extractProduct() { return null; } -async function sendProductToBackground(extractedProduct) { +async function sendProductToBackground(extractedProduct, sendTelemetry) { return browser.runtime.sendMessage({ type: 'extracted-product', + sendTelemetry, extractedProduct: { ...extractedProduct, url: document.location.href, @@ -111,8 +112,9 @@ async function attemptExtraction() { // Messy workaround for bug 1493470: Resend product info to the background // script twice in case subframe loads clear the toolbar icon. - // TODO(osmose): Remove once Firefox 64 hits the release channel. - const resend = () => sendProductToBackground(extractedProduct); + // TODO(osmose): Remove once Firefox 64 hits the release channel, including second argument + // to sendProductToBackground. + const resend = () => sendProductToBackground(extractedProduct, false); setTimeout(resend, 5000); setTimeout(resend, 10000); diff --git a/src/telemetry/extension.js b/src/telemetry/extension.js index be22d5b..9c83b0a 100644 --- a/src/telemetry/extension.js +++ b/src/telemetry/extension.js @@ -52,6 +52,8 @@ const EVENTS = { 'price_alert', 'price_orig', 'product_key', + // For 'element' value of 'system_notification' only + 'price_last_high', // For 'element' value 'product_card' only 'product_index', ], @@ -137,6 +139,7 @@ const EVENTS = { objects: ['system_notification'], extra_keys: [ 'price', + 'price_last_high', 'price_orig', 'product_key', ...DEFAULT_EXTRAS, From 6bf71516aa6f6c6bb55a05a9f7e89a5d3b6eb7f0 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Wed, 31 Oct 2018 15:22:03 -0700 Subject: [PATCH 008/140] Rename telemetry event category to 'extension.price_wise' --- docs/METRICS.md | 6 +++--- src/telemetry/extension.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/METRICS.md b/docs/METRICS.md index d394729..f241d6a 100644 --- a/docs/METRICS.md +++ b/docs/METRICS.md @@ -86,7 +86,7 @@ We will be sending pings using [Event Telemetry](https://firefox-source-docs.moz Each event will exist as part of the `main` ping under `payload.processes.dynamic.events` as an array in the `events` array (see Appendix B for how to view the events in `about:telemetry`). The data types of individual fields for each event follow the Event Telemetry [serialization format](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/events.html#serialization-format). -The telemetry category for events is `'extension.price_alerts'`. +The telemetry category for events is `'extension.price_wise'`. Below is a sample ping for the `badge_toolbar_button` and `visit_supported_site` events. @@ -103,7 +103,7 @@ Below is a sample ping for the `badge_toolbar_button` and `visit_supported_site` "events": [ [ 2079, - "extension.price_alerts", + "extension.price_wise", "badge_toolbar_button", "toolbar_button", null, @@ -114,7 +114,7 @@ Below is a sample ping for the `badge_toolbar_button` and `visit_supported_site` ], [ 2081, - "extension.price_alerts", + "extension.price_wise", "visit_supported_site", "supported_site", null, diff --git a/src/telemetry/extension.js b/src/telemetry/extension.js index 9c83b0a..1b7593e 100644 --- a/src/telemetry/extension.js +++ b/src/telemetry/extension.js @@ -11,7 +11,7 @@ import {shouldCollectTelemetry} from 'commerce/privacy'; import store from 'commerce/state'; import {getAllProducts} from 'commerce/state/products'; -const CATEGORY = 'extension.price_alerts'; +const CATEGORY = 'extension.price_wise'; const DEFAULT_EXTRAS = [ 'tracked_prods', From 0bca7d982a28862e66c296e1509a2890dbccf9e3 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Thu, 1 Nov 2018 11:02:17 -0700 Subject: [PATCH 009/140] Fix #158: Add 'attempt_extraction' and 'complete_extraction' probes * Update 'method' extra key for 'complete_extraction' event to have values of 'fathom', 'css_selectors', 'open_graph' or 'none' to distinguish between the two fallback extraction methods to Fathom: CSS Selectors or Open Graph attributes. * Note: Since none of our five supported sites use Open Graph attributes currently for product information, we should not expect to see any successful extraction using that method for the MVP. * Important caveats for making conclusions using these probes as-is: * The coverage values that these probes will suggest will not be very accurate initially until we ensure we are extracting on only **product pages** for a supported site, rather than any page on the site (see Issues #225 and #181). * Successful extraction does not mean that the information extracted for the product is correct. It only means that _a_ value was extracted for each product feature (i.e. title, image and price) on the page. --- docs/METRICS.md | 2 +- src/extraction/index.js | 42 ++++++++++++++++++++++++++++------------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/docs/METRICS.md b/docs/METRICS.md index f241d6a..c038c08 100644 --- a/docs/METRICS.md +++ b/docs/METRICS.md @@ -140,7 +140,7 @@ Below is a sample ping for the `badge_toolbar_button` and `visit_supported_site` - `'badge_type'`: Indicates what, if any, badge was present on the browserAction toolbar button. One of 'add', 'price_alert', or 'none'. A value of 'unknown' is possible if the badge text is unrecognized. - `'extraction_id'`: A unique identifier to associate an extraction attempt to an extraction completion event for a given page. - `'is_bg_update'`: 'true' if the extraction is associated with a background price check; otherwise 'false'. -- `method`: The extraction method that was successful, if any. One of: 'fathom', 'fallback' or 'neither'. A value of 'neither' means that extraction failed. +- `method`: The extraction method that was successful, if any. One of: 'fathom', 'css_selectors', 'open_graph' or 'none'. A value of 'none' means that all extraction methods failed. - `'price'`: The price of the product in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only). - `'price_alert'`: 'true' if the product has an active Price Alert; otherwise 'false'. - `'price_last_high'`: The last high price of the product in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only). diff --git a/src/extraction/index.js b/src/extraction/index.js index f5dbff5..dc64165 100644 --- a/src/extraction/index.js +++ b/src/extraction/index.js @@ -8,9 +8,11 @@ * been parsed but before all resources have been loaded. */ +import uuidv4 from 'uuid/v4'; + import config from 'commerce/config/content'; import extractProductWithFathom from 'commerce/extraction/fathom'; -import extractProductWithFallback from 'commerce/extraction/selector'; +import extractProductWithCSSSelectors from 'commerce/extraction/selector'; import extractProductWithOpenGraph from 'commerce/extraction/open_graph'; import {shouldExtract} from 'commerce/privacy'; import recordEvent from 'commerce/telemetry/content'; @@ -20,25 +22,39 @@ import recordEvent from 'commerce/telemetry/content'; * return either a valid ExtractedProduct, or null if a valid product could not * be found. */ -const EXTRACTION_METHODS = [ - extractProductWithFathom, - extractProductWithFallback, - extractProductWithOpenGraph, -]; +const EXTRACTION_METHODS = { + fathom: extractProductWithFathom, + css_selectors: extractProductWithCSSSelectors, + open_graph: extractProductWithOpenGraph, +}; /** * Perform product extraction, trying each method from EXTRACTION_METHODS in * order until one of them returns a truthy result. * @return {ExtractedProduct|null} */ -function extractProduct() { - for (const extract of EXTRACTION_METHODS) { +function extractProduct(isBackgroundUpdate) { + const baseExtra = { + extraction_id: uuidv4(), + is_bg_update: isBackgroundUpdate, + }; + recordEvent('attempt_extraction', 'product_page', null, { + ...baseExtra, + }); + for (const [method, extract] of Object.entries(EXTRACTION_METHODS)) { const extractedProduct = extract(window.document); if (extractedProduct) { + recordEvent('complete_extraction', 'product_page', null, { + ...baseExtra, + method, + }); return extractedProduct; } } - + recordEvent('complete_extraction', 'product_page', null, { + ...baseExtra, + method: 'none', + }); return null; } @@ -58,8 +74,8 @@ async function sendProductToBackground(extractedProduct, sendTelemetry) { * Checks to see if any product information for the page was found, * and if so, sends it to the background script. */ -async function attemptExtraction() { - const extractedProduct = extractProduct(); +async function attemptExtraction(isBackgroundUpdate) { + const extractedProduct = extractProduct(isBackgroundUpdate); if (extractedProduct) { await sendProductToBackground(extractedProduct); } @@ -105,9 +121,9 @@ async function attemptExtraction() { } // Extract immediately, and again if the readyState changes. - let extractedProduct = await attemptExtraction(); + let extractedProduct = await attemptExtraction(isBackgroundUpdate); document.addEventListener('readystatechange', async () => { - extractedProduct = await attemptExtraction(); + extractedProduct = await attemptExtraction(isBackgroundUpdate); }); // Messy workaround for bug 1493470: Resend product info to the background From 349787b8d566776f55cd8e9a38eb32b3ee79d66f Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Fri, 2 Nov 2018 09:41:52 -0700 Subject: [PATCH 010/140] Collapse privacy extra keys into a single key Event Telemetry [limits the max number of extra keys](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/events.html#limits) for an event to 10. In the fix for Issue #185, where three new privacy-related extra keys were added to every telemetry event, the number of extra keys for the 'open_external_page' event went to 11, which causes event telemetry to fail at the registration step. This patch collapses these 3 privacy keys into a single key that points to a stringified JSON object. --- docs/METRICS.md | 21 +++++++++++---------- src/telemetry/extension.js | 12 ++++++------ 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/docs/METRICS.md b/docs/METRICS.md index c038c08..68b09ce 100644 --- a/docs/METRICS.md +++ b/docs/METRICS.md @@ -138,6 +138,17 @@ Below is a sample ping for the `badge_toolbar_button` and `visit_supported_site` `extra_keys` are keys in the [optional `extra` object field](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/events.html#serialization-format) for telemetry events. All `extra_keys` and their values are strings. - `'badge_type'`: Indicates what, if any, badge was present on the browserAction toolbar button. One of 'add', 'price_alert', or 'none'. A value of 'unknown' is possible if the badge text is unrecognized. +- `'dnt_tp_cookie'`: The status of three different privacy settings collapsed into a single, stringified JSON object: + - `'dnt'`: 'true' if the user has [requested not to be tracked by websites, content, or advertising](https://support.mozilla.org/en-US/kb/how-do-i-turn-do-not-track-feature); otherwise 'false'. + - `'tp'`: The user's [tracking protection](https://support.mozilla.org/en-US/kb/tracking-protection) setting: + - `'always'`: Tracking Protection is on + - `'never'`: Tracking Protection is off + - `'private_browsing'`: Tracking Protection is on in private browsing windows only + - `'cookie'`: The user's [cookie setting](https://support.mozilla.org/en-US/kb/disable-third-party-cookies): + - `'allow_all'`: Accept all cookies + - `'reject_all'`: Reject all cookies + - `'reject_third_party'`: Reject all third-party cookies + - `'allow_visited'`: Accept a third-party cookie only if the cookie's top-level domain already has at least one cookie. - `'extraction_id'`: A unique identifier to associate an extraction attempt to an extraction completion event for a given page. - `'is_bg_update'`: 'true' if the extraction is associated with a background price check; otherwise 'false'. - `method`: The extraction method that was successful, if any. One of: 'fathom', 'css_selectors', 'open_graph' or 'none'. A value of 'none' means that all extraction methods failed. @@ -161,16 +172,6 @@ Below is a sample ping for the `badge_toolbar_button` and `visit_supported_site` - `'product_card'`: Sends the user to the product page for the given Product Card. - `'system_notification'`: Sends the user to the product page for the Price Alert displayed in the notification. - `'walmart_link'`: Sends the user to Walmart. -- `'privacy_dnt'`: 'true' if the user has [requested not to be tracked by websites, content, or advertising](https://support.mozilla.org/en-US/kb/how-do-i-turn-do-not-track-feature); otherwise 'false'. -- `'privacy_tp'`: The user's [tracking protection](https://support.mozilla.org/en-US/kb/tracking-protection) setting: - - `'always'`: Tracking Protection is on - - `'never'`: Tracking Protection is off - - `'private_browsing'`: Tracking Protection is on in private browsing windows only -- `'privacy_cookie'`: The user's [cookie setting](https://support.mozilla.org/en-US/kb/disable-third-party-cookies): - - `'allow_all'`: Accept all cookies - - `'reject_all'`: Reject all cookies - - `'reject_third_party'`: Reject all third-party cookies - - `'allow_visited'`: Accept a third-party cookie only if the cookie's top-level domain already has at least one cookie. ## Collection (User Events) diff --git a/src/telemetry/extension.js b/src/telemetry/extension.js index 1b7593e..d726f4c 100644 --- a/src/telemetry/extension.js +++ b/src/telemetry/extension.js @@ -15,9 +15,7 @@ const CATEGORY = 'extension.price_wise'; const DEFAULT_EXTRAS = [ 'tracked_prods', - 'privacy_dnt', - 'privacy_tp', - 'privacy_cookie', + 'dnt_tp_cookie', ]; const EVENTS = { @@ -181,9 +179,11 @@ export async function recordEvent(method, object, value, extraBase = {}) { const extra = { ...extraBase, tracked_prods: getAllProducts(store.getState()).length, - privacy_dnt: navigator.doNotTrack === '1', - privacy_tp: (await browser.privacy.websites.trackingProtectionMode.get({})).value, - privacy_cookie: (await browser.privacy.websites.cookieConfig.get({})).value.behavior, + dnt_tp_cookie: JSON.stringify({ + dnt: (navigator.doNotTrack === '1'), + tp: (await browser.privacy.websites.trackingProtectionMode.get({})).value, + cookie: (await browser.privacy.websites.cookieConfig.get({})).value.behavior, + }), }; // Convert all extra key values to strings as required by event telemetry From e633803432ecceaf9fb5d6cc476f5bd38b4d95e7 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Fri, 2 Nov 2018 10:06:11 -0700 Subject: [PATCH 011/140] Update METRICS.md Break up Extra Keys section into Common Extra Keys and Event-specific Extra Keys subsections. Update Sample Ping section to include additional common keys added from Issue #185. --- docs/METRICS.md | 80 +++++++++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/docs/METRICS.md b/docs/METRICS.md index 68b09ce..224d9f5 100644 --- a/docs/METRICS.md +++ b/docs/METRICS.md @@ -88,7 +88,7 @@ Each event will exist as part of the `main` ping under `payload.processes.dynami The telemetry category for events is `'extension.price_wise'`. -Below is a sample ping for the `badge_toolbar_button` and `visit_supported_site` events. +Below is a sample ping for the `visit_supported_site` and `badge_toolbar_button` events. ```javascript { @@ -102,24 +102,26 @@ Below is a sample ping for the `badge_toolbar_button` and `visit_supported_site` // ... "events": [ [ - 2079, + 733502, "extension.price_wise", - "badge_toolbar_button", - "toolbar_button", + "visit_supported_site", + "supported_site", null, { - "badge_type": "add", - "tracked_prods": "5" + "tracked_prods": "0", + "dnt_tp_cookie": "{\"dnt\":false,\"tp\":\"private_browsing\",\"cookie\":\"allow_visited\"}" } ], [ - 2081, + 733530, "extension.price_wise", - "visit_supported_site", - "supported_site", + "badge_toolbar_button", + "toolbar_button", null, { - "tracked_prods": "5" + "badge_type": "add", + "tracked_prods": "0", + "dnt_tp_cookie": "{\"dnt\":false,\"tp\":\"private_browsing\",\"cookie\":\"allow_visited\"}" } ] ] @@ -133,11 +135,14 @@ Below is a sample ping for the `badge_toolbar_button` and `visit_supported_site` ``` -## `extra_keys` +## Extra Keys `extra_keys` are keys in the [optional `extra` object field](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/events.html#serialization-format) for telemetry events. All `extra_keys` and their values are strings. -- `'badge_type'`: Indicates what, if any, badge was present on the browserAction toolbar button. One of 'add', 'price_alert', or 'none'. A value of 'unknown' is possible if the badge text is unrecognized. +### Common Extra Keys + +Some `extra_keys` are sent with every telemetry event recorded by the extension: +- `'tracked_prods'`: The number of products the user is tracking. - `'dnt_tp_cookie'`: The status of three different privacy settings collapsed into a single, stringified JSON object: - `'dnt'`: 'true' if the user has [requested not to be tracked by websites, content, or advertising](https://support.mozilla.org/en-US/kb/how-do-i-turn-do-not-track-feature); otherwise 'false'. - `'tp'`: The user's [tracking protection](https://support.mozilla.org/en-US/kb/tracking-protection) setting: @@ -149,18 +154,10 @@ Below is a sample ping for the `badge_toolbar_button` and `visit_supported_site` - `'reject_all'`: Reject all cookies - `'reject_third_party'`: Reject all third-party cookies - `'allow_visited'`: Accept a third-party cookie only if the cookie's top-level domain already has at least one cookie. -- `'extraction_id'`: A unique identifier to associate an extraction attempt to an extraction completion event for a given page. -- `'is_bg_update'`: 'true' if the extraction is associated with a background price check; otherwise 'false'. -- `method`: The extraction method that was successful, if any. One of: 'fathom', 'css_selectors', 'open_graph' or 'none'. A value of 'none' means that all extraction methods failed. -- `'price'`: The price of the product in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only). -- `'price_alert'`: 'true' if the product has an active Price Alert; otherwise 'false'. -- `'price_last_high'`: The last high price of the product in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only). - - A high price is, semantically, the price that there's been an interesting drop from to warrant alerting the user. Practically, it is the highest price since the previous price alert. -- `'price_orig'`: The original price of the product in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only). -- `'price_prev'`: The previous price of the product when different from the latest price (`price`) in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only). -- `'product_index'`: The index of the product in the product listing. The top most list item is index '0'. The list is sorted by date added, descending (#113). -- `'product_key'`: A unique identifier for the product relative to other products for a given user. This key is _not_ unique to the product across all users. -- `'tracked_prods'`: The number of products the user is tracking. + +### Event-specific Extra Keys + +- `'badge_type'`: Indicates what, if any, badge was present on the browserAction toolbar button. One of 'add', 'price_alert', or 'none'. A value of 'unknown' is possible if the badge text is unrecognized. - `'element'`: The extension UI element that the user clicked to open a page in a new tab. Note: All `*_link` elements exist in the Onboarding Popup only. One of... - `'amazon_link'`: Sends the user to Amazon. - `'best_buy_link'`: Sends the user to Best Buy. @@ -172,6 +169,17 @@ Below is a sample ping for the `badge_toolbar_button` and `visit_supported_site` - `'product_card'`: Sends the user to the product page for the given Product Card. - `'system_notification'`: Sends the user to the product page for the Price Alert displayed in the notification. - `'walmart_link'`: Sends the user to Walmart. +- `'extraction_id'`: A unique identifier to associate an extraction attempt to an extraction completion event for a given page. +- `'is_bg_update'`: 'true' if the extraction is associated with a background price check; otherwise 'false'. +- `method`: The extraction method that was successful, if any. One of: 'fathom', 'css_selectors', 'open_graph' or 'none'. A value of 'none' means that all extraction methods failed. +- `'price'`: The price of the product in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only). +- `'price_alert'`: 'true' if the product has an active Price Alert; otherwise 'false'. +- `'price_last_high'`: The last high price of the product in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only). + - A high price is, semantically, the price that there's been an interesting drop from to warrant alerting the user. Practically, it is the highest price since the previous price alert. +- `'price_orig'`: The original price of the product in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only). +- `'price_prev'`: The previous price of the product when different from the latest price (`price`) in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only). +- `'product_index'`: The index of the product in the product listing. The top most list item is index '0'. The list is sorted by date added, descending (#113). +- `'product_key'`: A unique identifier for the product relative to other products for a given user. This key is _not_ unique to the product across all users. ## Collection (User Events) @@ -186,7 +194,7 @@ Fired when the user navigates to a Supported Site. - `objects`: String - `'supported_site'` - `extra_keys`: Object - - `'tracked_prods'` + - [Common extra keys](#common-extra-keys) ### `open_popup` @@ -199,7 +207,7 @@ Fired when the user clicks the Price Wise browserAction toolbar button to open t - `'toolbar_button'` - `extra_keys`: Object - `'badge_type'` - - `'tracked_prods'` + - [Common extra keys](#common-extra-keys) ### `open_external_page` @@ -212,7 +220,7 @@ Fired when the user clicks on a UI element in the extension that opens a page in - `'ui_element'` - `extra_keys`: Object; which keys are included depends on the value of the `'element'` extra key. - All values: - - `'tracked_prods'` + - [Common extra keys](#common-extra-keys) - `'element'` - `'system_notification'` and `'product_card'` only: - `'price'` @@ -237,7 +245,7 @@ Fired when the user clicks the add product button in the browserAction popup. - `extra_keys`: Object - `'price'` - `'product_key'` - - `'tracked_prods'` + - [Common extra keys](#common-extra-keys) ### `delete_product` @@ -255,7 +263,7 @@ Fired when the user clicks a delete product button in a Product Card in the brow - `'price_orig'` - `'product_index'` - `'product_key'` - - `'tracked_prods'` + - [Common extra keys](#common-extra-keys) ### `undo_delete_product` @@ -273,7 +281,7 @@ Fired when the user clicks an undo button in a Product Card in the browserAction - `'price_orig'` - `'product_index'` - `'product_key'` - - `'tracked_prods'` + - [Common extra keys](#common-extra-keys) ### `uninstall` @@ -291,7 +299,7 @@ Fired when the user hides the extension's browserAction toolbar button from the - `'toolbar_button'` - `extra_keys`: Object - `'badge_type'` - - `'tracked_prods'` + - [Common extra keys](#common-extra-keys) ## Collection (Non-User Events) @@ -311,7 +319,7 @@ Fired whenever a price change (of any magnitude and in any direction) is detecte - `'price_orig'` - `'price_prev'` - `'product_key'` - - `'tracked_prods'` + - [Common extra keys](#common-extra-keys) ### `badge_toolbar_button` @@ -328,7 +336,7 @@ Fired whenever the toolbar is badged in response to: - `'toolbar_button'` - `extra_keys`: Object - `'badge_type'` - - `'tracked_prods'` + - [Common extra keys](#common-extra-keys) ### `send_notification` @@ -345,7 +353,7 @@ Fired whenever a system notification is sent to the user notifying them of a Pri - `'price_last_high'` - `'price_orig'` - `'product_key'` - - `'tracked_prods'` + - [Common extra keys](#common-extra-keys) ### `attempt_extraction` @@ -360,7 +368,7 @@ Fired whenever a supported page loads and the add-on attempts to extract product - `extra_keys`: Object - `'extraction_id'` - `'is_bg_update'` - - `'tracked_prods'` + - [Common extra keys](#common-extra-keys) ### `complete_extraction` @@ -376,7 +384,7 @@ Fired whenever extraction on a supported page completes, whether or not the extr - `'extraction_id'` - `'is_bg_update'` - `method` - - `'tracked_prods'` + - [Common extra keys](#common-extra-keys) ## Opt-out From e88c84b71a0c5feef382d924301fcdf1e79529e4 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Fri, 2 Nov 2018 10:11:11 -0700 Subject: [PATCH 012/140] Remove 'uninstall' event from list of events to register Issue #157's patch removed this event from METRICS.md, but failed to remove it from the code. The uninstall event is recorded by the Addons Manager. It is not possible to record from a WE, as the extension is uninstalled before the event can be recorded. --- src/telemetry/extension.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/telemetry/extension.js b/src/telemetry/extension.js index d726f4c..b0db585 100644 --- a/src/telemetry/extension.js +++ b/src/telemetry/extension.js @@ -92,12 +92,6 @@ const EVENTS = { ...DEFAULT_EXTRAS, ], }, - // User uninstalls the extension - uninstall: { - methods: ['uninstall'], - objects: ['uninstall'], - extra_keys: ['tracked_prods'], - }, // User hides the toolbar button for the extension hide_toolbar_button: { methods: ['hide_toolbar_button'], From 6ea6684c56426d606670fa20ce71dc0dc9b51dd9 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Fri, 2 Nov 2018 16:22:27 -0700 Subject: [PATCH 013/140] Incorporate Osmose's feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Note: This fix is complicated by the fact that a 'price alert' badge only changes the global badge state. An 'add' product badge changes the tab-specific badge state, which takes precedence over the global badge state. To avoid event duplication for 'badge_toolbar_button': * Add 'hasBadgeTextChanged' function with optional 'tabId' argument, so that the event only fires if the badge text has changed. * Previously, we were getting a bunch of redundant `badge_toolbar_button` events for ‘price_alert’ any time the state was changed and we’re on a page with an ‘add’ badge. Since `handlePriceAlerts` is called every time state changes in any way (`store.subscribe(handlePriceAlerts)`), we now check to see if the badge text has changed for a price alert badge on the global browserAction button before recording the 'badge_toolbar_button' with badge type 'price_alert' event. * Previously, if tab 1 had badge type 'add' and tab 2 had badge type 'price_alert', and I switch to tab 2 before any calls to 'resend' (#220) are made from tab 1, I would get two extra 'badge_toolbar_button' of type 'add' events. Adding the 'tabId' optional argument fixes this bug. --- src/background/extraction.js | 8 +-- src/background/price_alerts.js | 15 ++--- src/background/price_updates.js | 11 ++-- src/extraction/index.js | 97 ++++++++++++++++++++------------- src/state/prices.js | 8 +-- src/telemetry/extension.js | 14 +++++ 6 files changed, 92 insertions(+), 61 deletions(-) diff --git a/src/background/extraction.js b/src/background/extraction.js index ac17d7b..3e8999a 100644 --- a/src/background/extraction.js +++ b/src/background/extraction.js @@ -10,7 +10,7 @@ import config from 'commerce/config'; import {updateProductWithExtracted} from 'commerce/background/price_updates'; import {isValidExtractedProduct} from 'commerce/state/products'; -import {recordEvent} from 'commerce/telemetry/extension'; +import {recordEvent, hasBadgeTextChanged} from 'commerce/telemetry/extension'; /** * Triggers background tasks when a product is extracted from a webpage. Along @@ -21,7 +21,7 @@ import {recordEvent} from 'commerce/telemetry/extension'; * @param {MessageSender} sender * The sender for the content script that extracted this product */ -export async function handleExtractedProductData({extractedProduct, sendTelemetry = true}, sender) { +export async function handleExtractedProductData({extractedProduct}, sender) { // Do nothing if the extracted product isn't valid. if (!isValidExtractedProduct(extractedProduct)) { return; @@ -51,12 +51,12 @@ export async function handleExtractedProductData({extractedProduct, sendTelemetr color: await config.get('badgeDetectBackground'), tabId, }); - browser.browserAction.setBadgeText({text: '✚', tabId}); - if (sendTelemetry) { + if (await hasBadgeTextChanged('✚', sender.tab.id)) { await recordEvent('badge_toolbar_button', 'toolbar_button', null, { badge_type: 'add', }); } + browser.browserAction.setBadgeText({text: '✚', tabId}); } // Update saved product data if it exists diff --git a/src/background/price_alerts.js b/src/background/price_alerts.js index 361e9c4..b630e25 100644 --- a/src/background/price_alerts.js +++ b/src/background/price_alerts.js @@ -22,7 +22,7 @@ import { } from 'commerce/state/prices'; import {getProduct} from 'commerce/state/products'; import {getVendor} from 'commerce/state/vendors'; -import {recordEvent} from 'commerce/telemetry/extension'; +import {recordEvent, hasBadgeTextChanged} from 'commerce/telemetry/extension'; /** * Update the extension UI based on the current state of active price alerts. @@ -34,10 +34,12 @@ export async function handlePriceAlerts() { // Show the browser action badge if there are any active alerts. if (activeAlerts.length > 0) { + if (await hasBadgeTextChanged(`${activeAlerts.length}`)) { + await recordEvent('badge_toolbar_button', 'toolbar_button', null, { + badge_type: 'price_alert', + }); + } browser.browserAction.setBadgeText({text: `${activeAlerts.length}`}); - await recordEvent('badge_toolbar_button', 'toolbar_button', null, { - badge_type: 'price_alert', - }); } else { browser.browserAction.setBadgeText({text: null}); } @@ -66,7 +68,7 @@ export async function handlePriceAlerts() { }); await recordEvent('send_notification', 'system_notification', null, { // eslint-disable-line no-await-in-loop price: alertPrice.amount.getAmount(), - price_last_high: highPriceAmount.getAmount(), + price_last_high: alert.highPriceAmount, price_orig: originalPrice.amount.getAmount(), product_key: product.anonId, }); @@ -95,12 +97,11 @@ export async function handleNotificationClicked(notificationId) { // Record open_external_page event const latestPrice = getLatestPriceForProduct(state, product.id); const originalPrice = getOldestPriceForProduct(state, product.id); - const highPriceAmount = Dinero({amount: alert.highPriceAmount}); await recordEvent('open_external_page', 'ui_element', null, { element: 'system_notification', price: latestPrice.amount.getAmount(), price_alert: alert.active, - price_last_high: highPriceAmount.getAmount(), + price_last_high: alert.highPriceAmount, price_orig: originalPrice.amount.getAmount(), product_key: product.anonId, }); diff --git a/src/background/price_updates.js b/src/background/price_updates.js index c25f817..7c0bddf 100644 --- a/src/background/price_updates.js +++ b/src/background/price_updates.js @@ -91,16 +91,13 @@ export async function updateProductWithExtracted(data) { const id = getProductIdFromExtracted(data); const product = getProduct(state, id); if (product) { - const isPriceChange = await store.dispatch(addPriceFromExtracted(data)); - if (isPriceChange) { + const price = await store.dispatch(addPriceFromExtracted(data)); + if (price) { // Record the detect_price_change event const previousPrice = getLatestPriceForProduct(state, id); - // Need to refetch state, since we just added a price entry for this product - const updatedState = store.getState(); - const latestPrice = getLatestPriceForProduct(updatedState, id); - const originalPrice = getOldestPriceForProduct(updatedState, id); + const originalPrice = getOldestPriceForProduct(state, id); await recordEvent('detect_price_change', 'product_page', null, { - price: latestPrice.amount.getAmount(), + price: price.amount, price_prev: previousPrice.amount.getAmount(), price_orig: originalPrice.amount.getAmount(), product_key: product.anonId, diff --git a/src/extraction/index.js b/src/extraction/index.js index dc64165..87694d3 100644 --- a/src/extraction/index.js +++ b/src/extraction/index.js @@ -28,40 +28,72 @@ const EXTRACTION_METHODS = { open_graph: extractProductWithOpenGraph, }; +const IS_BACKGROUND_UPDATE = (function isBackgroundUpdate() { + let result = false; + try { + result = window.top.location.href.startsWith( + browser.runtime.getURL('/'), // URL is unique per-install / hard to forge + ); + } catch (err) { + // Non-background updates may throw a cross-origin error + } + return result; +}()); + +/** + * Helper class to record extraction-related telemetry events. + */ +class ExtractionAttempt { + constructor() { + this.baseExtra = { + extraction_id: uuidv4(), + is_bg_update: IS_BACKGROUND_UPDATE, + }; + } + + start() { + recordEvent('attempt_extraction', 'product_page', null, { + ...this.baseExtra, + }); + } + + succeed(methodName) { + recordEvent('complete_extraction', 'product_page', null, { + ...this.baseExtra, + method: methodName, + }); + } + + fail() { + recordEvent('complete_extraction', 'product_page', null, { + ...this.baseExtra, + method: 'none', + }); + } +} + /** * Perform product extraction, trying each method from EXTRACTION_METHODS in * order until one of them returns a truthy result. * @return {ExtractedProduct|null} */ -function extractProduct(isBackgroundUpdate) { - const baseExtra = { - extraction_id: uuidv4(), - is_bg_update: isBackgroundUpdate, - }; - recordEvent('attempt_extraction', 'product_page', null, { - ...baseExtra, - }); - for (const [method, extract] of Object.entries(EXTRACTION_METHODS)) { +function extractProduct() { + const attempt = new ExtractionAttempt(); + attempt.start(); + for (const [methodName, extract] of Object.entries(EXTRACTION_METHODS)) { const extractedProduct = extract(window.document); if (extractedProduct) { - recordEvent('complete_extraction', 'product_page', null, { - ...baseExtra, - method, - }); + attempt.succeed(methodName); return extractedProduct; } } - recordEvent('complete_extraction', 'product_page', null, { - ...baseExtra, - method: 'none', - }); + attempt.fail(); return null; } -async function sendProductToBackground(extractedProduct, sendTelemetry) { +async function sendProductToBackground(extractedProduct) { return browser.runtime.sendMessage({ type: 'extracted-product', - sendTelemetry, extractedProduct: { ...extractedProduct, url: document.location.href, @@ -74,8 +106,8 @@ async function sendProductToBackground(extractedProduct, sendTelemetry) { * Checks to see if any product information for the page was found, * and if so, sends it to the background script. */ -async function attemptExtraction(isBackgroundUpdate) { - const extractedProduct = extractProduct(isBackgroundUpdate); +async function attemptExtraction() { + const extractedProduct = extractProduct(); if (extractedProduct) { await sendProductToBackground(extractedProduct); } @@ -87,16 +119,8 @@ async function attemptExtraction(isBackgroundUpdate) { // If we're in an iframe, don't bother extracting a product EXCEPT if we were // started by the background script for a price check. const isInIframe = window !== window.top; - let isBackgroundUpdate = false; - try { - isBackgroundUpdate = window.top.location.href.startsWith( - browser.runtime.getURL('/'), // URL is unique per-install / hard to forge - ); - } catch (err) { - // Non-background updates may throw a cross-origin error - } - if (isInIframe && !isBackgroundUpdate) { + if (isInIframe && !IS_BACKGROUND_UPDATE) { return; } @@ -111,26 +135,25 @@ async function attemptExtraction(isBackgroundUpdate) { const url = new URL(document.location.href); const allowList = await config.get('extractionAllowlist'); const allowAll = allowList.length === 1 && allowList[0] === '*'; - if (!allowAll && !isBackgroundUpdate && !allowList.includes(url.host)) { + if (!allowAll && !IS_BACKGROUND_UPDATE && !allowList.includes(url.host)) { return; } // Record visit_supported_site event - if (!isBackgroundUpdate) { + if (!IS_BACKGROUND_UPDATE) { await recordEvent('visit_supported_site', 'supported_site'); } // Extract immediately, and again if the readyState changes. - let extractedProduct = await attemptExtraction(isBackgroundUpdate); + let extractedProduct = await attemptExtraction(); document.addEventListener('readystatechange', async () => { - extractedProduct = await attemptExtraction(isBackgroundUpdate); + extractedProduct = await attemptExtraction(); }); // Messy workaround for bug 1493470: Resend product info to the background // script twice in case subframe loads clear the toolbar icon. - // TODO(osmose): Remove once Firefox 64 hits the release channel, including second argument - // to sendProductToBackground. - const resend = () => sendProductToBackground(extractedProduct, false); + // TODO(osmose): Remove once Firefox 64 hits the release channel + const resend = () => sendProductToBackground(extractedProduct); setTimeout(resend, 5000); setTimeout(resend, 10000); diff --git a/src/state/prices.js b/src/state/prices.js index 6b88719..e4a548d 100644 --- a/src/state/prices.js +++ b/src/state/prices.js @@ -229,13 +229,9 @@ export function addPriceFromExtracted(data) { // Potentially trigger an alert since there's a new price in town. dispatch(triggerPriceAlert(price)); - // If this isn't the first price for this product, record detect_price_change event - const prices = getPricesForProduct(state, price.productId); - if (prices.length >= 1) { - return true; - } + return price; } - return false; + return null; }; } diff --git a/src/telemetry/extension.js b/src/telemetry/extension.js index b0db585..d753eec 100644 --- a/src/telemetry/extension.js +++ b/src/telemetry/extension.js @@ -206,6 +206,7 @@ async function getActiveTabId() { } export async function getBadgeType() { + // browserAction and background scripts have to use activeTabId as a proxy for the tabId const activeTabId = await getActiveTabId(); const badgeText = await browser.browserAction.getBadgeText( activeTabId ? {tabId: activeTabId} : {}, @@ -223,6 +224,19 @@ export async function getBadgeType() { } } +export async function hasBadgeTextChanged(nextText, tabId = null) { + // If the nextText contains a digit, we know it's a price alert badge, which only affects + // the global badge text. + const returnGlobal = (/\d+/.test(nextText)); + const prevText = await browser.browserAction.getBadgeText( + returnGlobal ? {} : {tabId: tabId || await getActiveTabId()}, + ); + if (prevText !== nextText) { + return true; + } + return false; +} + export async function handleWidgetRemoved(widgetId) { const addonId = (await browser.management.getSelf()).id; // widgetId replaces '@' and '.' in the addonId with _ From 3b0e2b3000260d39fc6d2e83462112094f84ebf0 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Sat, 3 Nov 2018 12:48:34 -0700 Subject: [PATCH 014/140] Revert privacy extra keys and break out 'open_external_page' into two events This patch: * Reverts "Collapse privacy extra keys into a single key" (commit 32fcfc4f924e2d53fb47dd615a090bda15e51e7c) while preserving the Common Extra Keys and Event-Specific Extra Keys subsections and updating the Sample Ping section in the METRICS.md document. * Breaks out 'open_external_page' event (11 extra keys) into two events: 'open_nonproduct_page' (5 extra keys) and 'open_product_page' (10 extra keys). --- docs/METRICS.md | 144 +++++++++++++----- src/background/price_alerts.js | 3 +- .../components/BrowserActionApp.jsx | 4 +- .../components/EmptyOnboarding.jsx | 2 +- src/browser_action/components/ProductCard.jsx | 2 +- src/telemetry/extension.js | 35 +++-- 6 files changed, 133 insertions(+), 57 deletions(-) diff --git a/docs/METRICS.md b/docs/METRICS.md index 224d9f5..7ed0b63 100644 --- a/docs/METRICS.md +++ b/docs/METRICS.md @@ -88,7 +88,7 @@ Each event will exist as part of the `main` ping under `payload.processes.dynami The telemetry category for events is `'extension.price_wise'`. -Below is a sample ping for the `visit_supported_site` and `badge_toolbar_button` events. +Below is a sample ping for when the user visits a supported page and adds the product on that page. ```javascript { @@ -102,18 +102,51 @@ Below is a sample ping for the `visit_supported_site` and `badge_toolbar_button` // ... "events": [ [ - 733502, + 7756, "extension.price_wise", "visit_supported_site", "supported_site", null, { "tracked_prods": "0", - "dnt_tp_cookie": "{\"dnt\":false,\"tp\":\"private_browsing\",\"cookie\":\"allow_visited\"}" + "privacy_dnt": "false", + "privacy_tp": "private_browsing", + "privacy_cookie": "allow_visited" } ], [ - 733530, + 7769, + "extension.price_wise", + "attempt_extraction", + "product_page", + null, + { + "extraction_id": "67caf845-f971-42ce-8a9a-aa3ce919186f", + "is_bg_update": "false", + "tracked_prods": "0", + "privacy_dnt": "false", + "privacy_tp": "private_browsing", + "privacy_cookie": "allow_visited" + } + ], + [ + 7779, + "extension.price_wise", + "complete_extraction", + "product_page", + null, + { + "extraction_id": "67caf845-f971-42ce-8a9a-aa3ce919186f", + "is_bg_update": "false", + "method": "css_selectors", + "tracked_prods": "0", + "privacy_dnt": "false", + "privacy_tp": "private_browsing", + "privacy_cookie": "allow_visited" + } + ], + [ + 7783, "extension.price_wise", "badge_toolbar_button", "toolbar_button", @@ -121,10 +154,41 @@ Below is a sample ping for the `visit_supported_site` and `badge_toolbar_button` { "badge_type": "add", "tracked_prods": "0", - "dnt_tp_cookie": "{\"dnt\":false,\"tp\":\"private_browsing\",\"cookie\":\"allow_visited\"}" + "privacy_dnt": "false", + "privacy_tp": "private_browsing", + "privacy_cookie": "allow_visited" } - ] - ] + ], + [ + 18180, + "extension.price_wise", + "open_popup", + "toolbar_button", + null, + { + "badge_type": "add", + "tracked_prods": "0", + "privacy_dnt": "false", + "privacy_tp": "private_browsing", + "privacy_cookie": "allow_visited" + } + ], + [ + 19565, + "extension.price_wise", + "add_product", + "add_button", + null, + { + "price": "4800", + "product_key": "2b4d8569-3db9-4448-a9d8-af1fc5cacf7a", + "tracked_prods": "1", + "privacy_dnt": "false", + "privacy_tp": "private_browsing", + "privacy_cookie": "allow_visited" + } + ], + ], } // ... } @@ -143,17 +207,16 @@ Below is a sample ping for the `visit_supported_site` and `badge_toolbar_button` Some `extra_keys` are sent with every telemetry event recorded by the extension: - `'tracked_prods'`: The number of products the user is tracking. -- `'dnt_tp_cookie'`: The status of three different privacy settings collapsed into a single, stringified JSON object: - - `'dnt'`: 'true' if the user has [requested not to be tracked by websites, content, or advertising](https://support.mozilla.org/en-US/kb/how-do-i-turn-do-not-track-feature); otherwise 'false'. - - `'tp'`: The user's [tracking protection](https://support.mozilla.org/en-US/kb/tracking-protection) setting: - - `'always'`: Tracking Protection is on - - `'never'`: Tracking Protection is off - - `'private_browsing'`: Tracking Protection is on in private browsing windows only - - `'cookie'`: The user's [cookie setting](https://support.mozilla.org/en-US/kb/disable-third-party-cookies): - - `'allow_all'`: Accept all cookies - - `'reject_all'`: Reject all cookies - - `'reject_third_party'`: Reject all third-party cookies - - `'allow_visited'`: Accept a third-party cookie only if the cookie's top-level domain already has at least one cookie. +- `'privacy_dnt'`: 'true' if the user has [requested not to be tracked by websites, content, or advertising](https://support.mozilla.org/en-US/kb/how-do-i-turn-do-not-track-feature); otherwise 'false'. +- `'privacy_tp'`: The user's [tracking protection](https://support.mozilla.org/en-US/kb/tracking-protection) setting: + - `'always'`: Tracking Protection is on + - `'never'`: Tracking Protection is off + - `'private_browsing'`: Tracking Protection is on in private browsing windows only +- `'privacy_cookie'`: The user's [cookie setting](https://support.mozilla.org/en-US/kb/disable-third-party-cookies): + - `'allow_all'`: Accept all cookies + - `'reject_all'`: Reject all cookies + - `'reject_third_party'`: Reject all third-party cookies + - `'allow_visited'`: Accept a third-party cookie only if the cookie's top-level domain already has at least one cookie. ### Event-specific Extra Keys @@ -166,8 +229,6 @@ Some `extra_keys` are sent with every telemetry event recorded by the extension: - `'help_button'`: Sends the user to a Price Wise support.mozilla.org page. - `'home_depot_link'`: Sends the user to Home Depot. - `'learn_more_link'`: Sends the user to a Price Wise support.mozilla.org page. - - `'product_card'`: Sends the user to the product page for the given Product Card. - - `'system_notification'`: Sends the user to the product page for the Price Alert displayed in the notification. - `'walmart_link'`: Sends the user to Walmart. - `'extraction_id'`: A unique identifier to associate an extraction attempt to an extraction completion event for a given page. - `'is_bg_update'`: 'true' if the extraction is associated with a background price check; otherwise 'false'. @@ -209,28 +270,37 @@ Fired when the user clicks the Price Wise browserAction toolbar button to open t - `'badge_type'` - [Common extra keys](#common-extra-keys) -### `open_external_page` +### `open_nonproduct_page` -Fired when the user clicks on a UI element in the extension that opens a page in a new tab. +Fired when the user clicks on a UI element in the extension that opens a non-product page in a new tab. #### Payload properties - `methods`: String - - `'open_external_page'` + - `'open_nonproduct_page'` - `objects`: String - `'ui_element'` -- `extra_keys`: Object; which keys are included depends on the value of the `'element'` extra key. - - All values: - - [Common extra keys](#common-extra-keys) - - `'element'` - - `'system_notification'` and `'product_card'` only: - - `'price'` - - `'price_alert'` - - `'price_orig'` - - `'product_key'` - - `'system_notification'` only: - - `'price_last_high'` - - `'product_card'` only: - - `'product_index'` +- `extra_keys`: Object + - `'element'` + - [Common extra keys](#common-extra-keys) + +### `open_product_page` + +Fired when the user clicks on a UI element in the extension that opens a product page in a new tab. + +#### Payload properties +- `methods`: String + - `'open_product_page'` +- `objects`: String. The extension UI element that the user clicked to open a product page in a new tab. One of: + - `'product_card'`: Sends the user to the product page for the given Product Card. + - `'system_notification'`: Sends the user to the product page for the Price Alert displayed in the notification. +- `extra_keys`: Object + - `'price'` + - `'price_alert'` + - `'price_orig'` + - `'product_key'` + - [Common extra keys](#common-extra-keys) + - `'product_index'` (for `objects` value of `'product_card'` only) + - `'price_last_high'` (for `objects` value of `'system_notification'` only) ### `add_product` @@ -450,4 +520,4 @@ Note: This is a sample ping. The exact value for the extension ID may differ, th 1. Navigate to `about:telemetry`. 2. Click 'Events' in the sidebar menu. - Note: This menu item is not present until an event has been recorded for the current session. If you don't see it, trigger one of the events as described in this document (e.g. `open_popup`) and refresh the page. -3. On the top right corner of the next page, click 'dynamic' in the dropdown menu. \ No newline at end of file +3. On the top right corner of the next page, click 'dynamic' in the dropdown menu. diff --git a/src/background/price_alerts.js b/src/background/price_alerts.js index b630e25..e5210eb 100644 --- a/src/background/price_alerts.js +++ b/src/background/price_alerts.js @@ -97,8 +97,7 @@ export async function handleNotificationClicked(notificationId) { // Record open_external_page event const latestPrice = getLatestPriceForProduct(state, product.id); const originalPrice = getOldestPriceForProduct(state, product.id); - await recordEvent('open_external_page', 'ui_element', null, { - element: 'system_notification', + await recordEvent('open_product_page', 'system_notification', null, { price: latestPrice.amount.getAmount(), price_alert: alert.active, price_last_high: alert.highPriceAmount, diff --git a/src/browser_action/components/BrowserActionApp.jsx b/src/browser_action/components/BrowserActionApp.jsx index 129eb54..e9c7940 100644 --- a/src/browser_action/components/BrowserActionApp.jsx +++ b/src/browser_action/components/BrowserActionApp.jsx @@ -69,7 +69,7 @@ export default class BrowserActionApp extends React.Component { */ async handleClickHelp() { browser.tabs.create({url: await config.get('supportUrl')}); - await recordEvent('open_external_page', 'ui_element', null, {element: 'help_button'}); + await recordEvent('open_nonproduct_page', 'ui_element', null, {element: 'help_button'}); window.close(); } @@ -78,7 +78,7 @@ export default class BrowserActionApp extends React.Component { */ async handleClickFeedback() { browser.tabs.create({url: await config.get('feedbackUrl')}); - await recordEvent('open_external_page', 'ui_element', null, {element: 'feedback_button'}); + await recordEvent('open_nonproduct_page', 'ui_element', null, {element: 'feedback_button'}); window.close(); } diff --git a/src/browser_action/components/EmptyOnboarding.jsx b/src/browser_action/components/EmptyOnboarding.jsx index 6b76ab3..c2e1544 100644 --- a/src/browser_action/components/EmptyOnboarding.jsx +++ b/src/browser_action/components/EmptyOnboarding.jsx @@ -50,7 +50,7 @@ export default class EmptyOnboarding extends React.Component { if (event.target.href) { event.preventDefault(); browser.tabs.create({url: event.target.href}); - await recordEvent('open_external_page', 'ui_element', null, {element: `${event.target.dataset.telemetryId}_link`}); + await recordEvent('open_nonproduct_page', 'ui_element', null, {element: `${event.target.dataset.telemetryId}_link`}); window.close(); } } diff --git a/src/browser_action/components/ProductCard.jsx b/src/browser_action/components/ProductCard.jsx index b7a1d9c..c1774b2 100644 --- a/src/browser_action/components/ProductCard.jsx +++ b/src/browser_action/components/ProductCard.jsx @@ -63,7 +63,7 @@ export default class ProductCard extends React.Component { */ async handleClick() { browser.tabs.create({url: this.props.product.url}); - await this.recordClickEvent('open_external_page', 'ui_element', {element: 'product_card'}); + await this.recordClickEvent('open_product_page', 'product_card'); window.close(); } diff --git a/src/telemetry/extension.js b/src/telemetry/extension.js index d753eec..799a29e 100644 --- a/src/telemetry/extension.js +++ b/src/telemetry/extension.js @@ -15,7 +15,9 @@ const CATEGORY = 'extension.price_wise'; const DEFAULT_EXTRAS = [ 'tracked_prods', - 'dnt_tp_cookie', + 'privacy_dnt', + 'privacy_tp', + 'privacy_cookie', ]; const EVENTS = { @@ -38,22 +40,29 @@ const EVENTS = { ...DEFAULT_EXTRAS, ], }, - // User clicks on a UI element in the extension opening a page in a new tab - open_external_page: { - methods: ['open_external_page'], + // User clicks on a UI element in the extension opening a non-product page in a new tab + open_nonproduct_page: { + methods: ['open_nonproduct_page'], objects: ['ui_element'], extra_keys: [ - ...DEFAULT_EXTRAS, 'element', - // For 'element' values 'product_card' and 'system_notification' only + ...DEFAULT_EXTRAS, + ], + }, + // User clicks on a UI element in the extension opening a product page in a new tab + open_product_page: { + methods: ['open_product_page'], + objects: ['product_card', 'system_notification'], + extra_keys: [ 'price', 'price_alert', 'price_orig', 'product_key', - // For 'element' value of 'system_notification' only - 'price_last_high', - // For 'element' value 'product_card' only + ...DEFAULT_EXTRAS, + // For 'objects' value 'product_card' only 'product_index', + // For 'objects' value of 'system_notification' only + 'price_last_high', ], }, // User adds a product to the product listing @@ -173,11 +182,9 @@ export async function recordEvent(method, object, value, extraBase = {}) { const extra = { ...extraBase, tracked_prods: getAllProducts(store.getState()).length, - dnt_tp_cookie: JSON.stringify({ - dnt: (navigator.doNotTrack === '1'), - tp: (await browser.privacy.websites.trackingProtectionMode.get({})).value, - cookie: (await browser.privacy.websites.cookieConfig.get({})).value.behavior, - }), + privacy_dnt: navigator.doNotTrack === '1', + privacy_tp: (await browser.privacy.websites.trackingProtectionMode.get({})).value, + privacy_cookie: (await browser.privacy.websites.cookieConfig.get({})).value.behavior, }; // Convert all extra key values to strings as required by event telemetry From 44391b79f783fd9b9dea86ce00ac424116750737 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Mon, 5 Nov 2018 21:32:03 -0800 Subject: [PATCH 015/140] Incorporate more of Osmose's feedback --- src/background/extraction.js | 4 ++-- src/background/price_alerts.js | 4 ++-- src/extraction/index.js | 27 ++++++++++++--------------- src/telemetry/extension.js | 21 +++++++-------------- 4 files changed, 23 insertions(+), 33 deletions(-) diff --git a/src/background/extraction.js b/src/background/extraction.js index 3e8999a..cb7d4c4 100644 --- a/src/background/extraction.js +++ b/src/background/extraction.js @@ -10,7 +10,7 @@ import config from 'commerce/config'; import {updateProductWithExtracted} from 'commerce/background/price_updates'; import {isValidExtractedProduct} from 'commerce/state/products'; -import {recordEvent, hasBadgeTextChanged} from 'commerce/telemetry/extension'; +import {recordEvent, getToolbarBadgeText} from 'commerce/telemetry/extension'; /** * Triggers background tasks when a product is extracted from a webpage. Along @@ -51,7 +51,7 @@ export async function handleExtractedProductData({extractedProduct}, sender) { color: await config.get('badgeDetectBackground'), tabId, }); - if (await hasBadgeTextChanged('✚', sender.tab.id)) { + if (await getToolbarBadgeText(tabId) !== '✚') { await recordEvent('badge_toolbar_button', 'toolbar_button', null, { badge_type: 'add', }); diff --git a/src/background/price_alerts.js b/src/background/price_alerts.js index e5210eb..298b3c1 100644 --- a/src/background/price_alerts.js +++ b/src/background/price_alerts.js @@ -22,7 +22,7 @@ import { } from 'commerce/state/prices'; import {getProduct} from 'commerce/state/products'; import {getVendor} from 'commerce/state/vendors'; -import {recordEvent, hasBadgeTextChanged} from 'commerce/telemetry/extension'; +import {recordEvent, getToolbarBadgeText} from 'commerce/telemetry/extension'; /** * Update the extension UI based on the current state of active price alerts. @@ -34,7 +34,7 @@ export async function handlePriceAlerts() { // Show the browser action badge if there are any active alerts. if (activeAlerts.length > 0) { - if (await hasBadgeTextChanged(`${activeAlerts.length}`)) { + if (await getToolbarBadgeText() !== `${activeAlerts.length}`) { await recordEvent('badge_toolbar_button', 'toolbar_button', null, { badge_type: 'price_alert', }); diff --git a/src/extraction/index.js b/src/extraction/index.js index 87694d3..e365cbb 100644 --- a/src/extraction/index.js +++ b/src/extraction/index.js @@ -28,17 +28,14 @@ const EXTRACTION_METHODS = { open_graph: extractProductWithOpenGraph, }; -const IS_BACKGROUND_UPDATE = (function isBackgroundUpdate() { - let result = false; - try { - result = window.top.location.href.startsWith( - browser.runtime.getURL('/'), // URL is unique per-install / hard to forge - ); - } catch (err) { - // Non-background updates may throw a cross-origin error - } - return result; -}()); +let isBackgroundUpdate = false; +try { + isBackgroundUpdate = window.top.location.href.startsWith( + browser.runtime.getURL('/'), // URL is unique per-install / hard to forge + ); +} catch (err) { + // Non-background updates may throw a cross-origin error +} /** * Helper class to record extraction-related telemetry events. @@ -47,7 +44,7 @@ class ExtractionAttempt { constructor() { this.baseExtra = { extraction_id: uuidv4(), - is_bg_update: IS_BACKGROUND_UPDATE, + is_bg_update: isBackgroundUpdate, }; } @@ -120,7 +117,7 @@ async function attemptExtraction() { // started by the background script for a price check. const isInIframe = window !== window.top; - if (isInIframe && !IS_BACKGROUND_UPDATE) { + if (isInIframe && !isBackgroundUpdate) { return; } @@ -135,12 +132,12 @@ async function attemptExtraction() { const url = new URL(document.location.href); const allowList = await config.get('extractionAllowlist'); const allowAll = allowList.length === 1 && allowList[0] === '*'; - if (!allowAll && !IS_BACKGROUND_UPDATE && !allowList.includes(url.host)) { + if (!allowAll && !isBackgroundUpdate && !allowList.includes(url.host)) { return; } // Record visit_supported_site event - if (!IS_BACKGROUND_UPDATE) { + if (!isBackgroundUpdate) { await recordEvent('visit_supported_site', 'supported_site'); } diff --git a/src/telemetry/extension.js b/src/telemetry/extension.js index 799a29e..1ed2707 100644 --- a/src/telemetry/extension.js +++ b/src/telemetry/extension.js @@ -214,10 +214,7 @@ async function getActiveTabId() { export async function getBadgeType() { // browserAction and background scripts have to use activeTabId as a proxy for the tabId - const activeTabId = await getActiveTabId(); - const badgeText = await browser.browserAction.getBadgeText( - activeTabId ? {tabId: activeTabId} : {}, - ); + const badgeText = await getToolbarBadgeText(await getActiveTabId()); switch (true) { case (badgeText === ''): return 'none'; @@ -231,17 +228,13 @@ export async function getBadgeType() { } } -export async function hasBadgeTextChanged(nextText, tabId = null) { - // If the nextText contains a digit, we know it's a price alert badge, which only affects - // the global badge text. - const returnGlobal = (/\d+/.test(nextText)); - const prevText = await browser.browserAction.getBadgeText( - returnGlobal ? {} : {tabId: tabId || await getActiveTabId()}, +export async function getToolbarBadgeText(tabId = null) { + // The 'add' badge modifies badge text for a specific tab and will have a tabId. + // The 'price_alert' badge modifies the global badge text and will not have a tabId. + const returnGlobal = !tabId; + return browser.browserAction.getBadgeText( + returnGlobal ? {} : {tabId}, ); - if (prevText !== nextText) { - return true; - } - return false; } export async function handleWidgetRemoved(widgetId) { From 96b7a244199cca65dfc98d63bdc700a3533c02d8 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Tue, 6 Nov 2018 13:08:51 -0800 Subject: [PATCH 016/140] Remove unnecessary 'returnGlobal' variable --- src/telemetry/extension.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/telemetry/extension.js b/src/telemetry/extension.js index 1ed2707..4c0d28f 100644 --- a/src/telemetry/extension.js +++ b/src/telemetry/extension.js @@ -231,9 +231,8 @@ export async function getBadgeType() { export async function getToolbarBadgeText(tabId = null) { // The 'add' badge modifies badge text for a specific tab and will have a tabId. // The 'price_alert' badge modifies the global badge text and will not have a tabId. - const returnGlobal = !tabId; return browser.browserAction.getBadgeText( - returnGlobal ? {} : {tabId}, + tabId ? {tabId} : {}, ); } From 578eb0c6bcaba24d1eb9bbf722b13a87fb214e9b Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Fri, 2 Nov 2018 20:29:00 -0700 Subject: [PATCH 017/140] Fix #237, fix #242: Re-add toolbar icon reset workaround. --- src/background/index.js | 12 ++++++++++++ src/extraction/index.js | 16 ++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/background/index.js b/src/background/index.js index c682ddf..6beb510 100644 --- a/src/background/index.js +++ b/src/background/index.js @@ -65,6 +65,18 @@ import {registerEvents, handleWidgetRemoved} from 'commerce/telemetry/extension' ['blocking', 'responseHeaders'], ); + // Workaround for bug 1493470: Resend product info to the background + // script in case subframe loads clear the toolbar icon. + // TODO(osmose): Remove once Firefox 64 hits the release channel. + browser.webRequest.onCompleted.addListener( + (details) => { + if (details.tabId) { + browser.tabs.sendMessage(details.tabId, {type: 'resend-product'}); + } + }, + {urls: ['https://*/*', 'http://*/*'], types: ['sub_frame']}, + ); + // Set up listener to trigger re-extraction when a page changes the URL via // the history API. browser.webNavigation.onHistoryStateUpdated.addListener( diff --git a/src/extraction/index.js b/src/extraction/index.js index e365cbb..0f72486 100644 --- a/src/extraction/index.js +++ b/src/extraction/index.js @@ -89,6 +89,10 @@ function extractProduct() { } async function sendProductToBackground(extractedProduct) { + if (!extractedProduct) { + return null; + } + return browser.runtime.sendMessage({ type: 'extracted-product', extractedProduct: { @@ -147,18 +151,14 @@ async function attemptExtraction() { extractedProduct = await attemptExtraction(); }); - // Messy workaround for bug 1493470: Resend product info to the background - // script twice in case subframe loads clear the toolbar icon. - // TODO(osmose): Remove once Firefox 64 hits the release channel - const resend = () => sendProductToBackground(extractedProduct); - setTimeout(resend, 5000); - setTimeout(resend, 10000); - browser.runtime.onMessage.addListener(async (message) => { - // Re-extract the product if requested if (message.type === 'reextract-product') { + // Re-extract the product if requested extractedProduct = await attemptExtraction(); await sendProductToBackground(extractedProduct); + } else if (message.type === 'resend-product') { + // Re-send the already-extracted product if requested + await sendProductToBackground(extractedProduct); } }); }()); From 24fdcae3c800c1b9ca7a217478192762f83b928b Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Tue, 6 Nov 2018 16:55:12 -0800 Subject: [PATCH 018/140] Fix #248: Allow data: URIs for product images --- src/state/products.js | 62 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/src/state/products.js b/src/state/products.js index 3474ceb..db507eb 100644 --- a/src/state/products.js +++ b/src/state/products.js @@ -39,6 +39,57 @@ export const extractedProductShape = pt.shape({ date: pt.string.isRequired, }); +const DATA_URI_PATHS = [ + 'image/gif;', + 'image/png;', + 'image/jpeg;', + 'image/svg+xml;', + 'image/webp;', +]; + +const RESOURCE_VALIDATION_DEFAULTS = { + isValidResource(value) { + try { + const url = new URL(value); + if (!['https:', 'http:'].includes(url.protocol)) { + return false; + } + } catch (err) { + return false; + } + return true; + }, +}; + +const RESOURCE_VALIDATION = { + url: { + ...RESOURCE_VALIDATION_DEFAULTS, + }, + image: { + ...RESOURCE_VALIDATION_DEFAULTS, + isValidResource(value) { + try { + const url = new URL(value); + const {protocol} = url; + if (!['https:', 'http:', 'data:'].includes(protocol)) { + return false; + } + if (protocol === 'data:') { + for (const path of DATA_URI_PATHS) { + if (url.pathname.startsWith(path)) { + return true; + } + } + return false; + } + } catch (err) { + return false; + } + return true; + }, + }, +}; + /** * Validate the contents of the given extracted product. This is used in lieu * of proptypes since proptype checks do not work in a production build. @@ -58,15 +109,8 @@ export function isValidExtractedProduct(extractedProduct) { return false; } - for (const key of ['url', 'image']) { - try { - const url = new URL(extractedProduct[key]); - if (!['https:', 'http:'].includes(url.protocol)) { - return false; - } - } catch (err) { - return false; - } + for (const [key, methods] of Object.entries(RESOURCE_VALIDATION)) { + return methods.isValidResource(extractedProduct[key]); } return true; From 022c60ca33d5613f83fdc4334deacc5b4010e660 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Wed, 7 Nov 2018 09:45:00 -0800 Subject: [PATCH 019/140] Incorporate Osmose's feedback Replaced 'isValidResource' indirection with easier-to-follow validation inline. 'url' and 'imageUrl' are declared outside of the 'try...catch' statement, so that the only error we catch in the catch block is from an error in creating the URL instance. Renamed 'DATA_URI_PATHS' to 'ALLOWED_IMAGE_MIMETYPES' to be more descriptive of the value and add some helpful comments. --- src/state/products.js | 69 +++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 46 deletions(-) diff --git a/src/state/products.js b/src/state/products.js index db507eb..7cb2e27 100644 --- a/src/state/products.js +++ b/src/state/products.js @@ -39,7 +39,7 @@ export const extractedProductShape = pt.shape({ date: pt.string.isRequired, }); -const DATA_URI_PATHS = [ +const ALLOWED_IMAGE_MIMETYPES = [ 'image/gif;', 'image/png;', 'image/jpeg;', @@ -47,49 +47,6 @@ const DATA_URI_PATHS = [ 'image/webp;', ]; -const RESOURCE_VALIDATION_DEFAULTS = { - isValidResource(value) { - try { - const url = new URL(value); - if (!['https:', 'http:'].includes(url.protocol)) { - return false; - } - } catch (err) { - return false; - } - return true; - }, -}; - -const RESOURCE_VALIDATION = { - url: { - ...RESOURCE_VALIDATION_DEFAULTS, - }, - image: { - ...RESOURCE_VALIDATION_DEFAULTS, - isValidResource(value) { - try { - const url = new URL(value); - const {protocol} = url; - if (!['https:', 'http:', 'data:'].includes(protocol)) { - return false; - } - if (protocol === 'data:') { - for (const path of DATA_URI_PATHS) { - if (url.pathname.startsWith(path)) { - return true; - } - } - return false; - } - } catch (err) { - return false; - } - return true; - }, - }, -}; - /** * Validate the contents of the given extracted product. This is used in lieu * of proptypes since proptype checks do not work in a production build. @@ -109,8 +66,28 @@ export function isValidExtractedProduct(extractedProduct) { return false; } - for (const [key, methods] of Object.entries(RESOURCE_VALIDATION)) { - return methods.isValidResource(extractedProduct[key]); + let url; + let imageUrl; + + try { + url = new URL(extractedProduct.url); + imageUrl = new URL(extractedProduct.image); + } catch (error) { + return false; + } + + if (!['https:', 'http:'].includes(url.protocol)) { + return false; + } + + // Some sites like Amazon initially load a data URI for the image + if (!['https:', 'http:', 'data:'].includes(imageUrl.protocol)) { + return false; + } + + // Ensure the data URI is an image by validating its mimetype + if (imageUrl.protocol === 'data:' && !(ALLOWED_IMAGE_MIMETYPES.find(path => imageUrl.pathname.startsWith(path)))) { + return false; } return true; From a847ec17f3c27204024d5f931da045b66d6ee7b2 Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Wed, 7 Nov 2018 11:11:37 -0800 Subject: [PATCH 020/140] 10.0.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 69f3358..f808820 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "9.0.0", + "version": "10.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 5acb9f9..5fec7ba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "9.0.0", + "version": "10.0.0", "description": "Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy.", "private": true, "author": "Mozilla", From 4b598dbfb2de561cec1ecbd43ff85d502b2e574a Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Thu, 8 Nov 2018 14:08:09 -0800 Subject: [PATCH 021/140] Fix #258: Record extension telemetry in the Release channel --- src/telemetry/extension.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/telemetry/extension.js b/src/telemetry/extension.js index 4c0d28f..a964143 100644 --- a/src/telemetry/extension.js +++ b/src/telemetry/extension.js @@ -29,6 +29,7 @@ const EVENTS = { extra_keys: [ ...DEFAULT_EXTRAS, ], + record_on_release: true, }, // User clicks toolbar button to open the popup @@ -39,6 +40,7 @@ const EVENTS = { 'badge_type', ...DEFAULT_EXTRAS, ], + record_on_release: true, }, // User clicks on a UI element in the extension opening a non-product page in a new tab open_nonproduct_page: { @@ -48,6 +50,7 @@ const EVENTS = { 'element', ...DEFAULT_EXTRAS, ], + record_on_release: true, }, // User clicks on a UI element in the extension opening a product page in a new tab open_product_page: { @@ -64,6 +67,7 @@ const EVENTS = { // For 'objects' value of 'system_notification' only 'price_last_high', ], + record_on_release: true, }, // User adds a product to the product listing add_product: { @@ -74,6 +78,7 @@ const EVENTS = { 'product_key', ...DEFAULT_EXTRAS, ], + record_on_release: true, }, // User deletes a product from the product listing delete_product: { @@ -87,6 +92,7 @@ const EVENTS = { 'product_key', ...DEFAULT_EXTRAS, ], + record_on_release: true, }, // User undeletes a product from the product listing undo_delete_product: { @@ -100,6 +106,7 @@ const EVENTS = { 'product_key', ...DEFAULT_EXTRAS, ], + record_on_release: true, }, // User hides the toolbar button for the extension hide_toolbar_button: { @@ -109,6 +116,7 @@ const EVENTS = { 'badge_type', ...DEFAULT_EXTRAS, ], + record_on_release: true, }, // Non-User Events @@ -123,6 +131,7 @@ const EVENTS = { 'product_key', ...DEFAULT_EXTRAS, ], + record_on_release: true, }, // Toolbar button is badged either due to a price alert or an extracted product @@ -133,6 +142,7 @@ const EVENTS = { 'badge_type', ...DEFAULT_EXTRAS, ], + record_on_release: true, }, // System notification is sent notifying user of a price alert send_notification: { @@ -145,6 +155,7 @@ const EVENTS = { 'product_key', ...DEFAULT_EXTRAS, ], + record_on_release: true, }, // Product extraction is attempted on the content page attempt_extraction: { @@ -155,6 +166,7 @@ const EVENTS = { 'is_bg_update', ...DEFAULT_EXTRAS, ], + record_on_release: true, }, // Product extraction is completed on the content page complete_extraction: { @@ -166,6 +178,7 @@ const EVENTS = { 'method', ...DEFAULT_EXTRAS, ], + record_on_release: true, }, }; From b05dc0d2cf27e95c76b1c37155cd4ac990727f49 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Thu, 8 Nov 2018 14:12:31 -0800 Subject: [PATCH 022/140] Fix #183: Enable telemetry for default cookie setting in Firefox 64+ --- src/privacy.js | 2 +- web-ext-config.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/privacy.js b/src/privacy.js index 1eb0392..e0f2adb 100644 --- a/src/privacy.js +++ b/src/privacy.js @@ -67,7 +67,7 @@ function doNotTrackEnabled() { async function cookiesBlocked() { if (browser.privacy.websites.cookieConfig) { const {behavior} = (await browser.privacy.websites.cookieConfig.get({})).value; - if (!['allow_all', 'allow_visited'].includes(behavior)) { + if (!['allow_all', 'allow_visited', 'reject_trackers'].includes(behavior)) { return true; } diff --git a/web-ext-config.js b/web-ext-config.js index 1495888..122ce7f 100644 --- a/web-ext-config.js +++ b/web-ext-config.js @@ -4,7 +4,6 @@ module.exports = { 'extensions.shopping-testpilot@mozilla.org.priceCheckInterval=30000', 'extensions.shopping-testpilot@mozilla.org.priceCheckTimeoutInterval=30000', 'extensions.shopping-testpilot@mozilla.org.iframeTimeout=10000', - 'network.cookie.cookieBehavior=3', // See Issue #183 ], startUrl: [ 'http://www.mkelly.me/fake-product-page/', From 15cc91a212614d9b4f18c29b6d01ea0ca73aaf8c Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Thu, 8 Nov 2018 14:51:21 -0800 Subject: [PATCH 023/140] 11.0.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index f808820..72c6ccd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "10.0.0", + "version": "11.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 5fec7ba..2292638 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "10.0.0", + "version": "11.0.0", "description": "Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy.", "private": true, "author": "Mozilla", From ce3e06e1e54fb3d6e5f87570280892d9b8a93c44 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Fri, 9 Nov 2018 13:42:35 -0800 Subject: [PATCH 024/140] Update METRICS.md with 'event' ping Update METRICS.md to accurately reflect the current state of event telemetry in Firefox and in the extension: * Firefox 62 added a new 'event' ping, so events are no longer appended to the 'main' ping. * 'addonsManager' events are only available in Firefox 64+. * Extension event telemetry is disabled with certain cookie settings. --- docs/METRICS.md | 272 +++++++++++++++++++++++++----------------------- 1 file changed, 142 insertions(+), 130 deletions(-) diff --git a/docs/METRICS.md b/docs/METRICS.md index 7ed0b63..2261809 100644 --- a/docs/METRICS.md +++ b/docs/METRICS.md @@ -84,117 +84,111 @@ While some of these questions may be partially answerable by this extension, ans We will be sending pings using [Event Telemetry](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/events.html) via the [WebExtensions Telemetry API](https://bugzilla.mozilla.org/show_bug.cgi?id=1280234). -Each event will exist as part of the `main` ping under `payload.processes.dynamic.events` as an array in the `events` array (see Appendix B for how to view the events in `about:telemetry`). The data types of individual fields for each event follow the Event Telemetry [serialization format](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/events.html#serialization-format). +Each event will exist as part of the [`event` ping](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/data/event-ping.html) under `payload.events.dynamic` as an array (see Appendix B for how to view extension events in `about:telemetry`). The data types of individual fields for each event follow the Event Telemetry [serialization format](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/events.html#serialization-format). The telemetry category for events is `'extension.price_wise'`. -Below is a sample ping for when the user visits a supported page and adds the product on that page. +Below is a sample `event` ping for when the user visits a supported page and adds the product on that page. ```javascript { - "type": "main", - // ... + "type": "event", + //... "payload": { - // ... - "processes": { - // ... - "dynamic": { - // ... - "events": [ - [ - 7756, - "extension.price_wise", - "visit_supported_site", - "supported_site", - null, - { - "tracked_prods": "0", - "privacy_dnt": "false", - "privacy_tp": "private_browsing", - "privacy_cookie": "allow_visited" - } - ], - [ - 7769, - "extension.price_wise", - "attempt_extraction", - "product_page", - null, - { - "extraction_id": "67caf845-f971-42ce-8a9a-aa3ce919186f", - "is_bg_update": "false", - "tracked_prods": "0", - "privacy_dnt": "false", - "privacy_tp": "private_browsing", - "privacy_cookie": "allow_visited" - } - ], - [ - 7779, - "extension.price_wise", - "complete_extraction", - "product_page", - null, - { - "extraction_id": "67caf845-f971-42ce-8a9a-aa3ce919186f", - "is_bg_update": "false", - "method": "css_selectors", - "tracked_prods": "0", - "privacy_dnt": "false", - "privacy_tp": "private_browsing", - "privacy_cookie": "allow_visited" - } - ], - [ - 7783, - "extension.price_wise", - "badge_toolbar_button", - "toolbar_button", - null, - { - "badge_type": "add", - "tracked_prods": "0", - "privacy_dnt": "false", - "privacy_tp": "private_browsing", - "privacy_cookie": "allow_visited" - } - ], - [ - 18180, - "extension.price_wise", - "open_popup", - "toolbar_button", - null, - { - "badge_type": "add", - "tracked_prods": "0", - "privacy_dnt": "false", - "privacy_tp": "private_browsing", - "privacy_cookie": "allow_visited" - } - ], - [ - 19565, - "extension.price_wise", - "add_product", - "add_button", - null, - { - "price": "4800", - "product_key": "2b4d8569-3db9-4448-a9d8-af1fc5cacf7a", - "tracked_prods": "1", - "privacy_dnt": "false", - "privacy_tp": "private_browsing", - "privacy_cookie": "allow_visited" - } - ], + //... + "events": { + "dynamic": [ + [ + 154572, + "extension.price_wise", + "visit_supported_site", + "supported_site", + null, + { + "tracked_prods": "0", + "privacy_dnt": "false", + "privacy_tp": "private_browsing", + "privacy_cookie": "allow_all" + } ], - } - // ... + [ + 154592, + "extension.price_wise", + "attempt_extraction", + "product_page", + null, + { + "extraction_id": "d7031676-74aa-41b7-a730-c26fc9617dd5", + "is_bg_update": "false", + "tracked_prods": "0", + "privacy_dnt": "false", + "privacy_tp": "private_browsing", + "privacy_cookie": "allow_all" + } + ], + [ + 154597, + "extension.price_wise", + "complete_extraction", + "product_page", + null, + { + "extraction_id": "d7031676-74aa-41b7-a730-c26fc9617dd5", + "is_bg_update": "false", + "method": "css_selectors", + "tracked_prods": "0", + "privacy_dnt": "false", + "privacy_tp": "private_browsing", + "privacy_cookie": "allow_all" + } + ], + [ + 154601, + "extension.price_wise", + "badge_toolbar_button", + "toolbar_button", + null, + { + "badge_type": "add", + "tracked_prods": "0", + "privacy_dnt": "false", + "privacy_tp": "private_browsing", + "privacy_cookie": "allow_all" + } + ], + [ + 156806, + "extension.price_wise", + "open_popup", + "toolbar_button", + null, + { + "badge_type": "add", + "tracked_prods": "0", + "privacy_dnt": "false", + "privacy_tp": "private_browsing", + "privacy_cookie": "allow_all" + } + ], + [ + 158056, + "extension.price_wise", + "add_product", + "add_button", + null, + { + "price": "1100", + "product_key": "791893d7-1303-4e11-9913-c2ce762aa691", + "tracked_prods": "1", + "privacy_dnt": "false", + "privacy_tp": "private_browsing", + "privacy_cookie": "allow_all" + } + ] + ] } - // ... - } - // ... + }, + //... } ``` @@ -467,8 +461,9 @@ No telemetry will be sent from the extension in the following additional cases: - [Tracking Protection](https://support.mozilla.org/en-US/kb/tracking-protection) is enabled - Preference: `privacy.trackingprotection.enabled` - The user is in a [Private Browsing](https://support.mozilla.org/en-US/kb/private-browsing-use-firefox-without-history?redirectlocale=en-US&redirectslug=Private+Browsing) window - - Preference: `browser.privatebrowsing.autostart` - [`windows.Window`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows/Window) property: `window.incognito` +- The user has elected to [block certain kinds of cookies](https://support.mozilla.org/en-US/kb/enable-and-disable-cookies-website-preferences) and site data: all third party cookies or all cookies. + - Preference: `network.cookie.cookieBehavior` ## Appendices @@ -477,47 +472,64 @@ No telemetry will be sent from the extension in the following additional cases: Fired when the user uninstalls the extension. -This event, along with all other add-on lifecycle events, is recorded by the Addons Manager's event telemetry in Firefox. It will exist as part of the `main` ping under `payload.processes.parent.events` as an array in the `events` array. This event will be fired under the `addonsManager` telemetry category. +This event, along with all other add-on lifecycle events, is recorded by the Addons Manager's event telemetry in Firefox. It will exist as part of the `event` ping under `payload.events.parent` as an array. -#### Sample Ping +This event will be fired under the `addonsManager` telemetry category. -Note: This is a sample ping. The exact value for the extension ID may differ, though the other values are correct. +Notes: +- Other lifecycle events such as `install` may have a different event structure than `uninstall`. Since `addonsManager` events are registered statically, you can view how each event is structured in [Events.yaml](https://searchfox.org/mozilla-central/source/toolkit/components/telemetry/Events.yaml) in the Firefox source code. +- The `addonsManager` events are only available in Firefox version 64 and later versions. + +#### Sample Ping ```javascript { - "type": "main", - // ... + "type": "event", + //... "payload": { - // ... - "processes": { - // ... - "parent": { - // ... - "events": [ - [ - 9792, - "addonsManager", - "uninstall", - "extension", - "shopping-testpilot@mozilla.org", // the extension ID - { - "source": "testpilot" - // ... - } - ] + //... + "events": { + "parent": [ + [ + 9792, + "addonsManager", + "uninstall", + "extension", + "shopping-testpilot@mozilla.org", + { + "source": "testpilot" + // ... + } ] - } - // ... + ] } - // ... - } - // ... + }, + //... } ``` + ### Appendix B: How to view Price Wise events in `about:telemetry` +Note: Event Telemetry for this extension may be disabled for certain situations, see [Opt Out](#opt-out). + +#### Current Session + +To view event telemetry for the current session: + 1. Navigate to `about:telemetry`. 2. Click 'Events' in the sidebar menu. - Note: This menu item is not present until an event has been recorded for the current session. If you don't see it, trigger one of the events as described in this document (e.g. `open_popup`) and refresh the page. 3. On the top right corner of the next page, click 'dynamic' in the dropdown menu. +4. You should see a table displayed with all the recorded dynamic events for the session. + +#### Previous Session + +To view event telemetry from a previous session: + +1. Click the dropdown menu down arrow in the top left corner of `about:telemetry` +2. Select 'Archived ping data' +3. Select the `event` ping type +4. Choose an archived `event` ping by date and time +5. In the sidebar menu, select 'Raw Payload' +6. You should see the `payload` JSON object displayed with events listed in the `events` array From e52fd28385ff003bb40c64facd7f7b6a221a1ddd Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Fri, 9 Nov 2018 15:55:54 -0800 Subject: [PATCH 025/140] Fix #223: Update README --- README.md | 122 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 94 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 8154cf3..4eb87bc 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,17 @@ Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy. + +## User Experience + +See [UX specifications](https://mozilla.invisionapp.com/share/UFNSHAIMT4V#/screens/317130676_Artboard_1). + + +## Telemetry + +See [METRICS.md](./docs/METRICS.md). + + ## Developer Setup Prerequisites: @@ -30,7 +41,57 @@ Prerequisites: npm start ``` -## Running Tests +Note: This will install the extension as an [unsigned](https://wiki.mozilla.org/Add-ons/Extension_Signing) [WebExtension Experiment](https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/basics.html#webextensions-experiments). +* Unsigned WebExtension Experiments can only be run in Nightly and DevEdition with boolean `about:config` preferences `xpinstall.signatures.required` set to `false` and `extensions.legacy.enabled` set to `true`. +* To test an unsigned WebExtension Experiment in Firefox Beta or Release, an [unbranded build](https://wiki.mozilla.org/Add-ons/Extension_Signing#Unbranded_Builds) must be used. + + +## Scripts + +| Command | Description | +| --- | --- | +| `npm start` | Launch Firefox with the extension temporarily installed | +| `npm run lint` | Run linting checks | +| `npm run build` | Compile source files with Webpack using a development configuration | +| `npm run build:prod` | Compile source files with Webpack using a production configuration | +| `npm run watch` | Watch for changes and rebuild with Webpack using a development configuration| +| `npm run watch:prod` | Watch for changes and rebuild with Webpack using a production configuration| +| `npm run package` | Package the extension into an XPI file | +| `pipenv run test` | Run test suite (See "Running Tests" for setup) | + + +## Code Organization + +- `src/background` contains the background scripts that trigger UI elements (such as the browserAction toolbar button) and periodically check for price updates. +- `src/browser_action` contains the toolbar popup for managing the list of currently-tracked products and tracking new products. +- `src/config` contains the scripts used to fetch config values specified in [config.js](src/config.js). +- `src/experiment_apis` contains the [experimental APIs](https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/basics.html#webextensions-experiments) used to read [preference values](#preferences) and listen for chrome-privileged Firefox events. +- `src/extraction` contains the content scripts that extract product information from product web pages. +- `src/img` contains all the non-favicon images used by the extension. +- `src/state` contains the Redux-based code for managing global extension state. +- `src/styles` contains Firefox-specific CSS property values stored as variables. +- `src/telemetry` contains the scripts used to register and record extension [telemetry events](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/events.html) in different contexts. +- `src/tests` contains the automated test suite. +- `config.js` contains the static configuration settings for the extension, including default values if [override preferences](#preferences) are not set. +- `manifest.json` contains basic metadata about the extension. +- `privacy.js` handles checking privacy settings to gate functionality across the extension. +- `utils.js` contains general utility functions that can be used across the extension. + + +## Data Storage + +Global state for the add-on is managed via [Redux][]. Any time the data is changed, it is persisted to the [add-on local storage][localstorage]. + +Reducers, action creators, etc. are organized into [ducks][] inside the `src/state` directory. + +[Redux]: https://redux.js.org/ +[localstorage]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/local +[ducks]: https://github.com/erikras/ducks-modular-redux + + +## Testing + +### Running Tests Automated tests are run in a Firefox browser instance using [Marionette][]. We use the Python client for Marionette since there is no up-to-date JavaScript client. @@ -58,16 +119,38 @@ After this, you can run `pipenv run test` to run the automated test suite. [Marionette]: https://firefox-source-docs.mozilla.org/testing/marionette/marionette/index.html [Pipenv]: https://docs.pipenv.org/ -## Scripts +### Preferences + +The following preferences can be set to customize the extension's behavior for testing purposes. Some convenient testing values can be found in [web-ext-config.js](web-ext-config.js), and will be used by default with `npm start`. + +
+
extensions.shopping-testpilot@mozilla.org.extractionAllowlist
+
Preference type: string. List of domains ({Array.string} or *) that extraction is performed on. Can be set to * to enable extraction on all sites (default: extractionAllowlist value specified in [config.js](src/config.js).
+ +
extensions.shopping-testpilot@mozilla.org.priceCheckInterval
+
Preference type: integer. Time to wait between price checks for a product in milliseconds (default: 21600000 or 6 hours).
+ +
extensions.shopping-testpilot@mozilla.org.priceCheckTimeoutInterval
+
Preference type: integer. Time to wait between checking if we should fetch new prices in milliseconds (default: 900000 or 15 minutes).
+ +
extensions.shopping-testpilot@mozilla.org.iframeTimeout
+
Preference type: integer. Delay before removing iframes created during price checks in milliseconds (default: 60000or 1 minute).
+ +
extensions.shopping-testpilot@mozilla.org.alertPercentThreshold
+
Preference type: integer. The percentage drop in price on which to trigger a price alert compared to the last high price (See `price_last_high` in [METRICS.md](./docs/METRICS.md)) default: 5 or 5%).
+ +
extensions.shopping-testpilot@mozilla.org.alertAbsoluteThreshold
+
Preference type: integer. The absolute drop in price on which to trigger a price alert compared to the last high price (see `price_last_high` in [METRICS.md](./docs/METRICS.md)) in cents (default: 1000 or $10).
+
+ +### Test Page + +The extension can be tested with this [Fake Product Page](http://www.mkelly.me/fake-product-page/), which randomly generates a price each time it loads. + +Query strings may be used to: +* Set the max price: e.g. http://www.mkelly.me/fake-product-page/?max=10000 +* Fix the price to a particular value: e.g. http://www.mkelly.me/fake-product-page/?dollars=10000 -| Command | Description | -| --- | --- | -| `npm start` | Launch Firefox with the extension temporarily installed | -| `npm run lint` | Run linting checks | -| `npm run build` | Compile source files with Webpack | -| `npm run watch` | Watch for changes and rebuild | -| `npm run package` | Package the extension into an XPI file | -| `pipenv run test` | Run test suite (See "Running Tests" for setup) | ## Releasing a New Version @@ -97,24 +180,7 @@ You can follow along with the build and upload progress for the new release on t [signing]: https://help.github.com/articles/signing-commits/ [CircleCI dashboard]: https://circleci.com/dashboard -## Code Organization - -- `src/background` contains the background scripts that trigger UI elements (such as the page action) and periodically check for price updates. -- `src/browser_action` contains the toolbar popup for managing the list of currently-tracked products and tracking new products. -- `src/extraction` contains the content scripts that extract product information from product web pages. -- `src/state` contains the Redux-based code for managing global extension state. -- `src/tests` contains the automated test suite. - -### Data Storage - -Global state for the add-on is managed via [Redux][]. Any time the data is changed, it is persisted to the [add-on local storage][localstorage]. - -Reducers, action creators, etc. are organized into [ducks][] inside the `src/state` directory. - -[Redux]: https://redux.js.org/ -[localstorage]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/local -[ducks]: https://github.com/erikras/ducks-modular-redux ## License -The Commerce WebExtension is licensed under the MPL v2.0. See `LICENSE` for details. +The Commerce WebExtension is licensed under the MPL v2.0. See [`LICENSE`](LICENSE) for details. From 54ed54d147c274ce8a9521c49fa3261028ca8ebd Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Mon, 12 Nov 2018 15:48:19 -0800 Subject: [PATCH 026/140] Incorporate feedback from Osmose and pdehaan --- README.md | 45 ++------- docs/METRICS.md | 264 ++++++++++++++++++++---------------------------- 2 files changed, 114 insertions(+), 195 deletions(-) diff --git a/README.md b/README.md index 4eb87bc..eeb34f7 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,7 @@ Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy. -## User Experience - -See [UX specifications](https://mozilla.invisionapp.com/share/UFNSHAIMT4V#/screens/317130676_Artboard_1). - - -## Telemetry +## Data Collection See [METRICS.md](./docs/METRICS.md). @@ -60,24 +55,6 @@ Note: This will install the extension as an [unsigned](https://wiki.mozilla.org/ | `pipenv run test` | Run test suite (See "Running Tests" for setup) | -## Code Organization - -- `src/background` contains the background scripts that trigger UI elements (such as the browserAction toolbar button) and periodically check for price updates. -- `src/browser_action` contains the toolbar popup for managing the list of currently-tracked products and tracking new products. -- `src/config` contains the scripts used to fetch config values specified in [config.js](src/config.js). -- `src/experiment_apis` contains the [experimental APIs](https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/basics.html#webextensions-experiments) used to read [preference values](#preferences) and listen for chrome-privileged Firefox events. -- `src/extraction` contains the content scripts that extract product information from product web pages. -- `src/img` contains all the non-favicon images used by the extension. -- `src/state` contains the Redux-based code for managing global extension state. -- `src/styles` contains Firefox-specific CSS property values stored as variables. -- `src/telemetry` contains the scripts used to register and record extension [telemetry events](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/events.html) in different contexts. -- `src/tests` contains the automated test suite. -- `config.js` contains the static configuration settings for the extension, including default values if [override preferences](#preferences) are not set. -- `manifest.json` contains basic metadata about the extension. -- `privacy.js` handles checking privacy settings to gate functionality across the extension. -- `utils.js` contains general utility functions that can be used across the extension. - - ## Data Storage Global state for the add-on is managed via [Redux][]. Any time the data is changed, it is persisted to the [add-on local storage][localstorage]. @@ -125,32 +102,24 @@ The following preferences can be set to customize the extension's behavior for t
extensions.shopping-testpilot@mozilla.org.extractionAllowlist
-
Preference type: string. List of domains ({Array.string} or *) that extraction is performed on. Can be set to * to enable extraction on all sites (default: extractionAllowlist value specified in [config.js](src/config.js).
+
(string) List of domains ({Array.string} or *) that extraction is performed on. Can be set to * to enable extraction on all sites.
extensions.shopping-testpilot@mozilla.org.priceCheckInterval
-
Preference type: integer. Time to wait between price checks for a product in milliseconds (default: 21600000 or 6 hours).
+
(integer) Time to wait between price checks for a product in milliseconds.
extensions.shopping-testpilot@mozilla.org.priceCheckTimeoutInterval
-
Preference type: integer. Time to wait between checking if we should fetch new prices in milliseconds (default: 900000 or 15 minutes).
+
(integer) Time to wait between checking if we should fetch new prices in milliseconds.
extensions.shopping-testpilot@mozilla.org.iframeTimeout
-
Preference type: integer. Delay before removing iframes created during price checks in milliseconds (default: 60000or 1 minute).
+
(integer) Delay before removing iframes created during price checks in milliseconds.
extensions.shopping-testpilot@mozilla.org.alertPercentThreshold
-
Preference type: integer. The percentage drop in price on which to trigger a price alert compared to the last high price (See `price_last_high` in [METRICS.md](./docs/METRICS.md)) default: 5 or 5%).
+
(integer) The percentage drop in price on which to trigger a price alert compared to the last high price (See price_last_high in [METRICS.md](./docs/METRICS.md)).
extensions.shopping-testpilot@mozilla.org.alertAbsoluteThreshold
-
Preference type: integer. The absolute drop in price on which to trigger a price alert compared to the last high price (see `price_last_high` in [METRICS.md](./docs/METRICS.md)) in cents (default: 1000 or $10).
+
(integer) The absolute drop in price on which to trigger a price alert compared to the last high price (see `price_last_high` in [METRICS.md](./docs/METRICS.md)) in currency subunits (e.g. cents for USD).
-### Test Page - -The extension can be tested with this [Fake Product Page](http://www.mkelly.me/fake-product-page/), which randomly generates a price each time it loads. - -Query strings may be used to: -* Set the max price: e.g. http://www.mkelly.me/fake-product-page/?max=10000 -* Fix the price to a particular value: e.g. http://www.mkelly.me/fake-product-page/?dollars=10000 - ## Releasing a New Version diff --git a/docs/METRICS.md b/docs/METRICS.md index 2261809..6b90d88 100644 --- a/docs/METRICS.md +++ b/docs/METRICS.md @@ -13,8 +13,8 @@ A summary of the metrics the Price Wise extension will record. * **Fathom**: A [JavaScript framework](https://github.com/erikrose/fathom) used to extract product information from a Product Page. * **Price Alert**: An alert that occurs when a tracked product's price _decreases_ below a certain absolute or percentage threshold. For the MVP, the default thresholds are specified in `./src/config.js`. * **Product Card**: A product list item in the list of tracked products for which the user has opted to receive Price Alerts displayed on the browserAction popup. Each Product Card displays the product title, image and price among other information. -* **Product Page**: A webpage ([example](https://www.amazon.com/LEGO-Fantastic-Beasts-Grindelwald-Grindelwalds/dp/B07BKQXCZR/ref=sr_1_3_sspa?s=toys-and-games&ie=UTF8&qid=1538418041&sr=1-3-spons&keywords=legos&psc=1)) displaying a single product that the user could purchase online. -* **Supported Sites**: For the initial launch (a.k.a. MVP, Minimum Viable Product) of this extension, we are limiting the sites supported by this feature to [five websites](https://github.com/mozilla/price-wise/issues/36#issuecomment-409641491): Amazon, Ebay, Walmart, Home Depot and Best Buy. +* **Product Page**: A webpage displaying a single product that the user could purchase online. +* **Supported Sites**: For the initial launch (a.k.a. MVP, Minimum Viable Product) of this extension, we are limiting the sites supported by this feature to [five websites](https://github.com/mozilla/price-wise/issues/36#issuecomment-409641491): Amazon, eBay, Walmart, Home Depot and Best Buy. * **Survey**: a short survey collecting user feedback. * **Onboarding Popup**: The popup displayed when the user has zero products tracked, including the first time the popup is opened. @@ -63,7 +63,7 @@ Note: For any questions related to general user shopping behavior, the data abou ### Questions to answer in future experiments -While some of these questions may be partially answerable by this extension, answering them thorougly requires controlled A/B testing and/or more extensive data collection on more sites. +While some of these questions may be partially answerable by this extension, answering them thoroughly requires controlled A/B testing and/or more extensive data collection on more sites. #### Does it affect user behavior in Firefox? - Does it increase shopping browsing? @@ -80,116 +80,104 @@ While some of these questions may be partially answerable by this extension, ans - On what sites do users shop? -## Sample Pings +## Sample Events We will be sending pings using [Event Telemetry](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/events.html) via the [WebExtensions Telemetry API](https://bugzilla.mozilla.org/show_bug.cgi?id=1280234). -Each event will exist as part of the [`event` ping](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/data/event-ping.html) under `payload.events.dynamic` as an array (see Appendix B for how to view extension events in `about:telemetry`). The data types of individual fields for each event follow the Event Telemetry [serialization format](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/events.html#serialization-format). +The data types of individual fields for each event follow the Event Telemetry [serialization format](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/events.html#serialization-format). The telemetry category for events is `'extension.price_wise'`. -Below is a sample `event` ping for when the user visits a supported page and adds the product on that page. +Below is a sample list of events recorded when the user visits a supported page and adds the product on that page. ```javascript -{ - "type": "event", - //... - "payload": { - //... - "events": { - "dynamic": [ - [ - 154572, - "extension.price_wise", - "visit_supported_site", - "supported_site", - null, - { - "tracked_prods": "0", - "privacy_dnt": "false", - "privacy_tp": "private_browsing", - "privacy_cookie": "allow_all" - } - ], - [ - 154592, - "extension.price_wise", - "attempt_extraction", - "product_page", - null, - { - "extraction_id": "d7031676-74aa-41b7-a730-c26fc9617dd5", - "is_bg_update": "false", - "tracked_prods": "0", - "privacy_dnt": "false", - "privacy_tp": "private_browsing", - "privacy_cookie": "allow_all" - } - ], - [ - 154597, - "extension.price_wise", - "complete_extraction", - "product_page", - null, - { - "extraction_id": "d7031676-74aa-41b7-a730-c26fc9617dd5", - "is_bg_update": "false", - "method": "css_selectors", - "tracked_prods": "0", - "privacy_dnt": "false", - "privacy_tp": "private_browsing", - "privacy_cookie": "allow_all" - } - ], - [ - 154601, - "extension.price_wise", - "badge_toolbar_button", - "toolbar_button", - null, - { - "badge_type": "add", - "tracked_prods": "0", - "privacy_dnt": "false", - "privacy_tp": "private_browsing", - "privacy_cookie": "allow_all" - } - ], - [ - 156806, - "extension.price_wise", - "open_popup", - "toolbar_button", - null, - { - "badge_type": "add", - "tracked_prods": "0", - "privacy_dnt": "false", - "privacy_tp": "private_browsing", - "privacy_cookie": "allow_all" - } - ], - [ - 158056, - "extension.price_wise", - "add_product", - "add_button", - null, - { - "price": "1100", - "product_key": "791893d7-1303-4e11-9913-c2ce762aa691", - "tracked_prods": "1", - "privacy_dnt": "false", - "privacy_tp": "private_browsing", - "privacy_cookie": "allow_all" - } - ] - ] - } - }, - //... -} +[ + 154572, + "extension.price_wise", + "visit_supported_site", + "supported_site", + null, + { + "tracked_prods": "0", + "privacy_dnt": "false", + "privacy_tp": "private_browsing", + "privacy_cookie": "allow_all" + } +], +[ + 154592, + "extension.price_wise", + "attempt_extraction", + "product_page", + null, + { + "extraction_id": "d7031676-74aa-41b7-a730-c26fc9617dd5", + "is_bg_update": "false", + "tracked_prods": "0", + "privacy_dnt": "false", + "privacy_tp": "private_browsing", + "privacy_cookie": "allow_all" + } +], +[ + 154597, + "extension.price_wise", + "complete_extraction", + "product_page", + null, + { + "extraction_id": "d7031676-74aa-41b7-a730-c26fc9617dd5", + "is_bg_update": "false", + "method": "css_selectors", + "tracked_prods": "0", + "privacy_dnt": "false", + "privacy_tp": "private_browsing", + "privacy_cookie": "allow_all" + } +], +[ + 154601, + "extension.price_wise", + "badge_toolbar_button", + "toolbar_button", + null, + { + "badge_type": "add", + "tracked_prods": "0", + "privacy_dnt": "false", + "privacy_tp": "private_browsing", + "privacy_cookie": "allow_all" + } +], +[ + 156806, + "extension.price_wise", + "open_popup", + "toolbar_button", + null, + { + "badge_type": "add", + "tracked_prods": "0", + "privacy_dnt": "false", + "privacy_tp": "private_browsing", + "privacy_cookie": "allow_all" + } +], +[ + 158056, + "extension.price_wise", + "add_product", + "add_button", + null, + { + "price": "1100", + "product_key": "791893d7-1303-4e11-9913-c2ce762aa691", + "tracked_prods": "1", + "privacy_dnt": "false", + "privacy_tp": "private_browsing", + "privacy_cookie": "allow_all" + } +] ``` @@ -218,7 +206,7 @@ Some `extra_keys` are sent with every telemetry event recorded by the extension: - `'element'`: The extension UI element that the user clicked to open a page in a new tab. Note: All `*_link` elements exist in the Onboarding Popup only. One of... - `'amazon_link'`: Sends the user to Amazon. - `'best_buy_link'`: Sends the user to Best Buy. - - `'ebay_link'`: Sends the user to Ebay. + - `'ebay_link'`: Sends the user to eBay. - `'feedback_button'`: Sends the user to a feedback Survey. - `'help_button'`: Sends the user to a Price Wise support.mozilla.org page. - `'home_depot_link'`: Sends the user to Home Depot. @@ -472,7 +460,7 @@ No telemetry will be sent from the extension in the following additional cases: Fired when the user uninstalls the extension. -This event, along with all other add-on lifecycle events, is recorded by the Addons Manager's event telemetry in Firefox. It will exist as part of the `event` ping under `payload.events.parent` as an array. +This event, along with all other add-on lifecycle events, is recorded by the Addons Manager's event telemetry in Firefox. This event will be fired under the `addonsManager` telemetry category. @@ -480,56 +468,18 @@ Notes: - Other lifecycle events such as `install` may have a different event structure than `uninstall`. Since `addonsManager` events are registered statically, you can view how each event is structured in [Events.yaml](https://searchfox.org/mozilla-central/source/toolkit/components/telemetry/Events.yaml) in the Firefox source code. - The `addonsManager` events are only available in Firefox version 64 and later versions. -#### Sample Ping +#### Sample Event ```javascript -{ - "type": "event", - //... - "payload": { - //... - "events": { - "parent": [ - [ - 9792, - "addonsManager", - "uninstall", - "extension", - "shopping-testpilot@mozilla.org", - { - "source": "testpilot" - // ... - } - ] - ] - } - }, - //... -} +[ + 9792, + "addonsManager", + "uninstall", + "extension", + "shopping-testpilot@mozilla.org", + { + "source": "testpilot" + // ... + } +] ``` - - -### Appendix B: How to view Price Wise events in `about:telemetry` - -Note: Event Telemetry for this extension may be disabled for certain situations, see [Opt Out](#opt-out). - -#### Current Session - -To view event telemetry for the current session: - -1. Navigate to `about:telemetry`. -2. Click 'Events' in the sidebar menu. - - Note: This menu item is not present until an event has been recorded for the current session. If you don't see it, trigger one of the events as described in this document (e.g. `open_popup`) and refresh the page. -3. On the top right corner of the next page, click 'dynamic' in the dropdown menu. -4. You should see a table displayed with all the recorded dynamic events for the session. - -#### Previous Session - -To view event telemetry from a previous session: - -1. Click the dropdown menu down arrow in the top left corner of `about:telemetry` -2. Select 'Archived ping data' -3. Select the `event` ping type -4. Choose an archived `event` ping by date and time -5. In the sidebar menu, select 'Raw Payload' -6. You should see the `payload` JSON object displayed with events listed in the `events` array From 6563d1e6f507daa5af840424be110dcdc91d6e96 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Mon, 12 Nov 2018 16:11:02 -0800 Subject: [PATCH 027/140] Fix #262: Update survey URL --- src/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.js b/src/config.js index 3e7f175..22aa612 100644 --- a/src/config.js +++ b/src/config.js @@ -76,7 +76,7 @@ const CONFIG = { supportUrl: new StringValue('https://support.mozilla.org/kb/new-test-pilot-experiments'), /** URL for the add-on's feedback form */ - feedbackUrl: new StringValue('https://www.surveygizmo.com/s3/4649085/Price-Wise-Feedback'), + feedbackUrl: new StringValue('https://qsurvey.mozilla.com/s3/price-wise'), /** List of domains that extraction is performed on. */ extractionAllowlist: new ListValue([ From 3f42a3616e165abe62137e598f38465d7d6fce27 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Tue, 13 Nov 2018 17:25:28 -0800 Subject: [PATCH 028/140] Fix #147: Update product information during re-extraction Adds a new Redux action UPDATE_PRODUCT which replaces the existing Product object in the store with a new one created from a re-extraction of the product page. The only keys that are not overwritten are the ids: `product.id` and `product.anonId`. --- src/background/price_updates.js | 10 +++++++--- src/state/products.js | 29 +++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/background/price_updates.js b/src/background/price_updates.js index 7c0bddf..aed9ff5 100644 --- a/src/background/price_updates.js +++ b/src/background/price_updates.js @@ -11,7 +11,7 @@ import config from 'commerce/config'; import store from 'commerce/state'; import {shouldUpdatePrices} from 'commerce/privacy'; import {addPriceFromExtracted, getLatestPriceForProduct, getOldestPriceForProduct} from 'commerce/state/prices'; -import {getAllProducts, getProduct, getProductIdFromExtracted} from 'commerce/state/products'; +import {getAllProducts, getProduct, getProductIdFromExtracted, updateProductFromExtracted} from 'commerce/state/products'; import {wait} from 'commerce/utils'; import {recordEvent} from 'commerce/telemetry/extension'; @@ -82,8 +82,8 @@ async function fetchLatestPrice(product, delay) { } /** - * If we have a saved product matching the extracted data, update the - * price history with the latest price. + * If we have a saved product matching the extracted data, update the product + * information and price history with the latest price. * @param {ExtractedProduct} data */ export async function updateProductWithExtracted(data) { @@ -91,6 +91,10 @@ export async function updateProductWithExtracted(data) { const id = getProductIdFromExtracted(data); const product = getProduct(state, id); if (product) { + // Update all product information (except product ids) in case they have changed + await store.dispatch(updateProductFromExtracted(data, id, product.anonId)); + + // Add new price const price = await store.dispatch(addPriceFromExtracted(data)); if (price) { // Record the detect_price_change event diff --git a/src/state/products.js b/src/state/products.js index 7cb2e27..840d640 100644 --- a/src/state/products.js +++ b/src/state/products.js @@ -99,6 +99,7 @@ export function isValidExtractedProduct(extractedProduct) { export const ADD_PRODUCT = 'commerce/products/ADD_PRODUCT'; // Used by price duck const SET_DELETION_FLAG = 'commerce/products/SET_DELETION_FLAG'; export const REMOVE_MARKED_PRODUCTS = 'commerce/products/REMOVE_MARKED_PRODUCTS'; +const UPDATE_PRODUCT = 'commerce/products/UPDATE_PRODUCT'; // Reducer @@ -137,6 +138,21 @@ export default function reducer(state = initialState(), action) { products: state.products.filter(product => !product.isDeleted), }; } + case UPDATE_PRODUCT: { + const updatedProduct = getProductFromExtracted( + {...action.extractedProductData}, + action.anonId, + ); + return { + ...state, + products: state.products.map((product) => { + if (product.id === action.productId) { + return {...updatedProduct}; + } + return product; + }), + }; + } default: return state; } @@ -182,6 +198,19 @@ export function removeMarkedProducts() { }; } +/** + * Update an existing product in the store. + * @param {ExtractedProduct} data + */ +export function updateProductFromExtracted(data, productId, anonId) { + return { + type: UPDATE_PRODUCT, + extractedProductData: data, + productId, + anonId, + }; +} + // Selectors /** From 6966d858199d954e6f77112b7bb5e35a30f26adc Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Tue, 13 Nov 2018 17:29:57 -0800 Subject: [PATCH 029/140] Fix JavaScript error introduced by PR #247 Tacking this on, though it's an unrelated error. Previously, we were attempting to send messages via `tabs.sendMessage` to all content scripts both the ones running in content processes and in the background. However, the tabId for a content script in the background is -1, which is not a valid value for sending messages to content scripts in specific tabs. Since the code that introduced this error was intended to fix an issue related to badging the browserAction toolbar button to add a new product, and since that badging is only triggered by extraction in content processes, we don't need to worry about sending the message to the background. Now, we now no longer see the error: `Type error for parameter tabId (Integer -1 is too small (must be at least 0)) for tabs.sendMessage.` --- src/background/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/background/index.js b/src/background/index.js index 6beb510..0988eb3 100644 --- a/src/background/index.js +++ b/src/background/index.js @@ -70,7 +70,7 @@ import {registerEvents, handleWidgetRemoved} from 'commerce/telemetry/extension' // TODO(osmose): Remove once Firefox 64 hits the release channel. browser.webRequest.onCompleted.addListener( (details) => { - if (details.tabId) { + if (details.tabId && details.tabId !== browser.tabs.TAB_ID_NONE) { browser.tabs.sendMessage(details.tabId, {type: 'resend-product'}); } }, From f9d7c5ed822b6a43960a4c9441f3e7438be5726e Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Wed, 14 Nov 2018 10:56:49 -0800 Subject: [PATCH 030/140] #186: Enable category 1/2 event telemetry in certain privacy contexts In order to avoid the eslint `no-cycle` error, I moved all events to be registered to their own `events.js` script, so that both `privacy.js` and `extension.js` could import from `events.js`. (thanks Osmose for the idea) More about the `no-cycle` error that was avoided: This error came up when I tried to import CATEGORY_3_EVENTS from `./src/telemetry/extension.js` into `./src/privacy.js`, since we were already importing `shouldCollectTelemetry` from the latter into the former. --- src/privacy.js | 22 +++-- src/telemetry/events.js | 185 +++++++++++++++++++++++++++++++++++++ src/telemetry/extension.js | 174 +--------------------------------- 3 files changed, 200 insertions(+), 181 deletions(-) create mode 100644 src/telemetry/events.js diff --git a/src/privacy.js b/src/privacy.js index e0f2adb..ed6652d 100644 --- a/src/privacy.js +++ b/src/privacy.js @@ -7,6 +7,8 @@ * @module */ +import {CATEGORY_3_EVENTS} from 'commerce/telemetry/events'; + /** * Determine if a content script should extract a product. * @return {boolean} @@ -19,17 +21,19 @@ export async function shouldExtract() { * Determine if a telemetry event should be recorded * @return {boolean} */ -export async function shouldCollectTelemetry() { - if (await trackingProtectionEnabled()) { - return false; - } +export async function shouldCollectTelemetry(method) { + if (CATEGORY_3_EVENTS.hasOwnProperty(method)) { + if (await trackingProtectionEnabled()) { + return false; + } - if (doNotTrackEnabled()) { - return false; - } + if (doNotTrackEnabled()) { + return false; + } - if (await cookiesBlocked()) { - return false; + if (await cookiesBlocked()) { + return false; + } } return true; diff --git a/src/telemetry/events.js b/src/telemetry/events.js new file mode 100644 index 0000000..a1fdf6a --- /dev/null +++ b/src/telemetry/events.js @@ -0,0 +1,185 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Lists all events by data collection category to be recorded by the extension. + * Which events are recorded and when can depend on this category (e.g. + * category 1/2 versus category 3). + * @module + */ + +export const CATEGORY = 'extension.price_wise'; + +const DEFAULT_EXTRAS = [ + 'tracked_prods', + 'privacy_dnt', + 'privacy_tp', + 'privacy_cookie', +]; + +const CATEGORY_1_AND_2_EVENTS = { + // User clicks toolbar button to open the popup + open_popup: { + methods: ['open_popup'], + objects: ['toolbar_button'], + extra_keys: [ + 'badge_type', + ...DEFAULT_EXTRAS, + ], + record_on_release: true, + }, + // User clicks on a UI element in the extension opening a non-product page in a new tab + open_nonproduct_page: { + methods: ['open_nonproduct_page'], + objects: ['ui_element'], + extra_keys: [ + 'element', + ...DEFAULT_EXTRAS, + ], + record_on_release: true, + }, + // User clicks on a UI element in the extension opening a product page in a new tab + open_product_page: { + methods: ['open_product_page'], + objects: ['product_card', 'system_notification'], + extra_keys: [ + 'price', + 'price_alert', + 'price_orig', + 'product_key', + ...DEFAULT_EXTRAS, + // For 'objects' value 'product_card' only + 'product_index', + // For 'objects' value of 'system_notification' only + 'price_last_high', + ], + record_on_release: true, + }, + // User adds a product to the product listing + add_product: { + methods: ['add_product'], + objects: ['add_button'], + extra_keys: [ + 'price', + 'product_key', + ...DEFAULT_EXTRAS, + ], + record_on_release: true, + }, + // User deletes a product from the product listing + delete_product: { + methods: ['delete_product'], + objects: ['delete_button'], + extra_keys: [ + 'price', + 'price_alert', + 'price_orig', + 'product_index', + 'product_key', + ...DEFAULT_EXTRAS, + ], + record_on_release: true, + }, + // User undeletes a product from the product listing + undo_delete_product: { + methods: ['undo_delete_product'], + objects: ['undo_button'], + extra_keys: [ + 'price', + 'price_alert', + 'price_orig', + 'product_index', + 'product_key', + ...DEFAULT_EXTRAS, + ], + record_on_release: true, + }, + // User hides the toolbar button for the extension + hide_toolbar_button: { + methods: ['hide_toolbar_button'], + objects: ['toolbar_button'], + extra_keys: [ + 'badge_type', + ...DEFAULT_EXTRAS, + ], + record_on_release: true, + }, + // There is a price change on a tracked product + detect_price_change: { + methods: ['detect_price_change'], + objects: ['product_page'], + extra_keys: [ + 'price', + 'price_prev', + 'price_orig', + 'product_key', + ...DEFAULT_EXTRAS, + ], + record_on_release: true, + }, + + // Toolbar button is badged either due to a price alert or an extracted product + badge_toolbar_button: { + methods: ['badge_toolbar_button'], + objects: ['toolbar_button'], + extra_keys: [ + 'badge_type', + ...DEFAULT_EXTRAS, + ], + record_on_release: true, + }, + // System notification is sent notifying user of a price alert + send_notification: { + methods: ['send_notification'], + objects: ['system_notification'], + extra_keys: [ + 'price', + 'price_last_high', + 'price_orig', + 'product_key', + ...DEFAULT_EXTRAS, + ], + record_on_release: true, + }, + // Product extraction is attempted on the content page + attempt_extraction: { + methods: ['attempt_extraction'], + objects: ['product_page'], + extra_keys: [ + 'extraction_id', + 'is_bg_update', + ...DEFAULT_EXTRAS, + ], + record_on_release: true, + }, + // Product extraction is completed on the content page + complete_extraction: { + methods: ['complete_extraction'], + objects: ['product_page'], + extra_keys: [ + 'extraction_id', + 'is_bg_update', + 'method', + ...DEFAULT_EXTRAS, + ], + record_on_release: true, + }, +}; + +export const CATEGORY_3_EVENTS = { + // User visits a supported site + visit_supported_site: { + methods: ['visit_supported_site'], + objects: ['supported_site'], + extra_keys: [ + ...DEFAULT_EXTRAS, + ], + record_on_release: true, + }, +}; + +export const EVENTS = { + ...CATEGORY_1_AND_2_EVENTS, + ...CATEGORY_3_EVENTS, +}; diff --git a/src/telemetry/extension.js b/src/telemetry/extension.js index a964143..03c4a1d 100644 --- a/src/telemetry/extension.js +++ b/src/telemetry/extension.js @@ -10,184 +10,14 @@ import {shouldCollectTelemetry} from 'commerce/privacy'; import store from 'commerce/state'; import {getAllProducts} from 'commerce/state/products'; - -const CATEGORY = 'extension.price_wise'; - -const DEFAULT_EXTRAS = [ - 'tracked_prods', - 'privacy_dnt', - 'privacy_tp', - 'privacy_cookie', -]; - -const EVENTS = { - // User Events - // User visits a supported site - visit_supported_site: { - methods: ['visit_supported_site'], - objects: ['supported_site'], - extra_keys: [ - ...DEFAULT_EXTRAS, - ], - record_on_release: true, - }, - - // User clicks toolbar button to open the popup - open_popup: { - methods: ['open_popup'], - objects: ['toolbar_button'], - extra_keys: [ - 'badge_type', - ...DEFAULT_EXTRAS, - ], - record_on_release: true, - }, - // User clicks on a UI element in the extension opening a non-product page in a new tab - open_nonproduct_page: { - methods: ['open_nonproduct_page'], - objects: ['ui_element'], - extra_keys: [ - 'element', - ...DEFAULT_EXTRAS, - ], - record_on_release: true, - }, - // User clicks on a UI element in the extension opening a product page in a new tab - open_product_page: { - methods: ['open_product_page'], - objects: ['product_card', 'system_notification'], - extra_keys: [ - 'price', - 'price_alert', - 'price_orig', - 'product_key', - ...DEFAULT_EXTRAS, - // For 'objects' value 'product_card' only - 'product_index', - // For 'objects' value of 'system_notification' only - 'price_last_high', - ], - record_on_release: true, - }, - // User adds a product to the product listing - add_product: { - methods: ['add_product'], - objects: ['add_button'], - extra_keys: [ - 'price', - 'product_key', - ...DEFAULT_EXTRAS, - ], - record_on_release: true, - }, - // User deletes a product from the product listing - delete_product: { - methods: ['delete_product'], - objects: ['delete_button'], - extra_keys: [ - 'price', - 'price_alert', - 'price_orig', - 'product_index', - 'product_key', - ...DEFAULT_EXTRAS, - ], - record_on_release: true, - }, - // User undeletes a product from the product listing - undo_delete_product: { - methods: ['undo_delete_product'], - objects: ['undo_button'], - extra_keys: [ - 'price', - 'price_alert', - 'price_orig', - 'product_index', - 'product_key', - ...DEFAULT_EXTRAS, - ], - record_on_release: true, - }, - // User hides the toolbar button for the extension - hide_toolbar_button: { - methods: ['hide_toolbar_button'], - objects: ['toolbar_button'], - extra_keys: [ - 'badge_type', - ...DEFAULT_EXTRAS, - ], - record_on_release: true, - }, - - // Non-User Events - // There is a price change on a tracked product - detect_price_change: { - methods: ['detect_price_change'], - objects: ['product_page'], - extra_keys: [ - 'price', - 'price_prev', - 'price_orig', - 'product_key', - ...DEFAULT_EXTRAS, - ], - record_on_release: true, - }, - - // Toolbar button is badged either due to a price alert or an extracted product - badge_toolbar_button: { - methods: ['badge_toolbar_button'], - objects: ['toolbar_button'], - extra_keys: [ - 'badge_type', - ...DEFAULT_EXTRAS, - ], - record_on_release: true, - }, - // System notification is sent notifying user of a price alert - send_notification: { - methods: ['send_notification'], - objects: ['system_notification'], - extra_keys: [ - 'price', - 'price_last_high', - 'price_orig', - 'product_key', - ...DEFAULT_EXTRAS, - ], - record_on_release: true, - }, - // Product extraction is attempted on the content page - attempt_extraction: { - methods: ['attempt_extraction'], - objects: ['product_page'], - extra_keys: [ - 'extraction_id', - 'is_bg_update', - ...DEFAULT_EXTRAS, - ], - record_on_release: true, - }, - // Product extraction is completed on the content page - complete_extraction: { - methods: ['complete_extraction'], - objects: ['product_page'], - extra_keys: [ - 'extraction_id', - 'is_bg_update', - 'method', - ...DEFAULT_EXTRAS, - ], - record_on_release: true, - }, -}; +import {CATEGORY, EVENTS} from 'commerce/telemetry/events'; export async function registerEvents() { await browser.telemetry.registerEvents(CATEGORY, EVENTS); } export async function recordEvent(method, object, value, extraBase = {}) { - if (!browser.telemetry.canUpload() || !(await shouldCollectTelemetry())) { + if (!browser.telemetry.canUpload() || !(await shouldCollectTelemetry(method))) { return; } From 4ea7eedb979d8ea655a80e9eb90e95385699002f Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Wed, 14 Nov 2018 12:02:56 -0800 Subject: [PATCH 031/140] Fix #186: Enable price polling in certain privacy contexts Previously, price polling (a.k.a. background price updates) was disabled when Do Not Track, Tracking Protection or certain cookie settings ('reject_third_party' and 'reject_all') were enabled. Now, price polling occurs in these situations. This leaves the `shouldUpdatePrices` function in `privacy.js` kind of useless, but I left it there instead of removing it entirely in order to add the Private Browsing check that is part of #177. --- src/privacy.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/privacy.js b/src/privacy.js index ed6652d..dff355f 100644 --- a/src/privacy.js +++ b/src/privacy.js @@ -44,18 +44,7 @@ export async function shouldCollectTelemetry(method) { * @return {boolean} */ export async function shouldUpdatePrices() { - if (await trackingProtectionEnabled()) { - return false; - } - - if (doNotTrackEnabled()) { - return false; - } - - if (await cookiesBlocked()) { - return false; - } - + // TODO (bdanforth): Add private browsing check per #177 return true; } From 2558ea5c6290f3b4918ddaddafba37c12595ba37 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Thu, 4 Oct 2018 21:44:37 -0400 Subject: [PATCH 032/140] Get trainer running on image out-rule from webext-commerce. Basically, copy ruleset_factory.js over from webext-commerce, copy the coeffs out of fathom_default_coefficients.json, and write a line or 2 of glue. --- src/extraction/fathom/ruleset_factory.js | 16 +++--- src/extraction/fathom/trainees.js | 69 ++++-------------------- 2 files changed, 21 insertions(+), 64 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index c5989ba..49c8d1f 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -2,10 +2,16 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/** + * Exports a RulesetFactory class, which when instantiated, binds Fathom + * coefficients to a ruleset. An instance of this class is used for product + * feature extraction (`fathom_extraction.js`) and for training (`trainees.js`). + */ + import {dom, out, rule, ruleset, score, type} from 'fathom-web'; // Since the fathom-trainees add-on currently uses a submodule of Fathom, for // training, replace 'utils' with 'utilsForFrontend' -import {ancestors} from 'fathom-web/utils'; +import {ancestors} from 'fathom-web/utilsForFrontend'; const DEFAULT_BODY_FONT_SIZE = 14; const DEFAULT_SCORE = 1; @@ -14,13 +20,11 @@ const TOP_BUFFER = 150; const ZEROISH = 0.08; const ONEISH = 0.9; -/** - * Creates Fathom ruleset instances, and holds individual rule methods for - * easier testing. - */ export default class RulesetFactory { /** - * @param {number[]} coefficients + * Create a ruleset factory. + * + * @param {Array.number} coefficients The coefficients to apply for each rule */ constructor(coefficients) { [ diff --git a/src/extraction/fathom/trainees.js b/src/extraction/fathom/trainees.js index 0f0a4f0..1494ab9 100644 --- a/src/extraction/fathom/trainees.js +++ b/src/extraction/fathom/trainees.js @@ -1,16 +1,11 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +import {ruleset, rule, dom, type, score, out} from 'fathom-web'; +import {ancestors} from 'fathom-web/utilsForFrontend'; -/* eslint-disable import/no-unresolved */ -import defaultCoefficients from './coefficients.json'; import RulesetFactory from './ruleset_factory'; -// Array of numbers corresponding to the coefficients in order -const coeffs = RulesetFactory.getCoeffsInOrder(defaultCoefficients); /** - * Rulesets to train using Fathom. + * Rulesets to train. * * More mechanically, a map of names to {coeffs, rulesetMaker} objects. * rulesetMaker is a function that takes an Array of coefficients and returns a @@ -18,58 +13,16 @@ const coeffs = RulesetFactory.getCoeffsInOrder(defaultCoefficients); * for a ruleset but can also be some more widely flung ones that you want to * start the trainer from. The rulesets you specify here show up in the Train * UI, from which you can kick off a training run. - * - * How to train: - * 1. Fork the `mozilla/fathom-trainees` repo, - * 2. In the `fathom-trainees` add-on, copy `src/extraction/fathom` to the - * `./src` folder. - * * Note: You will have to replace 'utils' with 'utilsForFrontend' on the - * import in `ruleset_factory.js`. See that file for more information. - * 3. Follow instructions at: https://github.com/erikrose/fathom-fox#the-trainer. - * - * Notes: - * - The FathomFox Trainer assumes that the value of your corpus' `data-fathom` - * attribute is the same as the `out`-ed string. Example: An element tagged with - * `data-fathom="image"` will map to `rule(..., out("image"))`. - * - The Trainer assumes that the name of the ruleset and the out-rule of interest - * are the same. Therefore, if a ruleset contains more than one out-rule, - * each `out`-ed feature must have its own key in the `trainees` map. You can - * select which feature to train from the dropdown menu on FathomFox's Trainer page. - * - I would not recommend using the Corpus Collector to build up a training set, - * because you can only batch freeze original pages, meaning tagged pages would be - * re-freezed, and there are non-obvious side effects in the diff (an issue with - * the freeze-dried library Fathom uses). */ +const trainees = new Map(); -function rulesetMaker(coefficients) { - // The coefficients are updated over time during training, so create a new factory for - // each iteration - const rulesetFactory = new RulesetFactory(coefficients); - return rulesetFactory.makeRuleset(); -} - -const trainees = new Map([ - [ +trainees.set( + // A ruleset that finds the full-screen, content-blocking overlays that + // often go behind modal popups 'image', - { - coeffs, - rulesetMaker, - }, - ], - [ - 'title', - { - coeffs, - rulesetMaker, - }, - ], - [ - 'price', - { - coeffs, - rulesetMaker, - }, - ], -]); + {coeffs: [8, 2, 17, 15, 13, 33, 5, 5, 7, 2], + rulesetMaker: coeffs => (new RulesetFactory(coeffs)).makeRuleset() + } +); export default trainees; From ca8d4c8eb0fd761b24beddc070e95e98385f5201 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Thu, 18 Oct 2018 21:10:36 -0400 Subject: [PATCH 033/140] Add a trainee for each out() rule so we can choose them from the Trainer menu. ...rather than having to edit the code between training or testing runs. --- src/extraction/fathom/trainees.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/extraction/fathom/trainees.js b/src/extraction/fathom/trainees.js index 1494ab9..4cb1716 100644 --- a/src/extraction/fathom/trainees.js +++ b/src/extraction/fathom/trainees.js @@ -16,13 +16,14 @@ import RulesetFactory from './ruleset_factory'; */ const trainees = new Map(); -trainees.set( - // A ruleset that finds the full-screen, content-blocking overlays that - // often go behind modal popups - 'image', - {coeffs: [8, 2, 17, 15, 13, 33, 5, 5, 7, 2], - rulesetMaker: coeffs => (new RulesetFactory(coeffs)).makeRuleset() - } -); +const commonRuleset = { + coeffs: [8, 2, 17, 15, 13, 33, 5, 5, 7, 2], + viewportSize: {width: 1680, height: 950}, + rulesetMaker: coeffs => (new RulesetFactory(coeffs)).makeRuleset() +}; + +trainees.set('image', commonRuleset); +trainees.set('title', commonRuleset); +trainees.set('price', commonRuleset); export default trainees; From ce27b0d5c10cb06d62bc59f7449fecd183f36b2c Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Thu, 25 Oct 2018 14:39:01 -0400 Subject: [PATCH 034/140] Respell a regex for clarity. --- src/extraction/fathom/ruleset_factory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index 49c8d1f..f1c4163 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -184,7 +184,7 @@ export default class RulesetFactory { * a decimal point and exactly two after, where the two digits after the decimal point * are at the end of the string */ - const regExp = /\${0,1}\d+\.\d{2}$/; + const regExp = /\$?\d+\.\d{2}$/; if (regExp.test(text)) { return this.hasPriceishPatternCoeff; } From d8e6f43fd734110e443b0cb7e97b4b966d4150fd Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Thu, 25 Oct 2018 17:05:39 -0400 Subject: [PATCH 035/140] Bring up to date with 9813ba8b59e6125b9ab18f51499e47bb2ec55745 in https://github.com/mozilla/price-wise. --- src/extraction/fathom/ruleset_factory.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index f1c4163..d27b10d 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -2,12 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/** - * Exports a RulesetFactory class, which when instantiated, binds Fathom - * coefficients to a ruleset. An instance of this class is used for product - * feature extraction (`fathom_extraction.js`) and for training (`trainees.js`). - */ - import {dom, out, rule, ruleset, score, type} from 'fathom-web'; // Since the fathom-trainees add-on currently uses a submodule of Fathom, for // training, replace 'utils' with 'utilsForFrontend' @@ -20,11 +14,13 @@ const TOP_BUFFER = 150; const ZEROISH = 0.08; const ONEISH = 0.9; +/** + * Creates Fathom ruleset instances, and holds individual rule methods for + * easier testing. + */ export default class RulesetFactory { /** - * Create a ruleset factory. - * - * @param {Array.number} coefficients The coefficients to apply for each rule + * @param {number[]} coefficients */ constructor(coefficients) { [ From 46b61d944ea8d30598e7266bba8ec776b126866f Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Thu, 25 Oct 2018 17:18:45 -0400 Subject: [PATCH 036/140] Rewrite isAboveTheFold using trapezoid() and fuzzy-logic scores. I'm hoping this sort of thing will help penalties like the cart one have a more consistent effect, since we'll no longer be blowing up bonuses without bound. --- src/extraction/fathom/ruleset_factory.js | 48 +++++++++++++++--------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index d27b10d..b489bb6 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -104,24 +104,11 @@ export default class RulesetFactory { */ isAboveTheFold(fnode, featureCoeff) { const viewportHeight = window.innerHeight; - const top = fnode.element.getBoundingClientRect().top; - const upperHeightLimit = viewportHeight * 2; + const imageTop = fnode.element.getBoundingClientRect().top; - // If the node is below the fold by more than a viewport's length, - // return a low score. - if (top >= upperHeightLimit) { - return ZEROISH * featureCoeff; - } - - // If the node is above the fold, return a high score. - if (top <= viewportHeight) { - return ONEISH * featureCoeff; - } - - // Otherwise, scale the score linearly between the fold and a viewport's - // length below it. - const slope = (ONEISH - ZEROISH) / (viewportHeight - upperHeightLimit); - return (slope * (top - upperHeightLimit) + ZEROISH) * featureCoeff; + // Stop giving additional bonus for anything closer than 200px to the top + // of the viewport. Those are probably usually headers. + return trapezoid(imageTop, viewportHeight * 2, 200) ** featureCoeff; } /** @@ -334,3 +321,30 @@ export default class RulesetFactory { return fnode._ruleset.get('image')[0].element; // eslint-disable-line no-underscore-dangle } } + +/** + * Scale a number to the range [ZEROISH, ONEISH]. + * + * For a rising trapezoid, the result is ZEROISH until the input reaches + * zeroAt, then increases linearly until oneAt, at which it becomes ONEISH. To + * make a falling trapezoid, where the result is ONEISH to the left and ZEROISH + * to the right, use a zeroAt greater than oneAt. + */ +function trapezoid(number, zeroAt, oneAt) { + const isRising = zeroAt < oneAt; + if (isRising) { + if (number <= zeroAt) { + return ZEROISH; + } else if (number >= oneAt) { + return ONEISH; + } + } else { + if (number >= zeroAt) { + return ZEROISH; + } else if (number <= oneAt) { + return ONEISH; + } + } + const slope = (ONEISH - ZEROISH) / (oneAt - zeroAt); + return slope * (number - zeroAt) + ZEROISH; +} From 2eb12b8fb62f1ba630f0e833955e7784076cf548 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Thu, 25 Oct 2018 17:33:27 -0400 Subject: [PATCH 037/140] Refactor largerImage as well. This completes the image coefficients. Images still score 100%. --- src/extraction/fathom/ruleset_factory.js | 15 +++++++++------ src/extraction/fathom/trainees.js | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index b489bb6..e9b3dc4 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -34,7 +34,7 @@ export default class RulesetFactory { this.isNearbyImageYAxisTitleCoeff, this.largerFontSizeCoeff, this.largerImageCoeff, - ] = coefficients; + ] = [0, 0, 0, 0, coefficients[0], 0, 0, 0, 0, coefficients[1]]; } /** @@ -42,11 +42,14 @@ export default class RulesetFactory { */ largerImage(fnode) { const domRect = fnode.element.getBoundingClientRect(); - const area = (domRect.width) * (domRect.height); - if (area === 0) { - return DEFAULT_SCORE; - } - return area * this.largerImageCoeff; + const area = domRect.width * domRect.height; + + // Assume no product images as small as 80px^2. No further bonus over + // 1000^2. For one thing, that's getting into background image territory + // (though we should have distinct penalties for that sort of thing if we + // care). More importantly, clamp the upper bound of the score so we don't + // overcome other bonuses and penalties. + return trapezoid(area, 80 ** 2, 1000 ** 2) ** this.largerImageCoeff; } /** diff --git a/src/extraction/fathom/trainees.js b/src/extraction/fathom/trainees.js index 4cb1716..0eab4a3 100644 --- a/src/extraction/fathom/trainees.js +++ b/src/extraction/fathom/trainees.js @@ -17,7 +17,7 @@ import RulesetFactory from './ruleset_factory'; const trainees = new Map(); const commonRuleset = { - coeffs: [8, 2, 17, 15, 13, 33, 5, 5, 7, 2], + coeffs: [4, 4], viewportSize: {width: 1680, height: 950}, rulesetMaker: coeffs => (new RulesetFactory(coeffs)).makeRuleset() }; From 51e6b30f5f13edfaac4758e12ff83310c6f1c9dd Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Fri, 26 Oct 2018 15:36:53 -0400 Subject: [PATCH 038/140] Rewrite image y-axis scorer to constrain to 0..1 and for simplicity. I'm not sure what scaling by the viewport size was getting us before. I could just be dense. Put the coefficients vector back; I had used a shrunken one for faster training when working on image rules. --- src/extraction/fathom/ruleset_factory.js | 40 +++++++++++++----------- src/extraction/fathom/trainees.js | 2 +- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index e9b3dc4..23baefa 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -34,7 +34,7 @@ export default class RulesetFactory { this.isNearbyImageYAxisTitleCoeff, this.largerFontSizeCoeff, this.largerImageCoeff, - ] = [0, 0, 0, 0, coefficients[0], 0, 0, 0, 0, coefficients[1]]; + ] = coefficients; } /** @@ -140,23 +140,27 @@ export default class RulesetFactory { } /** - * Scores fnode based on its y distance from the highest scoring image element + * Return whether the potential title is near the top or bottom of the + * highest-scoring image. + * + * This is a makeshift ORing 2 signals: a "near the top" and a "near the + * bottom" one. */ - isNearbyImageYAxisTitle(fnode) { - const viewportHeight = window.innerHeight; - const DOMRect = fnode.element.getBoundingClientRect(); - const imageElement = this.getHighestScoringImage(fnode); - const imageDOMRect = imageElement.getBoundingClientRect(); - // Some titles (like on Ebay) are above the image, so include a top buffer - const isEleTopNearby = DOMRect.top >= (imageDOMRect.top - TOP_BUFFER); - const isEleBottomNearby = DOMRect.bottom <= imageDOMRect.bottom; - // Give elements in a specific vertical band a higher score - if (isEleTopNearby && isEleBottomNearby) { - const deltaY = Math.abs(imageDOMRect.top - DOMRect.top); - // Give a higher score the closer it is to the image, normalized by viewportHeight - return (viewportHeight / deltaY) * this.isNearbyImageYAxisTitleCoeff; - } - return DEFAULT_SCORE; + isNearImageTopOrBottom(fnode) { + const image = this.getHighestScoringImage(fnode); + const imageRect = image.getBoundingClientRect(); + const nodeRect = fnode.element.getBoundingClientRect(); + + // Should cover title above image and title in a column next to image. + // Could also consider using the y-axis midpoint of title. + const topDistance = Math.abs(imageRect.top - nodeRect.top); + + // Test nodeRect.top. They're probably not side by side with the title at + // the bottom. Rather, title will be below image. + const bottomDistance = Math.abs(imageRect.bottom - nodeRect.top); + + const shortestDistance = Math.min(topDistance, bottomDistance); + return trapezoid(shortestDistance, 200, 0) ** this.isNearbyImageYAxisTitleCoeff; } /** @@ -278,7 +282,7 @@ export default class RulesetFactory { // consider all eligible h1 elements rule(dom('h1').when(this.isEligibleTitle.bind(this)), type('titleish')), // better score based on y-axis proximity to max scoring image element - rule(type('titleish'), score(this.isNearbyImageYAxisTitle.bind(this))), + rule(type('titleish'), score(this.isNearImageTopOrBottom.bind(this))), // return title element(s) with max score rule(type('titleish').max(), out('title')), diff --git a/src/extraction/fathom/trainees.js b/src/extraction/fathom/trainees.js index 0eab4a3..4cb1716 100644 --- a/src/extraction/fathom/trainees.js +++ b/src/extraction/fathom/trainees.js @@ -17,7 +17,7 @@ import RulesetFactory from './ruleset_factory'; const trainees = new Map(); const commonRuleset = { - coeffs: [4, 4], + coeffs: [8, 2, 17, 15, 13, 33, 5, 5, 7, 2], viewportSize: {width: 1680, height: 950}, rulesetMaker: coeffs => (new RulesetFactory(coeffs)).makeRuleset() }; From 6909520048a88bf3a60eab4845cac1fa65f5b36f Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Mon, 29 Oct 2018 10:49:45 -0400 Subject: [PATCH 039/140] Retrain to fix the priceish coeff for isAboutTheFold(). Title and image are unaffected, since they don't really have many rules to balance atm. --- src/extraction/fathom/trainees.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extraction/fathom/trainees.js b/src/extraction/fathom/trainees.js index 4cb1716..7ea23f2 100644 --- a/src/extraction/fathom/trainees.js +++ b/src/extraction/fathom/trainees.js @@ -17,7 +17,7 @@ import RulesetFactory from './ruleset_factory'; const trainees = new Map(); const commonRuleset = { - coeffs: [8, 2, 17, 15, 13, 33, 5, 5, 7, 2], + coeffs: [7, 1, 18, 19, 2, 20, 4, 7, 6, 2], viewportSize: {width: 1680, height: 950}, rulesetMaker: coeffs => (new RulesetFactory(coeffs)).makeRuleset() }; From 8d38da1c3f6cc279549b8c16a22d2b5c364d4596 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Mon, 29 Oct 2018 11:58:50 -0400 Subject: [PATCH 040/140] Change rules that look for "price" in IDs and classes to emit fuzzy confidences. Also the $ rule. Also break up both "price" rules into separate ones for parent and the actual element so the trainer can come up with optimal coeffs, rather than what I assume is a human guess of .75x difference. Start those new parent coeffs out at as close to .75x as I could. --- src/extraction/fathom/ruleset_factory.js | 49 +++++++++++------------- src/extraction/fathom/trainees.js | 2 +- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index 23baefa..bfbb0cb 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -26,7 +26,9 @@ export default class RulesetFactory { [ this.hasDollarSignCoeff, this.hasPriceInClassNameCoeff, + this.hasPriceInParentClassNameCoeff, this.hasPriceInIDCoeff, + this.hasPriceInParentIDCoeff, this.hasPriceishPatternCoeff, this.isAboveTheFoldImageCoeff, this.isAboveTheFoldPriceCoeff, @@ -66,40 +68,33 @@ export default class RulesetFactory { * Scores fnode with a '$' in its innerText */ hasDollarSign(fnode) { - if (fnode.element.innerText.includes('$')) { - return this.hasDollarSignCoeff; - } - return DEFAULT_SCORE; + return (fnode.element.innerText.includes('$') ? ONEISH : ZEROISH) ** this.hasDollarSignCoeff; + } + + /** Return a confidence of whether "price" is a word within a given string. */ + hasPriceIn(haystack, needle, coeff) { + return (element.id.toLowerCase().includes('price') ? ONEISH : ZEROISH) ** coeff; } /** - * Scores fnode with 'price' in its id or its parent's id + * Scores fnode with 'price' in its id */ hasPriceInID(fnode) { - const id = fnode.element.id; - const parentID = fnode.element.parentElement.id; - if (id.toLowerCase().includes('price')) { - return this.hasPriceInIDCoeff; - } - if (parentID.toLowerCase().includes('price')) { - return 0.75 * this.hasPriceInIDCoeff; - } - return DEFAULT_SCORE; + return this.hasPriceIn(fnode.element.id, 'price', this.hasPriceInIDCoeff); } - /** - * Scores fnode with 'price' in its class name or its parent's class name - */ + hasPriceInParentID(fnode) { + return this.hasPriceIn(fnode.element.parentElement.id, 'price', this.hasPriceInParentIDCoeff); + } + + /** Scores fnode with 'price' in its class name */ hasPriceInClassName(fnode) { - const className = fnode.element.className; - const parentClassName = fnode.element.parentElement.className; - if (className.toLowerCase().includes('price')) { - return this.hasPriceInClassNameCoeff; - } - if (parentClassName.toLowerCase().includes('price')) { - return 0.75 * this.hasPriceInClassNameCoeff; - } - return DEFAULT_SCORE; + return self.hasPriceIn(fnode.element.className, 'price', this.hasPriceInClassNameCoeff); + } + + /** Scores fnode with 'price' in its class name */ + hasPriceInParentClassName(fnode) { + return self.hasPriceIn(fnode.element.parentElement.className, 'price', this.hasPriceInParentClassNameCoeff); } /** @@ -297,8 +292,10 @@ export default class RulesetFactory { rule(type('priceish'), score(fnode => this.isAboveTheFold(fnode, this.isAboveTheFoldPriceCoeff))), // check if the id has "price" in it rule(type('priceish'), score(this.hasPriceInID.bind(this))), + rule(type('priceish'), score(this.hasPriceInParentID.bind(this))), // check if any class names have "price" in them rule(type('priceish'), score(this.hasPriceInClassName.bind(this))), + rule(type('priceish'), score(this.hasPriceInParentClassName.bind(this))), // better score for larger font size rule(type('priceish'), score(this.largerFontSize.bind(this))), // better score based on x-axis proximity to max scoring image element diff --git a/src/extraction/fathom/trainees.js b/src/extraction/fathom/trainees.js index 7ea23f2..e1a1ae2 100644 --- a/src/extraction/fathom/trainees.js +++ b/src/extraction/fathom/trainees.js @@ -17,7 +17,7 @@ import RulesetFactory from './ruleset_factory'; const trainees = new Map(); const commonRuleset = { - coeffs: [7, 1, 18, 19, 2, 20, 4, 7, 6, 2], + coeffs: [7, 1, 1, 18, 13, 19, 2, 20, 4, 7, 6, 2], viewportSize: {width: 1680, height: 950}, rulesetMaker: coeffs => (new RulesetFactory(coeffs)).makeRuleset() }; From 525bd54576552faec4f9fc180947f45a6f027844 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Mon, 29 Oct 2018 14:33:44 -0400 Subject: [PATCH 041/140] Re-express font-size rule as a confidence. Add a trapezoid function, mostly to clamp it to 0..1 before we raise it to the coeff's power. Re-spell largerImage() for consistency. ("Is" is what we've been using for fuzzy-truth values elsewhere, so we adopt it here.) --- src/extraction/fathom/ruleset_factory.js | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index bfbb0cb..5cdd6ef 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -7,7 +7,6 @@ import {dom, out, rule, ruleset, score, type} from 'fathom-web'; // training, replace 'utils' with 'utilsForFrontend' import {ancestors} from 'fathom-web/utilsForFrontend'; -const DEFAULT_BODY_FONT_SIZE = 14; const DEFAULT_SCORE = 1; const TOP_BUFFER = 150; // From: https://github.com/mozilla/fathom-trainees/blob/master/src/trainees.js @@ -34,15 +33,15 @@ export default class RulesetFactory { this.isAboveTheFoldPriceCoeff, this.isNearbyImageXAxisPriceCoeff, this.isNearbyImageYAxisTitleCoeff, - this.largerFontSizeCoeff, - this.largerImageCoeff, + this.bigFontCoeff, + this.bigImageCoeff, ] = coefficients; } /** * Scores fnode in direct proportion to its size */ - largerImage(fnode) { + imageIsBig(fnode) { const domRect = fnode.element.getBoundingClientRect(); const area = domRect.width * domRect.height; @@ -51,17 +50,13 @@ export default class RulesetFactory { // (though we should have distinct penalties for that sort of thing if we // care). More importantly, clamp the upper bound of the score so we don't // overcome other bonuses and penalties. - return trapezoid(area, 80 ** 2, 1000 ** 2) ** this.largerImageCoeff; + return trapezoid(area, 80 ** 2, 1000 ** 2) ** this.bigImageCoeff; } - /** - * Scores fnode in proportion to its font size - */ - largerFontSize(fnode) { + /** Return whether a */ + fontIsBig(fnode) { const size = window.getComputedStyle(fnode.element).fontSize; - // Normalize the multiplier by the default font size - const sizeMultiplier = parseFloat(size, 10) / DEFAULT_BODY_FONT_SIZE; - return sizeMultiplier * this.largerFontSizeCoeff; + return trapezoid(size, 14, 50) ** this.bigFontCoeff; } /** @@ -267,7 +262,7 @@ export default class RulesetFactory { // better score the closer the element is to the top of the page rule(type('imageish'), score(fnode => this.isAboveTheFold(fnode, this.isAboveTheFoldImageCoeff))), // better score for larger images - rule(type('imageish'), score(this.largerImage.bind(this))), + rule(type('imageish'), score(this.imageIsBig.bind(this))), // return image element(s) with max score rule(type('imageish').max(), out('image')), @@ -297,7 +292,7 @@ export default class RulesetFactory { rule(type('priceish'), score(this.hasPriceInClassName.bind(this))), rule(type('priceish'), score(this.hasPriceInParentClassName.bind(this))), // better score for larger font size - rule(type('priceish'), score(this.largerFontSize.bind(this))), + rule(type('priceish'), score(this.fontIsBig.bind(this))), // better score based on x-axis proximity to max scoring image element rule(type('priceish'), score(this.isNearbyImageXAxisPrice.bind(this))), // check if innerText has a priceish pattern From b567dd9feb92bf94a2c659c13463f3390ce2e14f Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Mon, 29 Oct 2018 15:32:24 -0400 Subject: [PATCH 042/140] Rewrite rule that give a bonus to prices near the winning image. Express it in terms of fuzzy truth. Also greatly simplify. I'd like to test whether this does as well or better than the overlap-testing method. In doing so, change getHighestScoringImage() to return its fnode, not its element. --- src/extraction/fathom/ruleset_factory.js | 37 +++++++----------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index 5cdd6ef..e7bc4d7 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -6,6 +6,7 @@ import {dom, out, rule, ruleset, score, type} from 'fathom-web'; // Since the fathom-trainees add-on currently uses a submodule of Fathom, for // training, replace 'utils' with 'utilsForFrontend' import {ancestors} from 'fathom-web/utilsForFrontend'; +import {euclidean} from 'fathom-web/clusters'; const DEFAULT_SCORE = 1; const TOP_BUFFER = 150; @@ -31,7 +32,7 @@ export default class RulesetFactory { this.hasPriceishPatternCoeff, this.isAboveTheFoldImageCoeff, this.isAboveTheFoldPriceCoeff, - this.isNearbyImageXAxisPriceCoeff, + this.isNearImageCoeff, this.isNearbyImageYAxisTitleCoeff, this.bigFontCoeff, this.bigImageCoeff, @@ -105,28 +106,12 @@ export default class RulesetFactory { } /** - * Scores fnode based on its x distance from the highest scoring image element + * Return whether the centerpoint of the element is near that of the highest- + * scoring image. */ - isNearbyImageXAxisPrice(fnode) { - const viewportWidth = window.innerWidth; - const eleDOMRect = fnode.element.getBoundingClientRect(); - const imageElement = this.getHighestScoringImage(fnode); - const imageDOMRect = imageElement.getBoundingClientRect(); - const deltaRight = eleDOMRect.left - imageDOMRect.right; - const deltaLeft = imageDOMRect.left - eleDOMRect.right; - // True if element is completely to the right or left of the image element - const noOverlap = (deltaRight > 0 || deltaLeft > 0); - let deltaX; - if (noOverlap) { - if (deltaRight > 0) { - deltaX = deltaRight; - } else { - deltaX = deltaLeft; - } - // Give a higher score the closer it is to the image, normalized by viewportWidth - return (viewportWidth / deltaX) * this.isNearbyImageXAxisPriceCoeff; - } - return DEFAULT_SCORE; + isNearImage(fnode) { + const image = this.getHighestScoringImage(fnode); + return trapezoid(euclidean(fnode, image), 1000, 0) ** this.isNearImageCoeff; } /** @@ -137,7 +122,7 @@ export default class RulesetFactory { * bottom" one. */ isNearImageTopOrBottom(fnode) { - const image = this.getHighestScoringImage(fnode); + const image = this.getHighestScoringImage(fnode).element; const imageRect = image.getBoundingClientRect(); const nodeRect = fnode.element.getBoundingClientRect(); @@ -222,7 +207,7 @@ export default class RulesetFactory { isNearbyImageYAxisPrice(fnode) { const element = fnode.element; const DOMRect = element.getBoundingClientRect(); - const imageElement = this.getHighestScoringImage(fnode); + const imageElement = this.getHighestScoringImage(fnode).element; const imageDOMRect = imageElement.getBoundingClientRect(); if (DOMRect.top >= (imageDOMRect.top - TOP_BUFFER) && DOMRect.bottom <= imageDOMRect.bottom) { @@ -294,7 +279,7 @@ export default class RulesetFactory { // better score for larger font size rule(type('priceish'), score(this.fontIsBig.bind(this))), // better score based on x-axis proximity to max scoring image element - rule(type('priceish'), score(this.isNearbyImageXAxisPrice.bind(this))), + rule(type('priceish'), score(this.isNearImage.bind(this))), // check if innerText has a priceish pattern rule(type('priceish'), score(this.hasPriceishPattern.bind(this))), // return price element(s) with max score @@ -317,7 +302,7 @@ export default class RulesetFactory { } getHighestScoringImage(fnode) { - return fnode._ruleset.get('image')[0].element; // eslint-disable-line no-underscore-dangle + return fnode._ruleset.get('image')[0]; // eslint-disable-line no-underscore-dangle } } From 90423dac2188e357d5d2e5107b61b8c9430c80dc Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Mon, 29 Oct 2018 15:48:52 -0400 Subject: [PATCH 043/140] Express hasPriceishPattern as a fuzzy truth. Also don't require the price to come at the end, in service of the "US $5.00 plus free shipping" use case which I misread "'US $5.00' on eBay" as. Let's see how that goes. --- src/extraction/fathom/ruleset_factory.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index e7bc4d7..2948125 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -139,21 +139,17 @@ export default class RulesetFactory { } /** - * Scores fnode whose innerText matches a priceish RegExp pattern + * Return whether the fnode's innertext contains a dollars-and-cents number. */ hasPriceishPattern(fnode) { const text = fnode.element.innerText; /** * With an optional '$' that doesn't necessarily have to be at the beginning * of the string (ex: 'US $5.00' on Ebay), matches any number of digits before - * a decimal point and exactly two after, where the two digits after the decimal point - * are at the end of the string + * a decimal point and exactly two after. */ - const regExp = /\$?\d+\.\d{2}$/; - if (regExp.test(text)) { - return this.hasPriceishPatternCoeff; - } - return DEFAULT_SCORE; + const regExp = /\$?\d+\.\d{2}(?![0-9])/; + return (regExp.test(text) ? ONEISH : ZEROISH) ** this.hasPriceishPatternCoeff; } /** From 74658e9210d0429fb715b25e7339b400c6061bc1 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Mon, 29 Oct 2018 16:41:38 -0400 Subject: [PATCH 044/140] Fix the bugs that immediately kept the trainer from training. --- src/extraction/fathom/ruleset_factory.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index 2948125..a0f7087 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -56,7 +56,7 @@ export default class RulesetFactory { /** Return whether a */ fontIsBig(fnode) { - const size = window.getComputedStyle(fnode.element).fontSize; + const size = parseInt(getComputedStyle(fnode.element).fontSize, 10); return trapezoid(size, 14, 50) ** this.bigFontCoeff; } @@ -69,7 +69,7 @@ export default class RulesetFactory { /** Return a confidence of whether "price" is a word within a given string. */ hasPriceIn(haystack, needle, coeff) { - return (element.id.toLowerCase().includes('price') ? ONEISH : ZEROISH) ** coeff; + return (haystack.toLowerCase().includes(needle) ? ONEISH : ZEROISH) ** coeff; } /** @@ -85,12 +85,12 @@ export default class RulesetFactory { /** Scores fnode with 'price' in its class name */ hasPriceInClassName(fnode) { - return self.hasPriceIn(fnode.element.className, 'price', this.hasPriceInClassNameCoeff); + return this.hasPriceIn(fnode.element.className, 'price', this.hasPriceInClassNameCoeff); } /** Scores fnode with 'price' in its class name */ hasPriceInParentClassName(fnode) { - return self.hasPriceIn(fnode.element.parentElement.className, 'price', this.hasPriceInParentClassNameCoeff); + return this.hasPriceIn(fnode.element.parentElement.className, 'price', this.hasPriceInParentClassNameCoeff); } /** @@ -260,12 +260,14 @@ export default class RulesetFactory { /** * Price rules */ + // 72% by itself, at [4, 4, 4, 4...]!: // consider all eligible span and h2 elements rule(dom('span, h2').when(this.isEligiblePrice.bind(this)), type('priceish')), // check if the element has a '$' in its innerText rule(type('priceish'), score(this.hasDollarSign.bind(this))), // better score the closer the element is to the top of the page rule(type('priceish'), score(fnode => this.isAboveTheFold(fnode, this.isAboveTheFoldPriceCoeff))), + // check if the id has "price" in it rule(type('priceish'), score(this.hasPriceInID.bind(this))), rule(type('priceish'), score(this.hasPriceInParentID.bind(this))), From c52af18eaa61abcb09547557003b1e577ca6b434 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Tue, 30 Oct 2018 09:48:11 -0400 Subject: [PATCH 045/140] Remove a now-unused constant and an out-of-date comment. --- src/extraction/fathom/ruleset_factory.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index a0f7087..1902028 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -3,12 +3,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import {dom, out, rule, ruleset, score, type} from 'fathom-web'; -// Since the fathom-trainees add-on currently uses a submodule of Fathom, for -// training, replace 'utils' with 'utilsForFrontend' import {ancestors} from 'fathom-web/utilsForFrontend'; import {euclidean} from 'fathom-web/clusters'; -const DEFAULT_SCORE = 1; const TOP_BUFFER = 150; // From: https://github.com/mozilla/fathom-trainees/blob/master/src/trainees.js const ZEROISH = 0.08; From 737ca676193d2c62efa595eaca803142e20c0b5b Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Tue, 30 Oct 2018 11:11:21 -0400 Subject: [PATCH 046/140] Add new coeffs to get to 100% on the training set! Price, title, image: all 100%! --- src/extraction/fathom/trainees.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extraction/fathom/trainees.js b/src/extraction/fathom/trainees.js index e1a1ae2..8ac424d 100644 --- a/src/extraction/fathom/trainees.js +++ b/src/extraction/fathom/trainees.js @@ -17,7 +17,7 @@ import RulesetFactory from './ruleset_factory'; const trainees = new Map(); const commonRuleset = { - coeffs: [7, 1, 1, 18, 13, 19, 2, 20, 4, 7, 6, 2], + coeffs: [2, 7, -2, 5, -4, 3, 1, -17, 4, 5, 15, 10], viewportSize: {width: 1680, height: 950}, rulesetMaker: coeffs => (new RulesetFactory(coeffs)).makeRuleset() }; From 47bbc7a01c7dd70ed9b38f198f6fe7fe3b257966 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Wed, 14 Nov 2018 15:03:14 -0500 Subject: [PATCH 047/140] Rename hasPriceIn, since it doesn't actually have "price" hard-coded in anymore. --- src/extraction/fathom/ruleset_factory.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index 1902028..f5f4b76 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -65,7 +65,7 @@ export default class RulesetFactory { } /** Return a confidence of whether "price" is a word within a given string. */ - hasPriceIn(haystack, needle, coeff) { + contains(haystack, needle, coeff) { return (haystack.toLowerCase().includes(needle) ? ONEISH : ZEROISH) ** coeff; } @@ -73,21 +73,21 @@ export default class RulesetFactory { * Scores fnode with 'price' in its id */ hasPriceInID(fnode) { - return this.hasPriceIn(fnode.element.id, 'price', this.hasPriceInIDCoeff); + return this.contains(fnode.element.id, 'price', this.hasPriceInIDCoeff); } hasPriceInParentID(fnode) { - return this.hasPriceIn(fnode.element.parentElement.id, 'price', this.hasPriceInParentIDCoeff); + return this.contains(fnode.element.parentElement.id, 'price', this.hasPriceInParentIDCoeff); } /** Scores fnode with 'price' in its class name */ hasPriceInClassName(fnode) { - return this.hasPriceIn(fnode.element.className, 'price', this.hasPriceInClassNameCoeff); + return this.contains(fnode.element.className, 'price', this.hasPriceInClassNameCoeff); } /** Scores fnode with 'price' in its class name */ hasPriceInParentClassName(fnode) { - return this.hasPriceIn(fnode.element.parentElement.className, 'price', this.hasPriceInParentClassNameCoeff); + return this.contains(fnode.element.parentElement.className, 'price', this.hasPriceInParentClassNameCoeff); } /** From 307fa3d425c2427aedd48788f64cc1e20bb21903 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Wed, 14 Nov 2018 15:04:11 -0500 Subject: [PATCH 048/140] Consider divs with background images as well as img tags. One of those showed up in 4.html. Rename imageIsBig() because we're calling it on things other than images now, and it was always general anyway. --- src/extraction/fathom/ruleset_factory.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index f5f4b76..c89fb44 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -39,7 +39,7 @@ export default class RulesetFactory { /** * Scores fnode in direct proportion to its size */ - imageIsBig(fnode) { + nodeIsBig(fnode) { const domRect = fnode.element.getBoundingClientRect(); const area = domRect.width * domRect.height; @@ -226,6 +226,11 @@ export default class RulesetFactory { return true; } + hasBackgroundImage(fnode) { + const bgImage = getComputedStyle(fnode.element)['background-image']; + return !!bgImage && bgImage !== 'none'; + } + /** * Using coefficients passed into the constructor method, returns a weighted * ruleset used to score elements in an HTML document. @@ -237,10 +242,13 @@ export default class RulesetFactory { */ // consider all visible img elements rule(dom('img').when(this.isVisible.bind(this)), type('imageish')), + // and divs, which sometimes have CSS background-images + // TODO: Consider a bonus for tags. + rule(dom('div').when((fnode) => this.isVisible(fnode) && this.hasBackgroundImage(fnode)), type('imageish')), // better score the closer the element is to the top of the page rule(type('imageish'), score(fnode => this.isAboveTheFold(fnode, this.isAboveTheFoldImageCoeff))), // better score for larger images - rule(type('imageish'), score(this.imageIsBig.bind(this))), + rule(type('imageish'), score(this.nodeIsBig.bind(this))), // return image element(s) with max score rule(type('imageish').max(), out('image')), From e1f447970b970da39ab668cac9a58ae8243360a9 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Wed, 14 Nov 2018 16:45:07 -0500 Subject: [PATCH 049/140] Typos --- src/extraction/fathom/ruleset_factory.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index c89fb44..b1c96b7 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -115,7 +115,7 @@ export default class RulesetFactory { * Return whether the potential title is near the top or bottom of the * highest-scoring image. * - * This is a makeshift ORing 2 signals: a "near the top" and a "near the + * This is a makeshift ORing of 2 signals: a "near the top" and a "near the * bottom" one. */ isNearImageTopOrBottom(fnode) { @@ -244,7 +244,7 @@ export default class RulesetFactory { rule(dom('img').when(this.isVisible.bind(this)), type('imageish')), // and divs, which sometimes have CSS background-images // TODO: Consider a bonus for tags. - rule(dom('div').when((fnode) => this.isVisible(fnode) && this.hasBackgroundImage(fnode)), type('imageish')), + rule(dom('div').when(fnode => this.isVisible(fnode) && this.hasBackgroundImage(fnode)), type('imageish')), // better score the closer the element is to the top of the page rule(type('imageish'), score(fnode => this.isAboveTheFold(fnode, this.isAboveTheFoldImageCoeff))), // better score for larger images @@ -253,8 +253,8 @@ export default class RulesetFactory { rule(type('imageish').max(), out('image')), /** - * Title rules - */ + * Title rules + */ // consider all eligible h1 elements rule(dom('h1').when(this.isEligibleTitle.bind(this)), type('titleish')), // better score based on y-axis proximity to max scoring image element @@ -263,8 +263,8 @@ export default class RulesetFactory { rule(type('titleish').max(), out('title')), /** - * Price rules - */ + * Price rules + */ // 72% by itself, at [4, 4, 4, 4...]!: // consider all eligible span and h2 elements rule(dom('span, h2').when(this.isEligiblePrice.bind(this)), type('priceish')), From f0eba0dc6775492e066c707025939b157d9269a5 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Wed, 14 Nov 2018 16:47:13 -0500 Subject: [PATCH 050/140] There's no need to say "node". All scoring functions take nodes. --- src/extraction/fathom/ruleset_factory.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index b1c96b7..1235afb 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -39,7 +39,7 @@ export default class RulesetFactory { /** * Scores fnode in direct proportion to its size */ - nodeIsBig(fnode) { + isBig(fnode) { const domRect = fnode.element.getBoundingClientRect(); const area = domRect.width * domRect.height; @@ -248,7 +248,7 @@ export default class RulesetFactory { // better score the closer the element is to the top of the page rule(type('imageish'), score(fnode => this.isAboveTheFold(fnode, this.isAboveTheFoldImageCoeff))), // better score for larger images - rule(type('imageish'), score(this.nodeIsBig.bind(this))), + rule(type('imageish'), score(this.isBig.bind(this))), // return image element(s) with max score rule(type('imageish').max(), out('image')), From 3fc58569fc0efbf37de098f11760484666ef5bcd Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Wed, 14 Nov 2018 16:49:02 -0500 Subject: [PATCH 051/140] Add a rule to punish extreme aspect ratios and another to punish background images. This gets us to 100% on the training corpus of 75. --- src/extraction/fathom/ruleset_factory.js | 25 ++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index 1235afb..a294d15 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -33,6 +33,8 @@ export default class RulesetFactory { this.isNearbyImageYAxisTitleCoeff, this.bigFontCoeff, this.bigImageCoeff, + this.extremeAspectCoeff, + this.backgroundIdImageCoeff ] = coefficients; } @@ -64,9 +66,14 @@ export default class RulesetFactory { return (fnode.element.innerText.includes('$') ? ONEISH : ZEROISH) ** this.hasDollarSignCoeff; } - /** Return a confidence of whether "price" is a word within a given string. */ + /** Return whether some substring is within a given string, case insensitively. */ + doesContain(haystack, needle) { + return haystack.toLowerCase().includes(needle); + } + + /** Return a weighted confidence of whether a substring is within a given string, case insensitively. */ contains(haystack, needle, coeff) { - return (haystack.toLowerCase().includes(needle) ? ONEISH : ZEROISH) ** coeff; + return (this.doesContain(haystack, needle) ? ONEISH : ZEROISH) ** coeff; } /** @@ -231,6 +238,15 @@ export default class RulesetFactory { return !!bgImage && bgImage !== 'none'; } + /** + * Return the aspect ratio of a fnode's client rect, with horizontal and + * vertical rearranged so it's always >=1. + */ + aspectRatio(element) { + const rect = element.getBoundingClientRect(); + return (rect.width > rect.height) ? (rect.width / rect.height) : (rect.height / rect.width); + } + /** * Using coefficients passed into the constructor method, returns a weighted * ruleset used to score elements in an HTML document. @@ -249,6 +265,11 @@ export default class RulesetFactory { rule(type('imageish'), score(fnode => this.isAboveTheFold(fnode, this.isAboveTheFoldImageCoeff))), // better score for larger images rule(type('imageish'), score(this.isBig.bind(this))), + // punishment for extreme aspect ratios, to filter out banners or nav elements + rule(type('imageish'), score(fnode => trapezoid(this.aspectRatio(fnode.element), 10, 5) ** this.extremeAspectCoeff)), + // no background images, even ones that have reasonable aspect ratios + // TODO: If necessary, also look at parents. I've seen them say "background" in their IDs as well. + rule(type('imageish'), score(fnode => (this.doesContain(fnode.element.id, 'background') ? (ZEROISH ** this.backgroundIdImageCoeff) : 1))), // return image element(s) with max score rule(type('imageish').max(), out('image')), From dd16bf0bcfbafd3b1a678119cbdb249e0351e9b1 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Wed, 14 Nov 2018 16:49:33 -0500 Subject: [PATCH 052/140] Hard-code a height for aboveTheFold so a user's different window size doesn't make a different answer come out. --- src/extraction/fathom/ruleset_factory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index a294d15..ad5d5f9 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -101,7 +101,7 @@ export default class RulesetFactory { * Scores fnode by its vertical location relative to the fold */ isAboveTheFold(fnode, featureCoeff) { - const viewportHeight = window.innerHeight; + const viewportHeight = 950; const imageTop = fnode.element.getBoundingClientRect().top; // Stop giving additional bonus for anything closer than 200px to the top From 418a9cf470027abdb6a057fac012a9eab169ab92 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Wed, 14 Nov 2018 16:50:12 -0500 Subject: [PATCH 053/140] Make the image trainee train only the image-affecting coeffs, for speed. --- src/extraction/fathom/trainees.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/extraction/fathom/trainees.js b/src/extraction/fathom/trainees.js index 8ac424d..9ecd7cb 100644 --- a/src/extraction/fathom/trainees.js +++ b/src/extraction/fathom/trainees.js @@ -15,14 +15,20 @@ import RulesetFactory from './ruleset_factory'; * UI, from which you can kick off a training run. */ const trainees = new Map(); +const viewportSize = {width: 1680, height: 950}; const commonRuleset = { coeffs: [2, 7, -2, 5, -4, 3, 1, -17, 4, 5, 15, 10], - viewportSize: {width: 1680, height: 950}, + viewportSize, rulesetMaker: coeffs => (new RulesetFactory(coeffs)).makeRuleset() }; -trainees.set('image', commonRuleset); +trainees.set('image', { + coeffs: [5, 9, 3, 4], // [5, 9, 3, 5] gets 98.7% training + viewportSize, + // Using Nan as a don't-care value: + rulesetMaker: coeffs => (new RulesetFactory([NaN, NaN, NaN, NaN, NaN, NaN, coeffs[0], NaN, NaN, NaN, NaN, coeffs[1], coeffs[2], coeffs[3]])).makeRuleset() +}); trainees.set('title', commonRuleset); trainees.set('price', commonRuleset); From 34868795054ddc3ac5f1d37b96d271e606b06d8d Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Thu, 15 Nov 2018 16:51:34 -0500 Subject: [PATCH 054/140] Move tuned image coeffs into master vector. --- src/extraction/fathom/trainees.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/extraction/fathom/trainees.js b/src/extraction/fathom/trainees.js index 9ecd7cb..85b6477 100644 --- a/src/extraction/fathom/trainees.js +++ b/src/extraction/fathom/trainees.js @@ -18,13 +18,13 @@ const trainees = new Map(); const viewportSize = {width: 1680, height: 950}; const commonRuleset = { - coeffs: [2, 7, -2, 5, -4, 3, 1, -17, 4, 5, 15, 10], + coeffs: [2, 7, -2, 5, -4, 3, 5, -17, 4, 5, 15, 9, 3, 4], viewportSize, rulesetMaker: coeffs => (new RulesetFactory(coeffs)).makeRuleset() }; trainees.set('image', { - coeffs: [5, 9, 3, 4], // [5, 9, 3, 5] gets 98.7% training + coeffs: [5, 9, 3, 4], viewportSize, // Using Nan as a don't-care value: rulesetMaker: coeffs => (new RulesetFactory([NaN, NaN, NaN, NaN, NaN, NaN, coeffs[0], NaN, NaN, NaN, NaN, coeffs[1], coeffs[2], coeffs[3]])).makeRuleset() From 9217d835b869304dcab544cb5478142211c2b493 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Thu, 15 Nov 2018 16:51:51 -0500 Subject: [PATCH 055/140] Make a more efficient training vector for price. --- src/extraction/fathom/trainees.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/extraction/fathom/trainees.js b/src/extraction/fathom/trainees.js index 85b6477..eefee15 100644 --- a/src/extraction/fathom/trainees.js +++ b/src/extraction/fathom/trainees.js @@ -30,6 +30,10 @@ trainees.set('image', { rulesetMaker: coeffs => (new RulesetFactory([NaN, NaN, NaN, NaN, NaN, NaN, coeffs[0], NaN, NaN, NaN, NaN, coeffs[1], coeffs[2], coeffs[3]])).makeRuleset() }); trainees.set('title', commonRuleset); -trainees.set('price', commonRuleset); +trainees.set('price', { + coeffs: [2, 7, -2, 5, -4, 3, -17, 4, 15], + viewportSize, + rulesetMaker: coeffs => (new RulesetFactory([coeffs[0], coeffs[1], coeffs[2], coeffs[3], coeffs[4], coeffs[5], commonRuleset.coeffs[6], coeffs[6], coeffs[7], commonRuleset.coeffs[9], coeffs[8], commonRuleset.coeffs[11], commonRuleset.coeffs[12], commonRuleset.coeffs[13]])).makeRuleset() +}); export default trainees; From 89da723378cff98e439ea982d77c2cb974a7be35 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Thu, 15 Nov 2018 16:54:31 -0500 Subject: [PATCH 056/140] Improve price coeffs: 100% on 12-16. --- src/extraction/fathom/trainees.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extraction/fathom/trainees.js b/src/extraction/fathom/trainees.js index eefee15..a0415e3 100644 --- a/src/extraction/fathom/trainees.js +++ b/src/extraction/fathom/trainees.js @@ -31,7 +31,7 @@ trainees.set('image', { }); trainees.set('title', commonRuleset); trainees.set('price', { - coeffs: [2, 7, -2, 5, -4, 3, -17, 4, 15], + coeffs: [2, 7, -2, 6, -3, 5, -17, 4, 16], viewportSize, rulesetMaker: coeffs => (new RulesetFactory([coeffs[0], coeffs[1], coeffs[2], coeffs[3], coeffs[4], coeffs[5], commonRuleset.coeffs[6], coeffs[6], coeffs[7], commonRuleset.coeffs[9], coeffs[8], commonRuleset.coeffs[11], commonRuleset.coeffs[12], commonRuleset.coeffs[13]])).makeRuleset() }); From 0c888cb6366a0a3ff28d885da0fef8614b44428e Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Thu, 15 Nov 2018 16:55:32 -0500 Subject: [PATCH 057/140] Improve price coeffs. 93.3% on 12-16, 1-10. 92% on 1-25. --- src/extraction/fathom/trainees.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extraction/fathom/trainees.js b/src/extraction/fathom/trainees.js index a0415e3..4c8a1ad 100644 --- a/src/extraction/fathom/trainees.js +++ b/src/extraction/fathom/trainees.js @@ -31,7 +31,7 @@ trainees.set('image', { }); trainees.set('title', commonRuleset); trainees.set('price', { - coeffs: [2, 7, -2, 6, -3, 5, -17, 4, 16], + coeffs: [2, 7, -1, 5, -3, 3, -19, 4, 15], viewportSize, rulesetMaker: coeffs => (new RulesetFactory([coeffs[0], coeffs[1], coeffs[2], coeffs[3], coeffs[4], coeffs[5], commonRuleset.coeffs[6], coeffs[6], coeffs[7], commonRuleset.coeffs[9], coeffs[8], commonRuleset.coeffs[11], commonRuleset.coeffs[12], commonRuleset.coeffs[13]])).makeRuleset() }); From 1735fe385aa33d0f9b6c5f28dddc1e2177a8c669 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Thu, 15 Nov 2018 17:29:21 -0500 Subject: [PATCH 058/140] Improve price coeffs: 98.7% on all current training samples (1-25 and all named samples). --- src/extraction/fathom/trainees.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extraction/fathom/trainees.js b/src/extraction/fathom/trainees.js index 4c8a1ad..20a0e51 100644 --- a/src/extraction/fathom/trainees.js +++ b/src/extraction/fathom/trainees.js @@ -31,7 +31,7 @@ trainees.set('image', { }); trainees.set('title', commonRuleset); trainees.set('price', { - coeffs: [2, 7, -1, 5, -3, 3, -19, 4, 15], + coeffs: [3, 7, -1, 8, -2, 4, -19, 4, 14], viewportSize, rulesetMaker: coeffs => (new RulesetFactory([coeffs[0], coeffs[1], coeffs[2], coeffs[3], coeffs[4], coeffs[5], commonRuleset.coeffs[6], coeffs[6], coeffs[7], commonRuleset.coeffs[9], coeffs[8], commonRuleset.coeffs[11], commonRuleset.coeffs[12], commonRuleset.coeffs[13]])).makeRuleset() }); From 82709cfde8af1307b15474b421ca310ad9c8e326 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Fri, 16 Nov 2018 10:57:40 -0500 Subject: [PATCH 059/140] Copy tuned price coeffs to master vector. --- src/extraction/fathom/trainees.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extraction/fathom/trainees.js b/src/extraction/fathom/trainees.js index 20a0e51..cad4514 100644 --- a/src/extraction/fathom/trainees.js +++ b/src/extraction/fathom/trainees.js @@ -18,7 +18,7 @@ const trainees = new Map(); const viewportSize = {width: 1680, height: 950}; const commonRuleset = { - coeffs: [2, 7, -2, 5, -4, 3, 5, -17, 4, 5, 15, 9, 3, 4], + coeffs: [3, 7, -1, 8, -2, 4, 5, -19, 4, 5, -19, 9, 3, 4], viewportSize, rulesetMaker: coeffs => (new RulesetFactory(coeffs)).makeRuleset() }; From ac1d3040f72341a01288bf9eec73be2d483d2f03 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Fri, 16 Nov 2018 15:28:03 -0500 Subject: [PATCH 060/140] Put the glue code back how I found it, and move the coeffs back into the JSON file. Order the coeffs alphabetically in the ruleset factory so getCoeffsInOrder() works once more. Upgrade to Fathom 2.8 so FathomFox's good/back-clicking features work when you symlink from a fathom-trainees fork to here. (Yarn looks in pricewise, not in fathom-trainees, for a copy of fathom.) --- package.json | 2 +- src/extraction/fathom/coefficients.json | 22 ++++++----- src/extraction/fathom/ruleset_factory.js | 14 +++---- src/extraction/fathom/trainees.js | 47 ++++++++++++++++-------- 4 files changed, 53 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index 2292638..bc08783 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "dependencies": { "autobind-decorator": "2.1.0", "dinero.js": "1.4.0", - "fathom-web": "2.3.0", + "fathom-web": "2.8.0", "lodash.maxby": "4.6.0", "lodash.minby": "4.6.0", "lodash.orderby": "^4.6.0", diff --git a/src/extraction/fathom/coefficients.json b/src/extraction/fathom/coefficients.json index 7a70565..3360bc0 100644 --- a/src/extraction/fathom/coefficients.json +++ b/src/extraction/fathom/coefficients.json @@ -1,12 +1,16 @@ { - "hasDollarSignCoeff": 8, - "hasPriceInClassNameCoeff": 2, - "hasPriceInIDCoeff": 17, - "hasPriceishPatternCoeff": 15, - "isAboveTheFoldImageCoeff": 13, - "isAboveTheFoldPriceCoeff": 33, - "isNearbyImageXAxisPriceCoeff": 5, + "backgroundIdImageCoeff": 4, + "bigFontCoeff": -19, + "bigImageCoeff": 9, + "extremeAspectCoeff": 3, + "hasDollarSignCoeff": 3, + "hasPriceInClassNameCoeff": 7, + "hasPriceInIDCoeff": 8, + "hasPriceInParentClassNameCoeff": -1, + "hasPriceInParentIDCoeff": -2, + "hasPriceishPatternCoeff": 4, + "isAboveTheFoldImageCoeff": 5, + "isAboveTheFoldPriceCoeff": -19, "isNearbyImageYAxisTitleCoeff": 5, - "largerFontSizeCoeff": 7, - "largerImageCoeff": 2 + "isNearImageCoeff": 4 } diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index ad5d5f9..8d9fdfa 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -21,20 +21,20 @@ export default class RulesetFactory { */ constructor(coefficients) { [ + this.backgroundIdImageCoeff, + this.bigFontCoeff, + this.bigImageCoeff, + this.extremeAspectCoeff, this.hasDollarSignCoeff, this.hasPriceInClassNameCoeff, - this.hasPriceInParentClassNameCoeff, this.hasPriceInIDCoeff, + this.hasPriceInParentClassNameCoeff, this.hasPriceInParentIDCoeff, this.hasPriceishPatternCoeff, this.isAboveTheFoldImageCoeff, this.isAboveTheFoldPriceCoeff, - this.isNearImageCoeff, this.isNearbyImageYAxisTitleCoeff, - this.bigFontCoeff, - this.bigImageCoeff, - this.extremeAspectCoeff, - this.backgroundIdImageCoeff + this.isNearImageCoeff ] = coefficients; } @@ -53,7 +53,7 @@ export default class RulesetFactory { return trapezoid(area, 80 ** 2, 1000 ** 2) ** this.bigImageCoeff; } - /** Return whether a */ + /** Return whether the computed font size of an element is big. */ fontIsBig(fnode) { const size = parseInt(getComputedStyle(fnode.element).fontSize, 10); return trapezoid(size, 14, 50) ** this.bigFontCoeff; diff --git a/src/extraction/fathom/trainees.js b/src/extraction/fathom/trainees.js index cad4514..dace896 100644 --- a/src/extraction/fathom/trainees.js +++ b/src/extraction/fathom/trainees.js @@ -1,11 +1,16 @@ -import {ruleset, rule, dom, type, score, out} from 'fathom-web'; -import {ancestors} from 'fathom-web/utilsForFrontend'; +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* eslint-disable import/no-unresolved */ +import defaultCoefficients from './coefficients.json'; import RulesetFactory from './ruleset_factory'; +// Array of numbers corresponding to the coefficients in order +const coeffs = RulesetFactory.getCoeffsInOrder(defaultCoefficients); /** - * Rulesets to train. + * Rulesets to train using Fathom. * * More mechanically, a map of names to {coeffs, rulesetMaker} objects. * rulesetMaker is a function that takes an Array of coefficients and returns a @@ -13,27 +18,39 @@ import RulesetFactory from './ruleset_factory'; * for a ruleset but can also be some more widely flung ones that you want to * start the trainer from. The rulesets you specify here show up in the Train * UI, from which you can kick off a training run. + * + * How to train: + * 1. Fork the `mozilla/fathom-trainees` repo, + * 2. In the `fathom-trainees` add-on, copy `src/extraction/fathom` to the + * `./src` folder. + * * Note: You will have to replace 'utils' with 'utilsForFrontend' on the + * import in `ruleset_factory.js`. See that file for more information. + * 3. Follow instructions at: https://github.com/erikrose/fathom-fox#the-trainer. + * + * Notes: + * - The FathomFox Trainer assumes that the value of your corpus' `data-fathom` + * attribute is the same as the `out`-ed string. Example: An element tagged with + * `data-fathom="image"` will map to `rule(..., out("image"))`. + * - The Trainer assumes that the name of the ruleset and the out-rule of interest + * are the same. Therefore, if a ruleset contains more than one out-rule, + * each `out`-ed feature must have its own key in the `trainees` map. You can + * select which feature to train from the dropdown menu on FathomFox's Trainer page. + * - I would not recommend using the Corpus Collector to build up a training set, + * because you can only batch freeze original pages, meaning tagged pages would be + * re-freezed, and there are non-obvious side effects in the diff (an issue with + * the freeze-dried library Fathom uses). */ const trainees = new Map(); const viewportSize = {width: 1680, height: 950}; const commonRuleset = { - coeffs: [3, 7, -1, 8, -2, 4, 5, -19, 4, 5, -19, 9, 3, 4], + coeffs, viewportSize, rulesetMaker: coeffs => (new RulesetFactory(coeffs)).makeRuleset() }; -trainees.set('image', { - coeffs: [5, 9, 3, 4], - viewportSize, - // Using Nan as a don't-care value: - rulesetMaker: coeffs => (new RulesetFactory([NaN, NaN, NaN, NaN, NaN, NaN, coeffs[0], NaN, NaN, NaN, NaN, coeffs[1], coeffs[2], coeffs[3]])).makeRuleset() -}); +trainees.set('image', commonRuleset); trainees.set('title', commonRuleset); -trainees.set('price', { - coeffs: [3, 7, -1, 8, -2, 4, -19, 4, 14], - viewportSize, - rulesetMaker: coeffs => (new RulesetFactory([coeffs[0], coeffs[1], coeffs[2], coeffs[3], coeffs[4], coeffs[5], commonRuleset.coeffs[6], coeffs[6], coeffs[7], commonRuleset.coeffs[9], coeffs[8], commonRuleset.coeffs[11], commonRuleset.coeffs[12], commonRuleset.coeffs[13]])).makeRuleset() -}); +trainees.set('price', commonRuleset); export default trainees; From ba89ed4fd54e27d113d5f08451710b7ffc5b34bc Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Fri, 16 Nov 2018 17:03:02 -0500 Subject: [PATCH 061/140] Fix a mistranscribed coefficient. This brings our testing accuracy to 92%. I think I trained on one vector (to get the 92% one) but then mistranscribed it into the master vector before I did the testing run. So it should be a legitimate, not-cheating 92%. --- src/extraction/fathom/coefficients.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extraction/fathom/coefficients.json b/src/extraction/fathom/coefficients.json index 3360bc0..2d1ab7e 100644 --- a/src/extraction/fathom/coefficients.json +++ b/src/extraction/fathom/coefficients.json @@ -1,6 +1,6 @@ { "backgroundIdImageCoeff": 4, - "bigFontCoeff": -19, + "bigFontCoeff": 14, "bigImageCoeff": 9, "extremeAspectCoeff": 3, "hasDollarSignCoeff": 3, From fd6b04302c33511028cb72e193c65f1985bfc807 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Fri, 16 Nov 2018 17:34:29 -0500 Subject: [PATCH 062/140] Make linter happy. --- src/extraction/fathom/ruleset_factory.js | 44 ++++++++++++++---------- src/extraction/fathom/trainees.js | 6 ++-- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index 8d9fdfa..d94637e 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -34,7 +34,7 @@ export default class RulesetFactory { this.isAboveTheFoldImageCoeff, this.isAboveTheFoldPriceCoeff, this.isNearbyImageYAxisTitleCoeff, - this.isNearImageCoeff + this.isNearImageCoeff, ] = coefficients; } @@ -71,7 +71,9 @@ export default class RulesetFactory { return haystack.toLowerCase().includes(needle); } - /** Return a weighted confidence of whether a substring is within a given string, case insensitively. */ + /** Return a weighted confidence of whether a substring is within a given + * string, case insensitively. + */ contains(haystack, needle, coeff) { return (this.doesContain(haystack, needle) ? ONEISH : ZEROISH) ** coeff; } @@ -266,9 +268,11 @@ export default class RulesetFactory { // better score for larger images rule(type('imageish'), score(this.isBig.bind(this))), // punishment for extreme aspect ratios, to filter out banners or nav elements - rule(type('imageish'), score(fnode => trapezoid(this.aspectRatio(fnode.element), 10, 5) ** this.extremeAspectCoeff)), + rule(type('imageish'), score(fnode => trapezoid(this.aspectRatio(fnode.element), 10, 5) + ** this.extremeAspectCoeff)), // no background images, even ones that have reasonable aspect ratios - // TODO: If necessary, also look at parents. I've seen them say "background" in their IDs as well. + // TODO: If necessary, also look at parents. I've seen them say + // "background" in their IDs as well. rule(type('imageish'), score(fnode => (this.doesContain(fnode.element.id, 'background') ? (ZEROISH ** this.backgroundIdImageCoeff) : 1))), // return image element(s) with max score rule(type('imageish').max(), out('image')), @@ -339,20 +343,22 @@ export default class RulesetFactory { * to the right, use a zeroAt greater than oneAt. */ function trapezoid(number, zeroAt, oneAt) { - const isRising = zeroAt < oneAt; - if (isRising) { - if (number <= zeroAt) { - return ZEROISH; - } else if (number >= oneAt) { - return ONEISH; - } - } else { - if (number >= zeroAt) { - return ZEROISH; - } else if (number <= oneAt) { - return ONEISH; - } + const isRising = zeroAt < oneAt; + if (isRising) { + if (number <= zeroAt) { + return ZEROISH; + } + if (number >= oneAt) { + return ONEISH; } - const slope = (ONEISH - ZEROISH) / (oneAt - zeroAt); - return slope * (number - zeroAt) + ZEROISH; + } else { + if (number >= zeroAt) { + return ZEROISH; + } + if (number <= oneAt) { + return ONEISH; + } + } + const slope = (ONEISH - ZEROISH) / (oneAt - zeroAt); + return slope * (number - zeroAt) + ZEROISH; } diff --git a/src/extraction/fathom/trainees.js b/src/extraction/fathom/trainees.js index dace896..530d13e 100644 --- a/src/extraction/fathom/trainees.js +++ b/src/extraction/fathom/trainees.js @@ -44,9 +44,9 @@ const trainees = new Map(); const viewportSize = {width: 1680, height: 950}; const commonRuleset = { - coeffs, - viewportSize, - rulesetMaker: coeffs => (new RulesetFactory(coeffs)).makeRuleset() + coeffs, + viewportSize, + rulesetMaker: coefficients => (new RulesetFactory(coefficients)).makeRuleset(), }; trainees.set('image', commonRuleset); From 5accc1e916670a5be512fb77894259091b194380 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Sat, 17 Nov 2018 11:05:28 -0800 Subject: [PATCH 063/140] Fix #274: Add UR study participation UI Notes: - I had to put the copy in brackets in StudyInvitation.jsx to be able to use the apostrophe it contains. This avoids the eslint rule error react/no-unescaped-entities. - The panels are wider than bryanbell's mocks, but the PR for #256 will fix that. --- .../components/BrowserActionApp.jsx | 41 +++++++++++++- src/browser_action/components/StudyFooter.css | 10 ++++ src/browser_action/components/StudyFooter.jsx | 32 +++++++++++ .../components/StudyInvitation.css | 52 +++++++++++++++++ .../components/StudyInvitation.jsx | 56 +++++++++++++++++++ .../components/TrackedProductList.css | 6 +- src/img/back.svg | 4 ++ 7 files changed, 196 insertions(+), 5 deletions(-) create mode 100644 src/browser_action/components/StudyFooter.css create mode 100644 src/browser_action/components/StudyFooter.jsx create mode 100644 src/browser_action/components/StudyInvitation.css create mode 100644 src/browser_action/components/StudyInvitation.jsx create mode 100644 src/img/back.svg diff --git a/src/browser_action/components/BrowserActionApp.jsx b/src/browser_action/components/BrowserActionApp.jsx index e9c7940..20c3281 100644 --- a/src/browser_action/components/BrowserActionApp.jsx +++ b/src/browser_action/components/BrowserActionApp.jsx @@ -13,6 +13,8 @@ import TrackedProductList from 'commerce/browser_action/components/TrackedProduc import {extractedProductShape, getAllProducts, productShape} from 'commerce/state/products'; import * as syncActions from 'commerce/state/sync'; import {recordEvent, getBadgeType} from 'commerce/telemetry/extension'; +import StudyInvitation from 'commerce/browser_action/components/StudyInvitation'; +import StudyFooter from 'commerce/browser_action/components/StudyFooter'; import 'commerce/browser_action/components/BrowserActionApp.css'; @@ -49,6 +51,7 @@ export default class BrowserActionApp extends React.Component { super(props); this.state = { extractedProduct: props.extractedProduct, + showStudyInvitation: false, }; } @@ -82,9 +85,40 @@ export default class BrowserActionApp extends React.Component { window.close(); } + /** + * Show the Study popup when the StudyFooter is clicked + */ + handleClickStudy() { + this.setState({showStudyInvitation: true}); + } + + /** + * Return to the TrackedProductList when the back button on the Study popup is clicked + */ + handleClickBack() { + this.setState({showStudyInvitation: false}); + } + + /** + * Open the Study recruitment survey page and close the panel when the participate button + * in the Study popup is clicked + */ + handleClickParticipate() { + browser.tabs.create({url: 'https://www.surveygizmo.com/s3/4693160/Price-Wise-Research-Study-Participant-Screener'}); + window.close(); + } + render() { const {products} = this.props; - const {extractedProduct} = this.state; + const {extractedProduct, showStudyInvitation} = this.state; + if (showStudyInvitation) { + return ( + + ); + } return (
@@ -115,7 +149,10 @@ export default class BrowserActionApp extends React.Component { ) : ( - + + + + )} ); diff --git a/src/browser_action/components/StudyFooter.css b/src/browser_action/components/StudyFooter.css new file mode 100644 index 0000000..6f68fef --- /dev/null +++ b/src/browser_action/components/StudyFooter.css @@ -0,0 +1,10 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** Study footer styles */ + +.menu-item.study { + justify-content: center; + border-top: 1px solid var(--grey-30); +} diff --git a/src/browser_action/components/StudyFooter.jsx b/src/browser_action/components/StudyFooter.jsx new file mode 100644 index 0000000..d12596e --- /dev/null +++ b/src/browser_action/components/StudyFooter.jsx @@ -0,0 +1,32 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import autobind from 'autobind-decorator'; +import pt from 'prop-types'; +import React from 'react'; + +import 'commerce/browser_action/components/StudyFooter.css'; + +/** + * Feedback footer for User Research study recruitment. + */ +@autobind +export default class StudyFooter extends React.Component { + static propTypes = { + // Direct props + onClick: pt.func.isRequired, + } + + render() { + return ( + + ); + } +} diff --git a/src/browser_action/components/StudyInvitation.css b/src/browser_action/components/StudyInvitation.css new file mode 100644 index 0000000..7641e6f --- /dev/null +++ b/src/browser_action/components/StudyInvitation.css @@ -0,0 +1,52 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** Components for the StudyInvitation screen */ + +.title-bar.study { + justify-content: flex-start; + position: relative; +} + +.title-bar.study .title { + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); +} + +.study-invitation { + align-items: center; + display: flex; + flex-direction: column; + gap: 16px; + margin: 16px; + text-align: center; +} + +.study-invitation .hero { + height: 123px; + width: 142px; +} + +.study-invitation .description { + margin: 0; +} + +.study-invitation .participate.button { + width: 100%; +} + +.participate.button:enabled { + color: var(--white-100); + background-color: var(--blue-60); +} + +.participate.button:hover:enabled { + background: var(--blue-70); +} + +.participate.button:active:enabled { + background: var(--blue-80); +} diff --git a/src/browser_action/components/StudyInvitation.jsx b/src/browser_action/components/StudyInvitation.jsx new file mode 100644 index 0000000..d1f785f --- /dev/null +++ b/src/browser_action/components/StudyInvitation.jsx @@ -0,0 +1,56 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import autobind from 'autobind-decorator'; +import pt from 'prop-types'; +import React from 'react'; + +import 'commerce/browser_action/components/StudyInvitation.css'; + +/** + * Study Invitation page for when users click the StudyFooter + */ +@autobind +export default class StudyInvitation extends React.Component { + static propTypes = { + // Direct props + onClickBack: pt.func.isRequired, + onClickParticipate: pt.func.isRequired, + } + + render() { + return ( + +
+ +

Feedback

+
+
+ +

+ {"Help us improve Price Wise by participating in a research study. Take this 5-minute survey to learn more about the study and see if you're a fit."} +

+ +
+
+ ); + } +} diff --git a/src/browser_action/components/TrackedProductList.css b/src/browser_action/components/TrackedProductList.css index 08872d9..ac81489 100644 --- a/src/browser_action/components/TrackedProductList.css +++ b/src/browser_action/components/TrackedProductList.css @@ -13,10 +13,10 @@ margin: 0; /* - max popup height - (titlebar height + track button height) = max list height - 600px - (42px + 36px) = 522px + max popup height - (titlebar height + track button height + survey footer height) = max list height + 600px - (42px + 36px + 36px) = 486px */ - max-height: 522px; + max-height: 486px; overflow-y: auto; padding: 0; } diff --git a/src/img/back.svg b/src/img/back.svg new file mode 100644 index 0000000..1257d51 --- /dev/null +++ b/src/img/back.svg @@ -0,0 +1,4 @@ + + From 0ba2b18eb535d2b12cb1cd5926b070dae34ffe13 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Mon, 19 Nov 2018 15:31:35 -0800 Subject: [PATCH 064/140] Update UR survey URL and hero image Also incorporate feedback from Osmose, including the feature flag 'enableStudyUI' in config.js to turn on/off the UI. --- src/browser_action/components/BrowserActionApp.jsx | 11 +++++++---- src/browser_action/components/StudyFooter.jsx | 2 +- src/browser_action/components/StudyInvitation.jsx | 2 +- src/config.js | 6 ++++++ src/img/ur_survey.svg | 4 ++++ 5 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 src/img/ur_survey.svg diff --git a/src/browser_action/components/BrowserActionApp.jsx b/src/browser_action/components/BrowserActionApp.jsx index 20c3281..5050729 100644 --- a/src/browser_action/components/BrowserActionApp.jsx +++ b/src/browser_action/components/BrowserActionApp.jsx @@ -52,6 +52,7 @@ export default class BrowserActionApp extends React.Component { this.state = { extractedProduct: props.extractedProduct, showStudyInvitation: false, + enableStudyUI: false, }; } @@ -64,6 +65,8 @@ export default class BrowserActionApp extends React.Component { } }); + this.setState({enableStudyUI: await config.get('enableStudyUI')}); + await recordEvent('open_popup', 'toolbar_button', null, {badge_type: await getBadgeType()}); } @@ -103,14 +106,14 @@ export default class BrowserActionApp extends React.Component { * Open the Study recruitment survey page and close the panel when the participate button * in the Study popup is clicked */ - handleClickParticipate() { - browser.tabs.create({url: 'https://www.surveygizmo.com/s3/4693160/Price-Wise-Research-Study-Participant-Screener'}); + async handleClickParticipate() { + browser.tabs.create({url: await config.get('studyUrl')}); window.close(); } render() { const {products} = this.props; - const {extractedProduct, showStudyInvitation} = this.state; + const {extractedProduct, showStudyInvitation, enableStudyUI} = this.state; if (showStudyInvitation) { return ( - + {enableStudyUI ? : null} )} diff --git a/src/browser_action/components/StudyFooter.jsx b/src/browser_action/components/StudyFooter.jsx index d12596e..286eae1 100644 --- a/src/browser_action/components/StudyFooter.jsx +++ b/src/browser_action/components/StudyFooter.jsx @@ -25,7 +25,7 @@ export default class StudyFooter extends React.Component { className="menu-item study" onClick={this.props.onClick} > - Help us improve Price Wise... + Help us improve Price Wise… ); } diff --git a/src/browser_action/components/StudyInvitation.jsx b/src/browser_action/components/StudyInvitation.jsx index d1f785f..0c90d72 100644 --- a/src/browser_action/components/StudyInvitation.jsx +++ b/src/browser_action/components/StudyInvitation.jsx @@ -38,7 +38,7 @@ export default class StudyInvitation extends React.Component {

Feedback

- +

{"Help us improve Price Wise by participating in a research study. Take this 5-minute survey to learn more about the study and see if you're a fit."}

diff --git a/src/config.js b/src/config.js index 22aa612..a02be41 100644 --- a/src/config.js +++ b/src/config.js @@ -94,6 +94,12 @@ const CONFIG = { 'mkelly.me', 'www.mkelly.me', ]), + + // TODO (bdanforth) Revert PR#278 after 11/26/18 + /** Temporary Cyber Monday study UI feature flag */ + enableStudyUI: new BoolValue(true), + /** URL for the study's recruitment survey */ + studyUrl: new StringValue('https://qsurvey.mozilla.com/s3/Price-Wise-Research-Study'), }; export default { diff --git a/src/img/ur_survey.svg b/src/img/ur_survey.svg new file mode 100644 index 0000000..92525d7 --- /dev/null +++ b/src/img/ur_survey.svg @@ -0,0 +1,4 @@ + +Artboard 1 From 4eab37c830535660837bef68981b1af018941a8f Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Mon, 19 Nov 2018 15:36:09 -0800 Subject: [PATCH 065/140] 12.0.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 72c6ccd..2626fa8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "11.0.0", + "version": "12.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 2292638..b92302a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "11.0.0", + "version": "12.0.0", "description": "Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy.", "private": true, "author": "Mozilla", From 6ce3ea91d50a150bc877b55b04d85674276d73ad Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Tue, 20 Nov 2018 10:55:38 -0500 Subject: [PATCH 066/140] Rename trapezoid() to linearScale(). --- src/extraction/fathom/ruleset_factory.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index d94637e..912d5c0 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -50,13 +50,13 @@ export default class RulesetFactory { // (though we should have distinct penalties for that sort of thing if we // care). More importantly, clamp the upper bound of the score so we don't // overcome other bonuses and penalties. - return trapezoid(area, 80 ** 2, 1000 ** 2) ** this.bigImageCoeff; + return linearScale(area, 80 ** 2, 1000 ** 2) ** this.bigImageCoeff; } /** Return whether the computed font size of an element is big. */ fontIsBig(fnode) { const size = parseInt(getComputedStyle(fnode.element).fontSize, 10); - return trapezoid(size, 14, 50) ** this.bigFontCoeff; + return linearScale(size, 14, 50) ** this.bigFontCoeff; } /** @@ -108,7 +108,7 @@ export default class RulesetFactory { // Stop giving additional bonus for anything closer than 200px to the top // of the viewport. Those are probably usually headers. - return trapezoid(imageTop, viewportHeight * 2, 200) ** featureCoeff; + return linearScale(imageTop, viewportHeight * 2, 200) ** featureCoeff; } /** @@ -117,7 +117,7 @@ export default class RulesetFactory { */ isNearImage(fnode) { const image = this.getHighestScoringImage(fnode); - return trapezoid(euclidean(fnode, image), 1000, 0) ** this.isNearImageCoeff; + return linearScale(euclidean(fnode, image), 1000, 0) ** this.isNearImageCoeff; } /** @@ -141,7 +141,7 @@ export default class RulesetFactory { const bottomDistance = Math.abs(imageRect.bottom - nodeRect.top); const shortestDistance = Math.min(topDistance, bottomDistance); - return trapezoid(shortestDistance, 200, 0) ** this.isNearbyImageYAxisTitleCoeff; + return linearScale(shortestDistance, 200, 0) ** this.isNearbyImageYAxisTitleCoeff; } /** @@ -268,7 +268,7 @@ export default class RulesetFactory { // better score for larger images rule(type('imageish'), score(this.isBig.bind(this))), // punishment for extreme aspect ratios, to filter out banners or nav elements - rule(type('imageish'), score(fnode => trapezoid(this.aspectRatio(fnode.element), 10, 5) + rule(type('imageish'), score(fnode => linearScale(this.aspectRatio(fnode.element), 10, 5) ** this.extremeAspectCoeff)), // no background images, even ones that have reasonable aspect ratios // TODO: If necessary, also look at parents. I've seen them say @@ -337,12 +337,12 @@ export default class RulesetFactory { /** * Scale a number to the range [ZEROISH, ONEISH]. * - * For a rising trapezoid, the result is ZEROISH until the input reaches + * For a rising line, the result is ZEROISH until the input reaches * zeroAt, then increases linearly until oneAt, at which it becomes ONEISH. To - * make a falling trapezoid, where the result is ONEISH to the left and ZEROISH + * make a falling line, where the result is ONEISH to the left and ZEROISH * to the right, use a zeroAt greater than oneAt. */ -function trapezoid(number, zeroAt, oneAt) { +function linearScale(number, zeroAt, oneAt) { const isRising = zeroAt < oneAt; if (isRising) { if (number <= zeroAt) { From 5d55d10d23822a2ed5238a07e03a1411755d0ff0 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Tue, 20 Nov 2018 11:12:26 -0500 Subject: [PATCH 067/140] Use single-line doclets where possible. Put a newline after double asterisks for multi-line ones. --- src/extraction/fathom/ruleset_factory.js | 34 +++++++++--------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index 912d5c0..d9a5659 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -38,9 +38,7 @@ export default class RulesetFactory { ] = coefficients; } - /** - * Scores fnode in direct proportion to its size - */ + /** Scores fnode in direct proportion to its size */ isBig(fnode) { const domRect = fnode.element.getBoundingClientRect(); const area = domRect.width * domRect.height; @@ -59,28 +57,28 @@ export default class RulesetFactory { return linearScale(size, 14, 50) ** this.bigFontCoeff; } - /** - * Scores fnode with a '$' in its innerText - */ + /** Scores fnode with a '$' in its innerText */ hasDollarSign(fnode) { return (fnode.element.innerText.includes('$') ? ONEISH : ZEROISH) ** this.hasDollarSignCoeff; } - /** Return whether some substring is within a given string, case insensitively. */ + /** + * Return whether some substring is within a given string, case + * insensitively. + */ doesContain(haystack, needle) { return haystack.toLowerCase().includes(needle); } - /** Return a weighted confidence of whether a substring is within a given - * string, case insensitively. + /** + * Return a weighted confidence of whether a substring is within a given + * string, case insensitively. */ contains(haystack, needle, coeff) { return (this.doesContain(haystack, needle) ? ONEISH : ZEROISH) ** coeff; } - /** - * Scores fnode with 'price' in its id - */ + /** Scores fnode with 'price' in its id */ hasPriceInID(fnode) { return this.contains(fnode.element.id, 'price', this.hasPriceInIDCoeff); } @@ -99,9 +97,7 @@ export default class RulesetFactory { return this.contains(fnode.element.parentElement.className, 'price', this.hasPriceInParentClassNameCoeff); } - /** - * Scores fnode by its vertical location relative to the fold - */ + /** Scores fnode by its vertical location relative to the fold */ isAboveTheFold(fnode, featureCoeff) { const viewportHeight = 950; const imageTop = fnode.element.getBoundingClientRect().top; @@ -158,9 +154,7 @@ export default class RulesetFactory { return (regExp.test(text) ? ONEISH : ZEROISH) ** this.hasPriceishPatternCoeff; } - /** - * Checks to see if a 'priceish' fnode is eligible for scoring - */ + /** Checks to see if a 'priceish' fnode is eligible for scoring */ isEligiblePrice(fnode) { return ( this.isVisible(fnode) @@ -169,9 +163,7 @@ export default class RulesetFactory { ); } - /** - * Checks to see if a 'titleish' fnode is eligible for scoring - */ + /** Checks to see if a 'titleish' fnode is eligible for scoring */ isEligibleTitle(fnode) { return ( this.isVisible(fnode) From 45db392a2dbfa2db7d7685fb7a638dc80344e1cf Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Tue, 20 Nov 2018 11:16:06 -0500 Subject: [PATCH 068/140] Rename contains() functions to indicate what returns bools and what returns scores. --- src/extraction/fathom/ruleset_factory.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index d9a5659..bbaabf2 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -66,7 +66,7 @@ export default class RulesetFactory { * Return whether some substring is within a given string, case * insensitively. */ - doesContain(haystack, needle) { + caselessIncludes(haystack, needle) { return haystack.toLowerCase().includes(needle); } @@ -74,27 +74,27 @@ export default class RulesetFactory { * Return a weighted confidence of whether a substring is within a given * string, case insensitively. */ - contains(haystack, needle, coeff) { - return (this.doesContain(haystack, needle) ? ONEISH : ZEROISH) ** coeff; + weightedIncludes(haystack, needle, coeff) { + return (this.caselessIncludes(haystack, needle) ? ONEISH : ZEROISH) ** coeff; } /** Scores fnode with 'price' in its id */ hasPriceInID(fnode) { - return this.contains(fnode.element.id, 'price', this.hasPriceInIDCoeff); + return this.weightedIncludes(fnode.element.id, 'price', this.hasPriceInIDCoeff); } hasPriceInParentID(fnode) { - return this.contains(fnode.element.parentElement.id, 'price', this.hasPriceInParentIDCoeff); + return this.weightedIncludes(fnode.element.parentElement.id, 'price', this.hasPriceInParentIDCoeff); } /** Scores fnode with 'price' in its class name */ hasPriceInClassName(fnode) { - return this.contains(fnode.element.className, 'price', this.hasPriceInClassNameCoeff); + return this.weightedIncludes(fnode.element.className, 'price', this.hasPriceInClassNameCoeff); } /** Scores fnode with 'price' in its class name */ hasPriceInParentClassName(fnode) { - return this.contains(fnode.element.parentElement.className, 'price', this.hasPriceInParentClassNameCoeff); + return this.weightedIncludes(fnode.element.parentElement.className, 'price', this.hasPriceInParentClassNameCoeff); } /** Scores fnode by its vertical location relative to the fold */ @@ -265,7 +265,7 @@ export default class RulesetFactory { // no background images, even ones that have reasonable aspect ratios // TODO: If necessary, also look at parents. I've seen them say // "background" in their IDs as well. - rule(type('imageish'), score(fnode => (this.doesContain(fnode.element.id, 'background') ? (ZEROISH ** this.backgroundIdImageCoeff) : 1))), + rule(type('imageish'), score(fnode => (this.caselessIncludes(fnode.element.id, 'background') ? (ZEROISH ** this.backgroundIdImageCoeff) : 1))), // return image element(s) with max score rule(type('imageish').max(), out('image')), From e9edf39b2fd580300bc4e47438d060bd13aadce3 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Tue, 20 Nov 2018 11:38:52 -0500 Subject: [PATCH 069/140] Un-inline the aspect ratio rule. --- src/extraction/fathom/ruleset_factory.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index bbaabf2..34ccb3c 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -92,7 +92,7 @@ export default class RulesetFactory { return this.weightedIncludes(fnode.element.className, 'price', this.hasPriceInClassNameCoeff); } - /** Scores fnode with 'price' in its class name */ + /** Scores fnode with 'price' in its parent's class name */ hasPriceInParentClassName(fnode) { return this.weightedIncludes(fnode.element.parentElement.className, 'price', this.hasPriceInParentClassNameCoeff); } @@ -241,6 +241,11 @@ export default class RulesetFactory { return (rect.width > rect.height) ? (rect.width / rect.height) : (rect.height / rect.width); } + /** Give a bonus for elements that have a non-extreme aspect ratio. */ + hasSquareAspectRatio(fnode) { + return linearScale(this.aspectRatio(fnode.element), 10, 5) ** this.extremeAspectCoeff; + } + /** * Using coefficients passed into the constructor method, returns a weighted * ruleset used to score elements in an HTML document. @@ -259,9 +264,10 @@ export default class RulesetFactory { rule(type('imageish'), score(fnode => this.isAboveTheFold(fnode, this.isAboveTheFoldImageCoeff))), // better score for larger images rule(type('imageish'), score(this.isBig.bind(this))), - // punishment for extreme aspect ratios, to filter out banners or nav elements - rule(type('imageish'), score(fnode => linearScale(this.aspectRatio(fnode.element), 10, 5) - ** this.extremeAspectCoeff)), + // bonus for non-extreme aspect ratios, to filter out banners or nav elements + // TODO: Meant to make this a penalty, but it turns out to work as is. + // Try as a penalty. + rule(type('imageish'), score(this.hasSquareAspectRatio.bind(this))), // no background images, even ones that have reasonable aspect ratios // TODO: If necessary, also look at parents. I've seen them say // "background" in their IDs as well. From c0570d3eb0b29a003d9930055a91bd4fd0e8dcc6 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Tue, 20 Nov 2018 11:43:45 -0500 Subject: [PATCH 070/140] Un-inline hasBackgroundInID(). --- src/extraction/fathom/ruleset_factory.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index 34ccb3c..6c3e723 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -78,6 +78,13 @@ export default class RulesetFactory { return (this.caselessIncludes(haystack, needle) ? ONEISH : ZEROISH) ** coeff; } + /** + * Punish elements with "background" in their ID. Do nothing to those without. + */ + hasBackgroundInID(fnode) { + return this.caselessIncludes(fnode.element.id, 'background') ? (ZEROISH ** this.backgroundIdImageCoeff) : 1; + } + /** Scores fnode with 'price' in its id */ hasPriceInID(fnode) { return this.weightedIncludes(fnode.element.id, 'price', this.hasPriceInIDCoeff); @@ -271,7 +278,7 @@ export default class RulesetFactory { // no background images, even ones that have reasonable aspect ratios // TODO: If necessary, also look at parents. I've seen them say // "background" in their IDs as well. - rule(type('imageish'), score(fnode => (this.caselessIncludes(fnode.element.id, 'background') ? (ZEROISH ** this.backgroundIdImageCoeff) : 1))), + rule(type('imageish'), score(this.hasBackgroundInID.bind(this))), // return image element(s) with max score rule(type('imageish').max(), out('image')), From a57656ab5c6b37e7d33b6289fa9c4bdc71d94bc9 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Tue, 20 Nov 2018 11:45:59 -0500 Subject: [PATCH 071/140] Stick types in local names. --- src/extraction/fathom/ruleset_factory.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index 6c3e723..515ee0f 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -119,8 +119,8 @@ export default class RulesetFactory { * scoring image. */ isNearImage(fnode) { - const image = this.getHighestScoringImage(fnode); - return linearScale(euclidean(fnode, image), 1000, 0) ** this.isNearImageCoeff; + const imageFnode = this.getHighestScoringImage(fnode); + return linearScale(euclidean(fnode, imageFnode), 1000, 0) ** this.isNearImageCoeff; } /** @@ -131,8 +131,8 @@ export default class RulesetFactory { * bottom" one. */ isNearImageTopOrBottom(fnode) { - const image = this.getHighestScoringImage(fnode).element; - const imageRect = image.getBoundingClientRect(); + const imageElement = this.getHighestScoringImage(fnode).element; + const imageRect = imageElement.getBoundingClientRect(); const nodeRect = fnode.element.getBoundingClientRect(); // Should cover title above image and title in a column next to image. From 4cca17a8803c2b572cb870b99d4ae5ee85149f4c Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Tue, 20 Nov 2018 11:47:44 -0500 Subject: [PATCH 072/140] Remove unneeded !!. --- src/extraction/fathom/ruleset_factory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index 515ee0f..e5ca8fd 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -236,7 +236,7 @@ export default class RulesetFactory { hasBackgroundImage(fnode) { const bgImage = getComputedStyle(fnode.element)['background-image']; - return !!bgImage && bgImage !== 'none'; + return bgImage && bgImage !== 'none'; } /** From 836dfaa568cc55744144f2858b62fa0bfde132a7 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Tue, 20 Nov 2018 09:37:16 -0800 Subject: [PATCH 073/140] Update version number to 14.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b92302a..6801245 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "12.0.0", + "version": "14.0.0", "description": "Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy.", "private": true, "author": "Mozilla", From ea275aaad9402a248ec6d277a2c346a7d198404e Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Tue, 20 Nov 2018 12:42:11 -0500 Subject: [PATCH 074/140] Teach the application bits how to extract from CSS background-images. We don't handle non-url() specifications of images. Extraction will just fail nicely in the (hopefully uncommon) cases of image-sets and such. --- src/extraction/fathom/index.js | 17 ++++++++++++++++- src/extraction/fathom/ruleset_factory.js | 4 +++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/extraction/fathom/index.js b/src/extraction/fathom/index.js index b264ef8..36e16a8 100644 --- a/src/extraction/fathom/index.js +++ b/src/extraction/fathom/index.js @@ -32,8 +32,23 @@ const FEATURE_DEFAULTS = { const PRODUCT_FEATURES = { image: { ...FEATURE_DEFAULTS, + /** + * @return the URL of an image resource + */ getValueFromElement(element) { - return element.src; + /** + * Given a CSS url() declaration 'url("http://foo")', return 'http://foo'. + */ + function urlFromCssDeclaration(declaration) { + return declaration.substring(5, declaration.length - 2); + } + if (element.tagName === 'IMG') { + return element.src; + } else { + // The other thing the ruleset can return is an arbitrary element with + // a CSS background image. + return urlFromCssDeclaration(getComputedStyle(element)['background-image']); + } }, }, title: { diff --git a/src/extraction/fathom/ruleset_factory.js b/src/extraction/fathom/ruleset_factory.js index e5ca8fd..9092d67 100644 --- a/src/extraction/fathom/ruleset_factory.js +++ b/src/extraction/fathom/ruleset_factory.js @@ -236,7 +236,9 @@ export default class RulesetFactory { hasBackgroundImage(fnode) { const bgImage = getComputedStyle(fnode.element)['background-image']; - return bgImage && bgImage !== 'none'; + return bgImage && bgImage.startsWith('url("') && bgImage.endsWith('")'); + // The app doesn't yet know how to deal with non-url() types of background + // images. } /** From 57ca2953ca3985621f8bbda5176370914112b543 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Tue, 20 Nov 2018 12:49:30 -0500 Subject: [PATCH 075/140] Damn you, linter. --- src/extraction/fathom/index.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/extraction/fathom/index.js b/src/extraction/fathom/index.js index 36e16a8..4660bc9 100644 --- a/src/extraction/fathom/index.js +++ b/src/extraction/fathom/index.js @@ -44,11 +44,10 @@ const PRODUCT_FEATURES = { } if (element.tagName === 'IMG') { return element.src; - } else { - // The other thing the ruleset can return is an arbitrary element with - // a CSS background image. - return urlFromCssDeclaration(getComputedStyle(element)['background-image']); } + // The other thing the ruleset can return is an arbitrary element with + // a CSS background image. + return urlFromCssDeclaration(getComputedStyle(element)['background-image']); }, }, title: { From aa4bd886c5af9222fe3014e8730bfc8eae913bdc Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Tue, 20 Nov 2018 15:22:44 -0500 Subject: [PATCH 076/140] Use slice() for brevity and great justice. --- src/extraction/fathom/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/extraction/fathom/index.js b/src/extraction/fathom/index.js index 4660bc9..8b1e104 100644 --- a/src/extraction/fathom/index.js +++ b/src/extraction/fathom/index.js @@ -40,8 +40,9 @@ const PRODUCT_FEATURES = { * Given a CSS url() declaration 'url("http://foo")', return 'http://foo'. */ function urlFromCssDeclaration(declaration) { - return declaration.substring(5, declaration.length - 2); + return declaration.slice(5, -2); } + if (element.tagName === 'IMG') { return element.src; } From 6795f5058cfd910ee329fc2801b04561701bfa38 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Tue, 20 Nov 2018 11:25:37 -0800 Subject: [PATCH 077/140] Fix #280: Use Firefox background colors for doorhanger footer Doorhanger footer styles are not specified in https://design.firefox.com/photon/components/doorhangers.html, nor do I see the colors I believe are correct (https://searchfox.org/mozilla-central/source/browser/themes/linux/browser.css#21-23) in the Photon Colors stylesheet (https://github.com/FirefoxUX/photon-colors/blob/master/photon-colors.css), so I used the [default button colors](https://design.firefox.com/photon/components/buttons.html#default-4). --- src/browser_action/components/StudyFooter.css | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/browser_action/components/StudyFooter.css b/src/browser_action/components/StudyFooter.css index 6f68fef..d75ca28 100644 --- a/src/browser_action/components/StudyFooter.css +++ b/src/browser_action/components/StudyFooter.css @@ -4,7 +4,16 @@ /** Study footer styles */ -.menu-item.study { +.menu-item.study:enabled { justify-content: center; border-top: 1px solid var(--grey-30); + background-color: var(--grey-90-a10); +} + +.menu-item.study:enabled:hover { + background-color: var(--grey-90-a20); +} + +.menu-item.study:enabled:active { + background-color: var(--grey-90-a30); } From 998710ebe7714145416b1327325266669a15b0a0 Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Tue, 20 Nov 2018 15:43:18 -0800 Subject: [PATCH 078/140] 15.0.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2626fa8..bc32b5d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "12.0.0", + "version": "15.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 0ad9fcd..68e69f5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "14.0.0", + "version": "15.0.0", "description": "Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy.", "private": true, "author": "Mozilla", From a719bbaf9d1206b51f97212519892728ca1b9b0a Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Thu, 15 Nov 2018 11:38:45 -0800 Subject: [PATCH 079/140] Fix #256: Change popup width in overflow menu With CustomizableUI.jsm (via the experimental `browser.customizableUI` API added in #157), it is possible to detect when the browserAction toolbar button is and is not in the Overflow menu. Because the overflow menu width varies by OS (for example, it is 377px wide on my Mac 10.13 and 425px wide on a Linux 14.04), this patch will detect whether or not the toolbar button is in the Overflow menu and adjust the width accordingly. This fix has the added benefit of allowing us to constrain the non-Overflow menu popup width (which is hopefully the vast majority use case) to the UX spec of 320px where previously we had set it to a max-width of 400px to try to accomodate Overflow menu issues. --- src/browser_action/index.css | 6 ++++-- src/browser_action/index.jsx | 6 ++++++ src/experiment_apis/customizableUI/api.js | 5 +++++ src/experiment_apis/customizableUI/schema.json | 15 +++++++++++++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/browser_action/index.css b/src/browser_action/index.css index 7a58ec9..c281d34 100644 --- a/src/browser_action/index.css +++ b/src/browser_action/index.css @@ -21,8 +21,10 @@ body { } #browser-action-app { - min-width: 320px; - max-width: 400px; /* Overflow menu popup width exceeds 320px and cannot be changed */ + width: 320px; +} + +#browser-action-app.overflow { width: 100%; } diff --git a/src/browser_action/index.jsx b/src/browser_action/index.jsx index 57dc807..6253e29 100644 --- a/src/browser_action/index.jsx +++ b/src/browser_action/index.jsx @@ -20,6 +20,12 @@ if (extractedProductJSON) { appProps.extractedProduct = JSON.parse(extractedProductJSON); } +(async function checkOverflow() { + if (await browser.customizableUI.isWidgetInOverflow('shopping-testpilot_mozilla_org-browser-action')) { + document.getElementById('browser-action-app').classList.add('overflow'); + } +}()); + ReactDOM.render( diff --git a/src/experiment_apis/customizableUI/api.js b/src/experiment_apis/customizableUI/api.js index 1af7a8b..50f6159 100644 --- a/src/experiment_apis/customizableUI/api.js +++ b/src/experiment_apis/customizableUI/api.js @@ -5,6 +5,7 @@ this.customizableUI = class extends ExtensionAPI { getAPI(context) { + const {Services} = ChromeUtils.import('resource://gre/modules/Services.jsm'); ChromeUtils.import('resource://gre/modules/ExtensionCommon.jsm'); const {EventManager} = ExtensionCommon; const {CustomizableUI} = ChromeUtils.import('resource:///modules/CustomizableUI.jsm', {}); @@ -25,6 +26,10 @@ this.customizableUI = class extends ExtensionAPI { }; }, ).api(), + async isWidgetInOverflow(widgetId) { + const browserWindow = Services.wm.getMostRecentWindow('navigator:browser'); + return CustomizableUI.getWidget(widgetId).forWindow(browserWindow).overflowed; + }, }, }; } diff --git a/src/experiment_apis/customizableUI/schema.json b/src/experiment_apis/customizableUI/schema.json index d177a40..6179b04 100644 --- a/src/experiment_apis/customizableUI/schema.json +++ b/src/experiment_apis/customizableUI/schema.json @@ -14,6 +14,21 @@ } ] } + ], + "functions": [ + { + "name": "isWidgetInOverflow", + "type": "function", + "description": "Returns a boolean for whether or not the provided widget in the provided window is in the overflow menu or not.", + "async": true, + "parameters": [ + { + "name": "widgetId", + "type": "string", + "description": "The id of the widget to check." + } + ] + } ] } ] From b6c508a16f425fda1565a7f5f6305c6d46cdf0dc Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Fri, 16 Nov 2018 12:28:53 -0800 Subject: [PATCH 080/140] Detect overflow for explicit (un)pinning of toolbar button to overflow menu Detect toolbar button in fixed overflow menu: - Add a call to `getPlacementOfWidget` - This check covers the case when the toolbar button is explicitly pinned/unpinned to the Overflow menu by the user. Context: - The original patch only detected the toolbar button in the non-fixed overflow menu, which only covered the case when the toolbar button was moved into and out of the overflow menu by a window resize. - Per jaws, the fixed versus non-fixed Overflow menus live in two different areas of the browser chrome, where "the non-fixed overflow panel is the area that is basically an extension of the navigation-toolbar." - With both checks together, we cover both of the cases in which the toolbar button can be moved into and out of the Overflow menu. --- src/experiment_apis/customizableUI/api.js | 14 +++++++++----- src/experiment_apis/customizableUI/schema.json | 4 ++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/experiment_apis/customizableUI/api.js b/src/experiment_apis/customizableUI/api.js index 50f6159..d95270d 100644 --- a/src/experiment_apis/customizableUI/api.js +++ b/src/experiment_apis/customizableUI/api.js @@ -1,14 +1,14 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* global ChromeUtils ExtensionAPI ExtensionCommon */ +/* global ChromeUtils ExtensionAPI */ this.customizableUI = class extends ExtensionAPI { getAPI(context) { - const {Services} = ChromeUtils.import('resource://gre/modules/Services.jsm'); - ChromeUtils.import('resource://gre/modules/ExtensionCommon.jsm'); + const {CustomizableUI} = ChromeUtils.import('resource:///modules/CustomizableUI.jsm'); + const {ExtensionCommon} = ChromeUtils.import('resource://gre/modules/ExtensionCommon.jsm'); const {EventManager} = ExtensionCommon; - const {CustomizableUI} = ChromeUtils.import('resource:///modules/CustomizableUI.jsm', {}); + const {Services} = ChromeUtils.import('resource://gre/modules/Services.jsm'); return { customizableUI: { onWidgetRemoved: new EventManager( @@ -27,8 +27,12 @@ this.customizableUI = class extends ExtensionAPI { }, ).api(), async isWidgetInOverflow(widgetId) { + const {area} = CustomizableUI.getPlacementOfWidget(widgetId); const browserWindow = Services.wm.getMostRecentWindow('navigator:browser'); - return CustomizableUI.getWidget(widgetId).forWindow(browserWindow).overflowed; + // First check is for the non-fixed overflow menu (e.g. widget moved by resizing window) + // Second is for fixed overflow menu (e.g. widget moved by (un)pinning button to overflow) + return (CustomizableUI.getWidget(widgetId).forWindow(browserWindow).overflowed + || area === 'widget-overflow-fixed-list'); }, }, }; diff --git a/src/experiment_apis/customizableUI/schema.json b/src/experiment_apis/customizableUI/schema.json index 6179b04..63a7c9f 100644 --- a/src/experiment_apis/customizableUI/schema.json +++ b/src/experiment_apis/customizableUI/schema.json @@ -5,7 +5,7 @@ { "name": "onWidgetRemoved", "type": "function", - "description": "Fired when a widget is removed from the browser chrome", + "description": "Fired when a widget is removed from the browser chrome.", "parameters": [ { "name": "widgetId", @@ -19,7 +19,7 @@ { "name": "isWidgetInOverflow", "type": "function", - "description": "Returns a boolean for whether or not the provided widget in the provided window is in the overflow menu or not.", + "description": "Determine whether or not a widget is in the overflow menu.", "async": true, "parameters": [ { From c60594f50e77f22ea7513d549436474fc05b6581 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Tue, 20 Nov 2018 17:04:13 -0800 Subject: [PATCH 081/140] Incorporate Osmose's feedback --- src/experiment_apis/customizableUI/api.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/experiment_apis/customizableUI/api.js b/src/experiment_apis/customizableUI/api.js index d95270d..0919694 100644 --- a/src/experiment_apis/customizableUI/api.js +++ b/src/experiment_apis/customizableUI/api.js @@ -31,7 +31,8 @@ this.customizableUI = class extends ExtensionAPI { const browserWindow = Services.wm.getMostRecentWindow('navigator:browser'); // First check is for the non-fixed overflow menu (e.g. widget moved by resizing window) // Second is for fixed overflow menu (e.g. widget moved by (un)pinning button to overflow) - return (CustomizableUI.getWidget(widgetId).forWindow(browserWindow).overflowed + return ( + CustomizableUI.getWidget(widgetId).forWindow(browserWindow).overflowed || area === 'widget-overflow-fixed-list'); }, }, From 8867cc18d1e0a53eaa1432652c081377bbd6370a Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Fri, 16 Nov 2018 13:50:50 -0800 Subject: [PATCH 082/140] Fix #177: Disable price polling in Private Browsing windows Update `shouldUpdatePrices` with a check for whether or not the active window is a private window. I did not add a check for `isActiveWindowPrivate` in `shouldExtract` in `./src/privacy.js`, despite the fact that `browser.extension.inIncognitoContext` returns the "wrong" value for background extraction, because background extraction is gated by the `shouldUpdatePrices` check. --- src/privacy.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/privacy.js b/src/privacy.js index dff355f..f2218d8 100644 --- a/src/privacy.js +++ b/src/privacy.js @@ -44,8 +44,7 @@ export async function shouldCollectTelemetry(method) { * @return {boolean} */ export async function shouldUpdatePrices() { - // TODO (bdanforth): Add private browsing check per #177 - return true; + return !isActiveWindowPrivate(); } async function trackingProtectionEnabled() { @@ -69,3 +68,8 @@ async function cookiesBlocked() { return true; } + +async function isActiveWindowPrivate() { + const activeWindow = await browser.windows.getCurrent(); + return activeWindow.incognito; +} From d736741baed018087b32811a24fbff461225ba32 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Tue, 20 Nov 2018 13:19:04 -0800 Subject: [PATCH 083/140] Incorporate Osmose's feedback --- src/privacy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/privacy.js b/src/privacy.js index f2218d8..444ce5f 100644 --- a/src/privacy.js +++ b/src/privacy.js @@ -44,7 +44,7 @@ export async function shouldCollectTelemetry(method) { * @return {boolean} */ export async function shouldUpdatePrices() { - return !isActiveWindowPrivate(); + return !(await isActiveWindowPrivate()); } async function trackingProtectionEnabled() { From e1d03913958648ee4b0b6e5fd4f8cf41ccf6ae60 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Fri, 16 Nov 2018 15:24:46 -0800 Subject: [PATCH 084/140] Update packages --- package-lock.json | 8 ++++---- package.json | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index bc32b5d..201134f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2519,7 +2519,7 @@ "color-support": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha1-k4NDeaHMmgxh+C9S8NBDIiUb1aI=", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true }, "colors": { @@ -2808,9 +2808,9 @@ "dev": true }, "cryptiles": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", - "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.4.tgz", + "integrity": "sha512-8I1sgZHfVwcSOY6mSGpVU3lw/GSIZvusg8dD2+OGehCJpOhQRLNcH0qb9upQnOH4XhgxxFJSg6E2kx95deb1Tw==", "dev": true, "requires": { "boom": "5.x.x" diff --git a/package.json b/package.json index 68e69f5..9f9ac9c 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "web-ext": "2.7.0", "webpack": "4.15.1", "webpack-command": "0.3.1", - "webpack-merge": "^4.1.4" + "webpack-merge": "4.1.4" }, "dependencies": { "autobind-decorator": "2.1.0", @@ -54,7 +54,7 @@ "fathom-web": "2.8.0", "lodash.maxby": "4.6.0", "lodash.minby": "4.6.0", - "lodash.orderby": "^4.6.0", + "lodash.orderby": "4.6.0", "prop-types": "15.6.2", "react": "16.4.1", "react-dom": "16.4.1", From 3109a9a9f77507354b9f9dfb2d0c7d054eccaeb9 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Mon, 26 Nov 2018 09:38:09 -0800 Subject: [PATCH 085/140] Update packages --- package-lock.json | 2096 +++++++++++++++++++++++++++++---------------- package.json | 2 +- 2 files changed, 1354 insertions(+), 744 deletions(-) diff --git a/package-lock.json b/package-lock.json index 201134f..f33cf85 100644 --- a/package-lock.json +++ b/package-lock.json @@ -111,6 +111,69 @@ } } }, + "@babel/polyfill": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.0.0.tgz", + "integrity": "sha512-dnrMRkyyr74CRelJwvgnnSUDh2ge2NCTyHVwpOdvRMHtJUyxLtMAfhBN3s64pY41zdw0kgiLPh6S20eb1NcX6Q==", + "dev": true, + "requires": { + "core-js": "^2.5.7", + "regenerator-runtime": "^0.11.1" + }, + "dependencies": { + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", + "dev": true + } + } + }, + "@babel/register": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.0.0.tgz", + "integrity": "sha512-f/+CRmaCe7rVEvcvPvxeA8j5aJhHC3aJie7YuqcMDhUOuyWLA7J/aNrTaHIzoWPEhpHA54mec4Mm8fv8KBlv3g==", + "dev": true, + "requires": { + "core-js": "^2.5.7", + "find-cache-dir": "^1.0.0", + "home-or-tmp": "^3.0.0", + "lodash": "^4.17.10", + "mkdirp": "^0.5.1", + "pirates": "^4.0.0", + "source-map-support": "^0.5.9" + }, + "dependencies": { + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", + "dev": true + }, + "home-or-tmp": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-3.0.0.tgz", + "integrity": "sha1-V6j+JM8zzdUkhgoVgh3cJchmcfs=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, "@babel/template": { "version": "7.0.0-beta.44", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.44.tgz", @@ -636,6 +699,12 @@ } } }, + "@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, "JSONSelect": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.2.1.tgz", @@ -668,11 +737,19 @@ } }, "acorn-globals": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.1.0.tgz", - "integrity": "sha512-KjZwU26uG3u6eZcfGbTULzFcsoz6pegNKtHPksZPOUsiKo5bUmiBPa38FuHZ/Eun+XYh/JCCkS9AS3Lu4McQOQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.0.tgz", + "integrity": "sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw==", "requires": { - "acorn": "^5.0.0" + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.4.tgz", + "integrity": "sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg==" + } } }, "acorn-jsx": { @@ -692,6 +769,11 @@ } } }, + "acorn-walk": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", + "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==" + }, "adbkit": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/adbkit/-/adbkit-2.11.0.tgz", @@ -731,62 +813,86 @@ } }, "addons-linter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/addons-linter/-/addons-linter-1.0.0.tgz", - "integrity": "sha512-6cC0Jcf0vMVgE86TV4A1lfjx78Fp0JltA1UH2icz/cALWMMfDZrD7YpB4dMrpobclsbKFPHexNOYhS4efAc5ng==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/addons-linter/-/addons-linter-1.3.8.tgz", + "integrity": "sha512-NFon8Q++k8R6t1lunNPoVPWxVUzC8ED5Cu8VB66HdsaVarLHNhIdpDSqClplefC5Mypx/EEgZhkMZAuaxScyUg==", "dev": true, "requires": { - "ajv": "6.5.0", - "ajv-merge-patch": "3.0.0", - "babel-register": "6.26.0", + "@babel/polyfill": "7.0.0", + "@babel/register": "7.0.0", + "ajv": "6.5.4", + "ajv-merge-patch": "4.1.0", "chalk": "2.4.0", "cheerio": "1.0.0-rc.2", "columnify": "1.5.4", - "common-tags": "1.7.2", + "common-tags": "1.8.0", "crx-parser": "0.1.2", - "deepmerge": "2.1.0", - "dispensary": "0.18.0", - "doctoc": "1.3.1", + "deepmerge": "2.2.1", + "dispensary": "0.26.0", "es6-promisify": "5.0.0", - "eslint": "4.19.1", + "eslint": "5.0.1", "eslint-plugin-no-unsafe-innerhtml": "1.0.16", + "eslint-visitor-keys": "1.0.0", + "espree": "4.0.0", "esprima": "3.1.3", "first-chunk-stream": "2.0.0", - "fluent-syntax": "^0.7.0", - "glob": "7.1.2", + "fluent-syntax": "0.7.0", + "fsevents": "1.2.4", + "glob": "7.1.3", "is-mergeable-object": "1.1.0", "jed": "1.1.1", - "os-locale": "2.1.0", - "pino": "4.16.1", + "os-locale": "3.0.1", + "pino": "5.5.0", "po2json": "0.4.5", - "postcss": "6.0.19", + "postcss": "7.0.5", "probe-image-size": "4.0.0", "relaxed-json": "1.0.1", - "semver": "5.5.0", - "shelljs": "0.8.1", - "snyk": "^1.78.1", + "semver": "5.6.0", + "shelljs": "0.8.2", + "snyk": "1.103.2", "source-map-support": "0.5.6", "strip-bom-stream": "3.0.0", "tosource": "1.0.0", - "upath": "1.0.5", - "whatwg-url": "6.4.1", + "upath": "1.1.0", + "whatwg-url": "7.0.0", "xmldom": "0.1.27", - "yargs": "11.0.0", - "yauzl": "2.9.1" + "yargs": "12.0.2", + "yauzl": "2.9.2" }, "dependencies": { + "acorn-jsx": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz", + "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==", + "dev": true, + "requires": { + "acorn": "^5.0.3" + } + }, "ajv": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.0.tgz", - "integrity": "sha512-VDUX1oSajablmiyFyED9L1DFndg0P9h7p1F+NO8FkIzei6EPrR6Zu1n18rd5P8PqaSRd/FrWv3G1TVBqpM83gA==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz", + "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0", - "uri-js": "^4.2.1" + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "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", @@ -807,6 +913,103 @@ "supports-color": "^5.3.0" } }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", + "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", + "dev": true, + "requires": { + "xregexp": "4.0.0" + } + }, + "eslint": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.0.1.tgz", + "integrity": "sha512-D5nG2rErquLUstgUaxJlWB5+gu+U/3VDY0fk/Iuq8y9CUFy/7Y6oF4N2cR1tV8knzQvciIbfqfohd359xTLIKQ==", + "dev": true, + "requires": { + "ajv": "^6.5.0", + "babel-code-frame": "^6.26.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^3.1.0", + "doctrine": "^2.1.0", + "eslint-scope": "^4.0.0", + "eslint-visitor-keys": "^1.0.0", + "espree": "^4.0.0", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.5.0", + "ignore": "^3.3.3", + "imurmurhash": "^0.1.4", + "inquirer": "^5.2.0", + "is-resolvable": "^1.1.0", + "js-yaml": "^3.11.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.5", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "regexpp": "^1.1.0", + "require-uncached": "^1.0.3", + "semver": "^5.5.0", + "string.prototype.matchall": "^2.0.0", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^4.0.3", + "text-table": "^0.2.0" + } + }, + "eslint-scope": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "espree": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz", + "integrity": "sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==", + "dev": true, + "requires": { + "acorn": "^5.6.0", + "acorn-jsx": "^4.1.1" + } + }, "esprima": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", @@ -819,17 +1022,132 @@ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", "dev": true }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "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" + } + }, + "globals": { + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.9.0.tgz", + "integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==", + "dev": true + }, + "inquirer": { + "version": "5.2.0", + "resolved": "http://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", + "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.1.0", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^5.5.2", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + } + }, + "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 + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "p-limit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", + "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + }, "postcss": { - "version": "6.0.19", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.19.tgz", - "integrity": "sha512-f13HRz0HtVwVaEuW6J6cOUCBLFtymhgyLPV7t4QEk2UD3twRI9IluDcQNdzQdBpiixkXj2OmzejhhTbSbDxNTg==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.5.tgz", + "integrity": "sha512-HBNpviAUFCKvEh7NZhw1e8MBPivRszIiUnhrJ+sBFVSYSqubrzwX3KG51mYgcRHX8j/cAgZJedONZcm5jTBdgQ==", "dev": true, "requires": { - "chalk": "^2.3.1", + "chalk": "^2.4.1", "source-map": "^0.6.1", - "supports-color": "^5.2.0" + "supports-color": "^5.5.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -846,56 +1164,87 @@ "source-map": "^0.6.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.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "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" } }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "table": { + "version": "4.0.3", + "resolved": "http://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" + } + }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "dev": true + }, + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "xregexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", + "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", "dev": true }, "yargs": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.0.0.tgz", - "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz", + "integrity": "sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==", "dev": true, "requires": { "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", + "decamelize": "^2.0.0", + "find-up": "^3.0.0", "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", + "os-locale": "^3.0.0", "require-directory": "^2.1.1", "require-main-filename": "^1.0.1", "set-blocking": "^2.0.0", "string-width": "^2.0.0", "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^9.0.2" - } - }, - "yargs-parser": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", - "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", - "dev": true, - "requires": { - "camelcase": "^4.1.0" + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^10.1.0" } } } }, "adm-zip": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.11.tgz", - "integrity": "sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA==", + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.13.tgz", + "integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==", "dev": true }, "agent-base": { @@ -911,6 +1260,7 @@ "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, "requires": { "co": "^4.6.0", "fast-deep-equal": "^1.0.0", @@ -925,32 +1275,15 @@ "dev": true }, "ajv-merge-patch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ajv-merge-patch/-/ajv-merge-patch-3.0.0.tgz", - "integrity": "sha1-dvBx45H0Gf6f4/6n6SChrYJLK2E=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ajv-merge-patch/-/ajv-merge-patch-4.1.0.tgz", + "integrity": "sha512-0mAYXMSauA8RZ7r+B4+EAOYcZEcO9OK5EiQCR7W7Cv4E44pJj56ZnkKLJ9/PAcOc0dT+LlV9fdDcq2TxVJfOYw==", "dev": true, "requires": { - "fast-json-patch": "^1.0.0", + "fast-json-patch": "^2.0.6", "json-merge-patch": "^0.2.3" } }, - "anchor-markdown-header": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/anchor-markdown-header/-/anchor-markdown-header-0.5.7.tgz", - "integrity": "sha1-BFBj125qH5zTJ6V6ASaqD97Dcac=", - "dev": true, - "requires": { - "emoji-regex": "~6.1.0" - }, - "dependencies": { - "emoji-regex": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.3.tgz", - "integrity": "sha1-7HmjlpsC0uzytyJUJ5v5m8eoOTI=", - "dev": true - } - } - }, "ansi-align": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", @@ -1113,6 +1446,12 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "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-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", @@ -1256,9 +1595,9 @@ "dev": true }, "ast-types": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.5.tgz", - "integrity": "sha512-oJjo+5e7/vEc2FBK8gUalV0pba4L3VdBIs2EKhOLHLcOd2FgQIVQN9xb0eZ9IjEWyAL7vq6fGJxOvVvdCHNyMw==", + "version": "0.11.7", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.7.tgz", + "integrity": "sha512-2mP3TwtkY/aTv5X3ZsMpNAbOnyoC/aMJwJSoaELPkHId0nSQgFcnU4dRW3isxiz7+zBexk0ym3WNVjMiQBnJSw==", "dev": true }, "ast-types-flow": { @@ -1320,9 +1659,10 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", - "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true }, "axobject-query": { "version": "0.1.0", @@ -1843,39 +2183,6 @@ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", "dev": true }, - "boom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", - "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "dev": true, - "requires": { - "hoek": "4.x.x" - } - }, - "bops": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/bops/-/bops-0.1.1.tgz", - "integrity": "sha1-Bi4CqNqoAfoQ8uXb5nQM/4Af4X4=", - "dev": true, - "requires": { - "base64-js": "0.0.2", - "to-utf8": "0.0.1" - }, - "dependencies": { - "base64-js": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.2.tgz", - "integrity": "sha1-Ak8Pcq+iW3X5wO5zzU9V7Bvtl4Q=", - "dev": true - } - } - }, - "boundary": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/boundary/-/boundary-1.0.1.tgz", - "integrity": "sha1-TWfcJgLAzBbdm85+v4fpSCkPWBI=", - "dev": true - }, "boxen": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", @@ -1968,9 +2275,9 @@ "dev": true }, "browser-process-hrtime": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz", - "integrity": "sha1-Ql1opY00R/AqBKqJQYf86K+Le44=" + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==" }, "browserify-aes": { "version": "1.2.0", @@ -2477,7 +2784,8 @@ "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true }, "code-point-at": { "version": "1.1.0", @@ -2553,13 +2861,10 @@ "dev": true }, "common-tags": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.7.2.tgz", - "integrity": "sha512-joj9ZlUOjCrwdbmiLqafeUSgkUM74NqhLsZtSqDmhKudaIY197zTrb8JMl31fMnCUuxwFT23eC/oWvrZzDLRJQ==", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0" - } + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", + "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", + "dev": true }, "commondir": { "version": "1.0.1", @@ -2714,18 +3019,18 @@ } }, "crc": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.7.0.tgz", - "integrity": "sha512-ZwmUex488OBjSVOMxnR/dIa1yxisBMJNEi+UxzXpKhax8MPsQtoRQtl5Qgo+W7pcSVkRXa3BEVjaniaWKtvKvw==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", "dev": true, "requires": { "buffer": "^5.1.0" }, "dependencies": { "buffer": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.1.0.tgz", - "integrity": "sha512-YkIRgwsZwJWTnyQrsBTWefizHh+8GYj3kbL1BTiAQ/9pwpino0G7B2gp5tx/FUBqUlvtxV85KNR3mwfAtv15Yw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", "dev": true, "requires": { "base64-js": "^1.0.2", @@ -2807,26 +3112,6 @@ "integrity": "sha1-fu7tnt3JXiLBiTguNGJARKiaWm0=", "dev": true }, - "cryptiles": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.4.tgz", - "integrity": "sha512-8I1sgZHfVwcSOY6mSGpVU3lw/GSIZvusg8dD2+OGehCJpOhQRLNcH0qb9upQnOH4XhgxxFJSg6E2kx95deb1Tw==", - "dev": true, - "requires": { - "boom": "5.x.x" - }, - "dependencies": { - "boom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "dev": true, - "requires": { - "hoek": "4.x.x" - } - } - } - }, "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", @@ -2925,9 +3210,9 @@ "integrity": "sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog==" }, "cssstyle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.0.0.tgz", - "integrity": "sha512-Bpuh47j2mRMY60X90mXaJAEtJwxvA2roZzbgwAXYhMbmwmakdRr4Cq9L5SkleKJNLOKqHIa2YWyOXDX3VgggSQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.1.1.tgz", + "integrity": "sha512-364AI1l/M5TYcFH83JnOH/pSqgaNnKmYgKrm0didZMGKWjQB60dymwWy1rKUgL3J1ffdq9xVi2yGLHdSjjSNog==", "requires": { "cssom": "0.3.x" } @@ -2977,19 +3262,24 @@ "dev": true }, "data-urls": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.0.0.tgz", - "integrity": "sha512-ai40PPQR0Fn1lD2PPie79CibnlMN2AYiDhwFX/rZHVsxbs5kNJSjegqXIprhouGXlRdEnfybva7kqRGnB6mypA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", "requires": { - "abab": "^1.0.4", - "whatwg-mimetype": "^2.0.0", - "whatwg-url": "^6.4.0" + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" }, "dependencies": { - "abab": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", - "integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4=" + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } } } }, @@ -3068,9 +3358,9 @@ "dev": true }, "deepmerge": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.1.0.tgz", - "integrity": "sha512-Q89Z26KAfA3lpPGhbF6XMfYAm3jIV3avViy6KOJ2JLzFbeWHOvPQUu5aSJIWXap3gDZC2y1eF5HXEPI2wGqgvw==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", "dev": true }, "defaults": { @@ -3264,20 +3554,19 @@ "dev": true }, "dispensary": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/dispensary/-/dispensary-0.18.0.tgz", - "integrity": "sha512-ikVxjigcj4leoPgjqYcHV1YhmLEZ5eXMq30CIPTf1BniWrH1C0X35F5iVCa4U2/JXZYcQJyHWniSRSOpM+hiNw==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/dispensary/-/dispensary-0.26.0.tgz", + "integrity": "sha512-Cw0N6Hf8/y4vH9/NvDPGLd2+Mve9xs+41+sULJ4ODHuhZ+9CnJ2eMl2ju2udL/UACY0Vcxw3TzyoDRBNaU/0DQ==", "dev": true, "requires": { "array-from": "~2.1.1", "async": "~2.6.0", "natural-compare-lite": "~1.4.0", - "pino": "~4.16.1", - "request": "~2.85.0", - "semver": "~5.5.0", + "pino": "~5.8.0", + "request": "~2.88.0", "sha.js": "~2.4.4", "source-map-support": "~0.5.4", - "yargs": "~11.0.0" + "yargs": "~12.0.1" }, "dependencies": { "async": { @@ -3289,6 +3578,81 @@ "lodash": "^4.17.10" } }, + "camelcase": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", + "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", + "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + }, + "pino": { + "version": "5.8.1", + "resolved": "https://registry.npmjs.org/pino/-/pino-5.8.1.tgz", + "integrity": "sha512-7bVFzUw3ffIfOM3t7MuQ9KsH+wX5bdGdQhGfccKgleoY7qG4FO3CmVSjywlFmmYGyMOISi1LDGC6JMEH7XkZJg==", + "dev": true, + "requires": { + "fast-json-parse": "^1.0.3", + "fast-redact": "^1.2.0", + "fast-safe-stringify": "^2.0.6", + "flatstr": "^1.0.5", + "pino-std-serializers": "^2.3.0", + "pump": "^3.0.0", + "quick-format-unescaped": "^3.0.0", + "sonic-boom": "^0.6.1" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -3296,74 +3660,47 @@ "dev": true }, "source-map-support": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz", - "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", "dev": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, "yargs": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.0.0.tgz", - "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==", + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", "dev": true, "requires": { "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", + "os-locale": "^3.0.0", "require-directory": "^2.1.1", "require-main-filename": "^1.0.1", "set-blocking": "^2.0.0", "string-width": "^2.0.0", "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^9.0.2" + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" } }, "yargs-parser": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", - "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", "dev": true, "requires": { - "camelcase": "^4.1.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } }, - "doctoc": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/doctoc/-/doctoc-1.3.1.tgz", - "integrity": "sha1-8BLjYD4xViVMLvIqyIxxkPVUJro=", - "dev": true, - "requires": { - "anchor-markdown-header": "^0.5.5", - "htmlparser2": "~3.9.2", - "markdown-to-ast": "~3.4.0", - "minimist": "~1.2.0", - "underscore": "~1.8.3", - "update-section": "^0.3.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -3707,9 +4044,9 @@ }, "dependencies": { "es6-promise": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", - "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", + "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", "dev": true } } @@ -4512,7 +4849,8 @@ "extend": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true }, "extend-shallow": { "version": "3.0.2", @@ -4619,7 +4957,8 @@ "fast-deep-equal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true }, "fast-glob": { "version": "2.2.2", @@ -4665,10 +5004,13 @@ "dev": true }, "fast-json-patch": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-1.2.2.tgz", - "integrity": "sha1-03fZfGkR290qHIC/rNoEik+Du/k=", - "dev": true + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-2.0.7.tgz", + "integrity": "sha512-DQeoEyPYxdTtfmB3yDlxkLyKTdbJ6ABfFGcMynDqjvGhPYLto/pZyb/dG2Nyd/n9CArjEWN9ZST++AFmgzgbGw==", + "dev": true, + "requires": { + "deep-equal": "^1.0.1" + } }, "fast-json-stable-stringify": { "version": "2.0.0", @@ -4680,10 +5022,16 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, + "fast-redact": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-1.4.0.tgz", + "integrity": "sha512-WsYhPdWJY+6d/pFJbBNWGUd5ENrBAJ6e7yDWcYNoFZoIQUUbKxnIRGS4d0kZkQlMPB4cLK3r4A0BZXpFxdoGhg==", + "dev": true + }, "fast-safe-stringify": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-1.2.3.tgz", - "integrity": "sha512-QJYT/i0QYoiZBQ71ivxdyTqkwKkQ0oxACXHYxH2zYHJEgzi2LsbjgvtzTbLi1SZcF190Db2YP7I7eTsU2egOlw==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz", + "integrity": "sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg==", "dev": true }, "fastparse": { @@ -4693,9 +5041,9 @@ "dev": true }, "fathom-web": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/fathom-web/-/fathom-web-2.3.0.tgz", - "integrity": "sha512-334TqwHCTnk+HZGhNUdLId+4qvcK0Ft87K8b4210WgFoxOlbL4tjbufbxo8WTQrCdH9PJE+oOPKgEEMD+SAPuQ==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/fathom-web/-/fathom-web-2.8.0.tgz", + "integrity": "sha512-BuBPlRwXEMLqndkuTEsjed8lqpSKvSWLJyd0ENCj0dzu3lHEHZZoNaOnf+uwwLGQfhWlzoWXWWFAp3lkWUBrvg==", "requires": { "jsdom": "^11.2.0", "wu": "^2.1.0" @@ -4716,9 +5064,9 @@ } }, "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", "dev": true, "requires": { "pend": "~1.2.0" @@ -4805,9 +5153,9 @@ } }, "firefox-profile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/firefox-profile/-/firefox-profile-1.1.0.tgz", - "integrity": "sha512-wUIE4QeAjwoHvFbomWmXgKyYtV4/oZxDcJG4znxtGGa/0BhKkd3HzeOf3tAsMWPq1ExARZxCRRiNw1BL3FuPqA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/firefox-profile/-/firefox-profile-1.2.0.tgz", + "integrity": "sha512-TTEFfPOkyaz4EWx/5ZDQC1mJAe3a+JgVcchpIfD4Tvx1UspwlTJRJxOYA35x/z2iJcxaF6aW2rdh6oj6qwgd2g==", "dev": true, "requires": { "adm-zip": "~0.4.x", @@ -4832,17 +5180,6 @@ "lodash": "^4.14.0" } }, - "fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", @@ -4965,9 +5302,9 @@ "dev": true }, "fs-extra": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", - "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", "dev": true, "requires": { "graceful-fs": "^4.1.2", @@ -5624,10 +5961,13 @@ } }, "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true + "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-json-webpack-plugin": { "version": "0.3.1", @@ -5904,12 +6244,39 @@ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, "requires": { - "ajv": "^5.1.0", + "ajv": "^6.5.5", "har-schema": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.5.tgz", + "integrity": "sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "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 + } } }, "has": { @@ -6017,18 +6384,6 @@ "minimalistic-assert": "^1.0.1" } }, - "hawk": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", - "dev": true, - "requires": { - "boom": "4.x.x", - "cryptiles": "3.x.x", - "hoek": "4.x.x", - "sntp": "2.x.x" - } - }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -6040,12 +6395,6 @@ "minimalistic-crypto-utils": "^1.0.1" } }, - "hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", - "dev": true - }, "hoist-non-react-statics": { "version": "2.5.5", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz", @@ -6155,13 +6504,19 @@ }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true } } }, @@ -6206,6 +6561,12 @@ "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", "dev": true }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", + "dev": true + }, "import-lazy": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-3.1.0.tgz", @@ -6351,9 +6712,9 @@ } }, "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=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, "ip": { @@ -6598,9 +6959,9 @@ "dev": true }, "is-my-json-valid": { - "version": "2.17.2", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", - "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz", + "integrity": "sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q==", "dev": true, "requires": { "generate-function": "^2.0.0", @@ -6928,36 +7289,105 @@ "xml-name-validator": "^3.0.0" }, "dependencies": { + "ajv": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.5.tgz", + "integrity": "sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg==", + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "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" + } + }, + "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==" + }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "requires": { + "mime-db": "~1.37.0" + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, "parse5": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==" }, "request": { - "version": "2.87.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", - "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "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.6.0", + "aws4": "^1.8.0", "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.1", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", "forever-agent": "~0.6.1", - "form-data": "~2.3.1", - "har-validator": "~5.0.3", + "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.17", - "oauth-sign": "~0.8.2", - "performance-now": "^2.1.0", - "qs": "~6.5.1", - "safe-buffer": "^5.1.1", - "tough-cookie": "~2.3.3", + "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.1.0" + "uuid": "^3.3.2" + }, + "dependencies": { + "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" + } + } } } } @@ -6991,7 +7421,8 @@ "json-schema-traverse": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true }, "json-stable-stringify": { "version": "1.0.1", @@ -7087,12 +7518,56 @@ } }, "jszip": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-2.6.1.tgz", - "integrity": "sha1-uI86ey5noqBIFSmCx6N1bZxIKPA=", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.1.5.tgz", + "integrity": "sha512-5W8NUaFRFRqTOL7ZDDrx5qWHJyBXy6velVudIzQUSoqAAYqzSh2Z7/m0Rf1QbmQJccegD0r+YZxBjzqoBiEeJQ==", "dev": true, "requires": { - "pako": "~1.0.2" + "core-js": "~2.3.0", + "es6-promise": "~3.0.2", + "lie": "~3.1.0", + "pako": "~1.0.2", + "readable-stream": "~2.0.6" + }, + "dependencies": { + "core-js": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz", + "integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU=", + "dev": true + }, + "es6-promise": { + "version": "3.0.2", + "resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", + "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + }, + "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 + } } }, "jwa": { @@ -7153,12 +7628,12 @@ } }, "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", "dev": true, "requires": { - "invert-kv": "^1.0.0" + "invert-kv": "^2.0.0" } }, "left-pad": { @@ -7175,6 +7650,15 @@ "type-check": "~0.3.2" } }, + "lie": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", + "dev": true, + "requires": { + "immediate": "~3.0.5" + } + }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -7250,6 +7734,12 @@ "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", "dev": true }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", + "dev": true + }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -7465,6 +7955,15 @@ "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", "dev": true }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -7498,102 +7997,6 @@ "integrity": "sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==", "dev": true }, - "markdown-to-ast": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/markdown-to-ast/-/markdown-to-ast-3.4.0.tgz", - "integrity": "sha1-Diy6gTkLBUmpFT7DsNkVthwWS+c=", - "dev": true, - "requires": { - "debug": "^2.1.3", - "remark": "^5.0.1", - "structured-source": "^3.0.2", - "traverse": "^0.6.6" - }, - "dependencies": { - "longest-streak": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-1.0.0.tgz", - "integrity": "sha1-0GWXxNTDG1LMsfXY+P5xSOr9aWU=", - "dev": true - }, - "markdown-table": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-0.4.0.tgz", - "integrity": "sha1-iQwsGzv+g/sA5BKbjkz+ZFJw+dE=", - "dev": true - }, - "remark": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/remark/-/remark-5.1.0.tgz", - "integrity": "sha1-y0Y709vLS5l5STXu4c9x16jjBow=", - "dev": true, - "requires": { - "remark-parse": "^1.1.0", - "remark-stringify": "^1.1.0", - "unified": "^4.1.1" - } - }, - "remark-parse": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-1.1.0.tgz", - "integrity": "sha1-w8oQ+ajaBGFcKPCapOMEUQUm7CE=", - "dev": true, - "requires": { - "collapse-white-space": "^1.0.0", - "extend": "^3.0.0", - "parse-entities": "^1.0.2", - "repeat-string": "^1.5.4", - "trim": "0.0.1", - "trim-trailing-lines": "^1.0.0", - "unherit": "^1.0.4", - "unist-util-remove-position": "^1.0.0", - "vfile-location": "^2.0.0" - } - }, - "remark-stringify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-1.1.0.tgz", - "integrity": "sha1-pxBeJbnuK/mkm3XSxCPxGwauIJI=", - "dev": true, - "requires": { - "ccount": "^1.0.0", - "extend": "^3.0.0", - "longest-streak": "^1.0.0", - "markdown-table": "^0.4.0", - "parse-entities": "^1.0.2", - "repeat-string": "^1.5.4", - "stringify-entities": "^1.0.1", - "unherit": "^1.0.4" - } - }, - "traverse": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", - "dev": true - }, - "unified": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/unified/-/unified-4.2.1.tgz", - "integrity": "sha1-dv9Dqo2kMPbn5KVchOusKtLPzS4=", - "dev": true, - "requires": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "has": "^1.0.1", - "once": "^1.3.3", - "trough": "^1.0.0", - "vfile": "^1.0.0" - } - }, - "vfile": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-1.4.0.tgz", - "integrity": "sha1-wP1vpIT43r23cfaMMe112I2pf+c=", - "dev": true - } - } - }, "math-random": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", @@ -7633,12 +8036,14 @@ "dev": true }, "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz", + "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.0.0", + "p-is-promise": "^1.1.0" } }, "memory-fs": { @@ -7980,6 +8385,18 @@ "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.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", @@ -8108,6 +8525,12 @@ "wrap-ansi": "^2.0.0" } }, + "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 + }, "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", @@ -8117,6 +8540,15 @@ "number-is-nan": "^1.0.0" } }, + "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" + } + }, "os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", @@ -8199,9 +8631,9 @@ } }, "needle": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.1.tgz", - "integrity": "sha512-t/ZswCM9JTWjAdXS9VpvqhI2Ct2sL2MdY4fUXqGJaGBk13ge99ObqRksRTbBE56K+wxUXwwfZYOuZHifFW9q+Q==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.4.tgz", + "integrity": "sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==", "dev": true, "requires": { "debug": "^2.1.2", @@ -8227,6 +8659,12 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, "node-fetch": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", @@ -8237,9 +8675,9 @@ } }, "node-forge": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", - "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.6.tgz", + "integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw==", "dev": true }, "node-libs-browser": { @@ -8273,6 +8711,12 @@ "vm-browserify": "0.0.4" } }, + "node-modules-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", + "dev": true + }, "node-notifier": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.2.1.tgz", @@ -8317,12 +8761,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", "dev": true - }, - "underscore": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", - "dev": true } } }, @@ -8396,14 +8834,15 @@ "dev": true }, "nwsapi": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.0.7.tgz", - "integrity": "sha512-VZXniaaaORAXGCNsvUNefsKRQYk8zCzQZ57jalgrpHcU70OrAzKAiN/3plYtH/VPRmZeYyUzQiYfKzcMXC1g5Q==" + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.0.9.tgz", + "integrity": "sha512-nlWFSCTYQcHk/6A9FFnfhKc14c3aFhfdNBXgo8Qgi9QTBu/qg3Ww+Uiz9wMzXd1T8GFxPc2QIHB6Qtf2XFryFQ==" }, "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true }, "object-assign": { "version": "4.1.1", @@ -8636,14 +9075,44 @@ "dev": true }, "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz", + "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==", "dev": true, "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" + "execa": "^0.10.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", + "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + } } }, "os-name": { @@ -8668,12 +9137,24 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, + "p-is-promise": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "dev": true + }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -8715,13 +9196,19 @@ }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true } } }, @@ -8954,41 +9441,21 @@ } }, "pino": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/pino/-/pino-4.16.1.tgz", - "integrity": "sha512-ST/IC5RMyqrOZL+Hq6LDwz5h4fGKABXzx2/5Ze7rz5TjuPvE8uI72dzj409xkq9JjyWsKoOOApgXn8kEjJ73yg==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-5.5.0.tgz", + "integrity": "sha512-cCaBKVwutiaGwgKXyOvsRSCeBxgi2j0X1PEK1cog1/9SMDhgL8+iJwWvTKUef20HDyGfZIUq5KaH0ZOhWLHYSw==", "dev": true, "requires": { - "chalk": "^2.3.2", "fast-json-parse": "^1.0.3", - "fast-safe-stringify": "^1.2.3", + "fast-redact": "^1.2.0", + "fast-safe-stringify": "^2.0.6", "flatstr": "^1.0.5", - "pino-std-serializers": "^2.0.0", + "pino-std-serializers": "^2.2.1", "pump": "^3.0.0", - "quick-format-unescaped": "^1.1.2", - "split2": "^2.2.0" + "quick-format-unescaped": "^3.0.0", + "sonic-boom": "^0.6.1" }, "dependencies": { - "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" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -8998,24 +9465,24 @@ "end-of-stream": "^1.1.0", "once": "^1.3.1" } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } } } }, "pino-std-serializers": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-2.1.0.tgz", - "integrity": "sha512-NqWvrQD/GpY78ybiNBzi/dg8ylERhDo6nB33j5sfCKpUmWLc3lYzeoBjyRoCMvEpDpL9lmH6ufRd0jw6rcd1pQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-2.3.0.tgz", + "integrity": "sha512-klfGoOsP6sJH7ON796G4xoUSx2fkpFgKHO4YVVO2zmz31jR+etzc/QzGJILaOIiCD6HTCFgkPx+XN8nk+ruqPw==", "dev": true }, + "pirates": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.0.tgz", + "integrity": "sha512-8t5BsXy1LUIjn3WWOlOuFDuKswhQb/tkak641lvBgmPOBUQHXveORtlMCp6OdPV1dtuTaEahKA8VNz6uLfKBtA==", + "dev": true, + "requires": { + "node-modules-regexp": "^1.0.0" + } + }, "pkg-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", @@ -9025,12 +9492,6 @@ "find-up": "^2.1.0" } }, - "pkginfo": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.4.1.tgz", - "integrity": "sha1-tUGO8EOd5UJfxJlQQtztFPsqhP8=", - "dev": true - }, "plur": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/plur/-/plur-3.0.1.tgz", @@ -9466,13 +9927,19 @@ }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true } } }, @@ -9494,6 +9961,11 @@ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + }, "public-encrypt": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", @@ -9551,13 +10023,10 @@ "dev": true }, "quick-format-unescaped": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-1.1.2.tgz", - "integrity": "sha1-DKWB3jF0vs7yWsPC6JVjQjgdtpg=", - "dev": true, - "requires": { - "fast-safe-stringify": "^1.0.8" - } + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-3.0.1.tgz", + "integrity": "sha512-Tnk4iJQ8x3V8ml3x9sLIf4tSDaVB9OJY/5gOrnxgK63CXKphhn8oYOPI4tqnXPQcZ3tCv7GFjeoYY5h6UAvuzg==", + "dev": true }, "quick-lru": { "version": "1.1.0", @@ -9891,6 +10360,15 @@ "safe-regex": "^1.1.0" } }, + "regexp.prototype.flags": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", + "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2" + } + }, "regexpp": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", @@ -10050,33 +10528,64 @@ "dev": true }, "request": { - "version": "2.85.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", - "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "dev": true, "requires": { "aws-sign2": "~0.7.0", - "aws4": "^1.6.0", + "aws4": "^1.8.0", "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.1", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", "forever-agent": "~0.6.1", - "form-data": "~2.3.1", - "har-validator": "~5.0.3", - "hawk": "~6.0.2", + "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.17", - "oauth-sign": "~0.8.2", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", "performance-now": "^2.1.0", - "qs": "~6.5.1", - "safe-buffer": "^5.1.1", - "stringstream": "~0.0.5", - "tough-cookie": "~2.3.3", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", "tunnel-agent": "^0.6.0", - "uuid": "^3.1.0" + "uuid": "^3.3.2" + }, + "dependencies": { + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", + "dev": true + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "dev": true, + "requires": { + "mime-db": "~1.37.0" + } + }, + "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==", + "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + } } }, "request-promise-core": { @@ -10244,6 +10753,23 @@ "rx-lite": "*" } }, + "rxjs": { + "version": "5.5.12", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", + "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", + "dev": true, + "requires": { + "symbol-observable": "1.0.1" + }, + "dependencies": { + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", + "dev": true + } + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -10451,9 +10977,9 @@ } }, "shelljs": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz", - "integrity": "sha512-YA/iYtZpzFe5HyWVGrb02FjPxc4EMCfpoU/Phg9fQoyMC72u9598OUBrsU8IrtwAKG0tO8IYaqbaLIw+k3IRGA==", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.2.tgz", + "integrity": "sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ==", "dev": true, "requires": { "glob": "^7.0.0", @@ -10508,6 +11034,16 @@ "integrity": "sha1-8JTHBB9mJZm7EnINoFnWucf/D0A=", "dev": true }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "dev": true, + "requires": { + "ajv": "^5.1.0", + "har-schema": "^2.0.0" + } + }, "mz": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.5.0.tgz", @@ -10519,6 +11055,12 @@ "thenify-all": "^1.0.0" } }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, "regenerator-runtime": { "version": "0.9.6", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.6.tgz", @@ -10693,24 +11235,15 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "sntp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", - "dev": true, - "requires": { - "hoek": "4.x.x" + "is-buffer": "^1.1.5" + } + } } }, "snyk": { - "version": "1.88.4", - "resolved": "https://registry.npmjs.org/snyk/-/snyk-1.88.4.tgz", - "integrity": "sha1-sCHrhh+G9cGNbsYo8Iqkk4Vy3Ng=", + "version": "1.103.2", + "resolved": "https://registry.npmjs.org/snyk/-/snyk-1.103.2.tgz", + "integrity": "sha512-rmMsNW94SQdmWQEtVDW1hiGKb3r7Gx1hVb0bTuK9mCm4/lHGmyuAG7QYdcwdhMrhGjg7yQDWCEXorEnq2JLs7Q==", "dev": true, "requires": { "abbrev": "^1.1.1", @@ -10721,28 +11254,30 @@ "hasbin": "^1.2.3", "inquirer": "^3.0.0", "lodash": "^4.17.5", - "needle": "^2.0.1", + "needle": "^2.2.4", "opn": "^5.2.0", "os-name": "^2.0.1", "proxy-agent": "^2.0.0", "proxy-from-env": "^1.0.0", "recursive-readdir": "^2.2.2", "semver": "^5.5.0", - "snyk-config": "2.1.0", - "snyk-docker-plugin": "1.10.3", - "snyk-go-plugin": "1.5.1", - "snyk-gradle-plugin": "1.3.0", + "snyk-config": "2.2.0", + "snyk-docker-plugin": "1.12.0", + "snyk-go-plugin": "1.5.2", + "snyk-gradle-plugin": "2.1.0", "snyk-module": "1.8.2", - "snyk-mvn-plugin": "1.2.0", - "snyk-nuget-plugin": "1.6.3", + "snyk-mvn-plugin": "2.0.0", + "snyk-nodejs-lockfile-parser": "1.5.1", + "snyk-nuget-plugin": "1.6.5", "snyk-php-plugin": "1.5.1", "snyk-policy": "1.12.0", - "snyk-python-plugin": "1.6.1", + "snyk-python-plugin": "1.8.2", "snyk-resolve": "1.0.1", - "snyk-resolve-deps": "3.1.0", - "snyk-sbt-plugin": "1.3.0", + "snyk-resolve-deps": "4.0.1", + "snyk-sbt-plugin": "2.0.0", "snyk-tree": "^1.0.0", "snyk-try-require": "1.3.1", + "source-map-support": "^0.5.9", "tempfile": "^2.0.0", "then-fs": "^2.0.0", "undefsafe": "^2.0.0", @@ -10770,18 +11305,40 @@ } }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "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" @@ -10790,82 +11347,64 @@ } }, "snyk-config": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/snyk-config/-/snyk-config-2.1.0.tgz", - "integrity": "sha512-D1Xz1pZa9lwA9AHogmAigyJGo/iuEGH+rcPB77mFsneVfnuiK9c6IjnsHbEBUf1cePtZvWdGBjs6e75Cvc2AMg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/snyk-config/-/snyk-config-2.2.0.tgz", + "integrity": "sha512-mq0wbP/AgjcmRq5i5jg2akVVV3iSYUPTowZwKn7DChRLDL8ySOzWAwan+ImXiyNbrWo87FNI/15O6MpOnTxOIg==", "dev": true, "requires": { "debug": "^3.1.0", + "lodash": "^4.17.5", "nconf": "^0.10.0" }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true } } }, "snyk-docker-plugin": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/snyk-docker-plugin/-/snyk-docker-plugin-1.10.3.tgz", - "integrity": "sha512-nIw6zS705SiQLEhBwoO2qsJ3lVN1DZ48tyMgqhlr5f5GuOrwUJ0ivUK5HQUI79xA6pF7tU18495OlbsKuEHUOw==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/snyk-docker-plugin/-/snyk-docker-plugin-1.12.0.tgz", + "integrity": "sha512-QqKq2bGdnf1L2PNGQrHoqcoaV/PIlJv1qjKIzwA93gfhToKGkgJ31oPXwfef/l9N+ui0Y44c4POBHFbFf8PlJw==", "dev": true, "requires": { - "debug": "^3.1.0", - "fs-extra": "^5.0.0", - "pkginfo": "^0.4.1", - "request": "^2.87.0", - "temp-dir": "^1.0.0" + "debug": "^3", + "tslib": "^1" }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, - "request": { - "version": "2.87.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", - "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.6.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.1", - "forever-agent": "~0.6.1", - "form-data": "~2.3.1", - "har-validator": "~5.0.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.17", - "oauth-sign": "~0.8.2", - "performance-now": "^2.1.0", - "qs": "~6.5.1", - "safe-buffer": "^5.1.1", - "tough-cookie": "~2.3.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.1.0" - } + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true } } }, "snyk-go-plugin": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/snyk-go-plugin/-/snyk-go-plugin-1.5.1.tgz", - "integrity": "sha512-8OPJOT05Z/UL5fFSXV6b/A6KjlS1Ahr2gpup1bhXtAGXlUUPyWidqkCIER9fexDXqYWgAoDAdn9YHIvmL/5bfw==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/snyk-go-plugin/-/snyk-go-plugin-1.5.2.tgz", + "integrity": "sha512-XWajcSh6Ld+I+WdcyU3DGDuE2ydThQd8ORkESy0nQ2LwekygLYVYN66OBy0uxpqYfd4qoqeg+J8lb4oGzCmyGA==", "dev": true, "requires": { "graphlib": "^2.1.1", @@ -10874,9 +11413,9 @@ } }, "snyk-gradle-plugin": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/snyk-gradle-plugin/-/snyk-gradle-plugin-1.3.0.tgz", - "integrity": "sha512-rKZcPwbDM9zk3pFcO0w77MIKOZTkk5ZBVBkBlTlUiFg+eNOKqPTmw2hBGF5NB4ASQmMnx3uB1C8+hrQ405CthA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/snyk-gradle-plugin/-/snyk-gradle-plugin-2.1.0.tgz", + "integrity": "sha512-9gYJluomFZ5kaww5FoBvp4zUIsr27pEJ12jQJaVf0FJ0BmyYHmbCoxvHdqjCSYS2fVtF+fmPnvw0XKQOIwA1SA==", "dev": true, "requires": { "clone-deep": "^0.3.0" @@ -10893,48 +11432,83 @@ }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true } } }, "snyk-mvn-plugin": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/snyk-mvn-plugin/-/snyk-mvn-plugin-1.2.0.tgz", - "integrity": "sha512-ieTWhn1MB88gEQ6nUtGCeUKQ6Xoxm+u+QmD9u3zfP1QS5ep9fWt3YYDUQjgUiDTJJy7QyVQdZ/fsz3RECnOA7w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/snyk-mvn-plugin/-/snyk-mvn-plugin-2.0.0.tgz", + "integrity": "sha512-9jAhZhv+7YcqtoQYCYlgMoxK+dWBKlk+wkX27Ebg3vNddNop9q5jZitRXTjsXwfSUZHRt+Ptw1f8vei9kjzZVg==", "dev": true }, + "snyk-nodejs-lockfile-parser": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/snyk-nodejs-lockfile-parser/-/snyk-nodejs-lockfile-parser-1.5.1.tgz", + "integrity": "sha512-rfFcW+ZrOEH3NxufUCpMBpNLSb4BPOxLbAM6MoRqfYH5DhSdTHsecwRDf1gU6XzQok/9Koav+1qtP8+welJC2A==", + "dev": true, + "requires": { + "@yarnpkg/lockfile": "^1.0.2", + "lodash": "4.17.10", + "path": "0.12.7", + "source-map-support": "^0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, "snyk-nuget-plugin": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/snyk-nuget-plugin/-/snyk-nuget-plugin-1.6.3.tgz", - "integrity": "sha512-sC590aveQb0ns7HuDheIZ7FhN/HZzWgzXKUnBGfia/SXIFBpQz/6tognraMJ4+877uLLSdsB2jkyDeHYeWICrg==", + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/snyk-nuget-plugin/-/snyk-nuget-plugin-1.6.5.tgz", + "integrity": "sha512-3qIndzkxCxiaGvAwMkqChbChGdwhNePPyfi0WjhC/nJGwecqU3Fb/NeTW7lgyT+xoq/dFnzW0DgBJ4+AyNA2gA==", "dev": true, "requires": { "debug": "^3.1.0", - "es6-promise": "^4.1.1", + "jszip": "^3.1.5", "lodash": "^4.17.10", - "xml2js": "^0.4.17", - "zip": "^1.2.0" + "xml2js": "^0.4.17" }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, - "es6-promise": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", - "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true } } @@ -10951,13 +11525,19 @@ }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true } } }, @@ -10979,20 +11559,26 @@ }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true } } }, "snyk-python-plugin": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/snyk-python-plugin/-/snyk-python-plugin-1.6.1.tgz", - "integrity": "sha512-6zr5jAB3p/bwMZQxZpdj+aPmioTgHB4DI6JMLInhZupss0x8Ome5YqzVzBbOvUKNrc3KaLtjGrJWcAuxDL6M/g==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/snyk-python-plugin/-/snyk-python-plugin-1.8.2.tgz", + "integrity": "sha512-LBvjztnXarSHKyhivzM567icOOLOB98I7S9EEnjepuG+EZ0jiZzqOEMVRmzuYi+hRq3Cwh0hhjkwgJAQpKDz+g==", "dev": true, "requires": { "tmp": "0.0.33" @@ -11009,31 +11595,38 @@ }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true } } }, "snyk-resolve-deps": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/snyk-resolve-deps/-/snyk-resolve-deps-3.1.0.tgz", - "integrity": "sha512-YVAelR+dTpqLgfk6lf6WgOlw+MGmGI0r3/Dny8tUbJJ9uVTHTRAOdZCbUyTFqJG7oEmEZxUwmfjqgAuniYwx8Q==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/snyk-resolve-deps/-/snyk-resolve-deps-4.0.1.tgz", + "integrity": "sha512-gieaYoOuJLXzUmDDKfQJAqfwaxa43KmSqN2d9abRfgMXnLlX9IqyoZ1wqZMbd3WN7tsHSkpWvVwc4FHdQEkUKA==", "dev": true, "requires": { "ansicolors": "^0.3.2", - "debug": "^3.1.0", + "debug": "^3.2.5", "lodash.assign": "^4.2.0", "lodash.assignin": "^4.2.0", + "lodash.clone": "^4.5.0", "lodash.flatten": "^4.4.0", "lodash.get": "^4.4.2", "lodash.set": "^4.3.2", "lru-cache": "^4.0.0", - "semver": "^5.1.0", + "semver": "^5.5.1", "snyk-module": "^1.6.0", "snyk-resolve": "^1.0.0", "snyk-tree": "^1.0.0", @@ -11042,24 +11635,33 @@ }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true } } }, "snyk-sbt-plugin": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/snyk-sbt-plugin/-/snyk-sbt-plugin-1.3.0.tgz", - "integrity": "sha512-SRxPB16392dvN3Qv2RfUcHe0XETLWx2kNIOuoNXvc2Gl6DuPW+X+meDJY7xC/yQhU7bSPPKoM2B7awYaj9i2Bg==", - "dev": true, - "requires": { - "debug": "^2.2.0" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/snyk-sbt-plugin/-/snyk-sbt-plugin-2.0.0.tgz", + "integrity": "sha512-bOUqsQ1Lysnwfnvf4QQIBfC0M0ZVuhlshTKd7pNwgAJ41YEPJNrPEpzOePl/HfKtwilEEwHh5YHvjYGegEKx0A==", + "dev": true }, "snyk-tree": { "version": "1.0.0", @@ -11083,13 +11685,19 @@ }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true } } }, @@ -11113,6 +11721,15 @@ "socks": "^1.1.10" } }, + "sonic-boom": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-0.6.3.tgz", + "integrity": "sha512-TMhj6kDJk9LLzCTTL8+HPCfFn4MwkE4P6k2Up89Rz949+DSRw90V62upRKC99rJEOmu4E9ljH5Otu2JSRmx+bg==", + "dev": true, + "requires": { + "flatstr": "^1.0.8" + } + }, "source-list-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", @@ -11219,15 +11836,6 @@ "extend-shallow": "^3.0.0" } }, - "split2": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", - "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", - "dev": true, - "requires": { - "through2": "^2.0.2" - } - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -11412,6 +12020,19 @@ } } }, + "string.prototype.matchall": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-2.0.0.tgz", + "integrity": "sha512-WoZ+B2ypng1dp4iFLF2kmZlwwlE19gmjgKuhL1FJfDgCREWb3ye3SDVHSzLH6bxfnvYmkCxbzkmWcQZHA4P//Q==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.10.0", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "regexp.prototype.flags": "^1.2.0" + } + }, "string.prototype.trim": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", @@ -11444,12 +12065,6 @@ "is-hexadecimal": "^1.0.0" } }, - "stringstream": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", - "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", - "dev": true - }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -11502,15 +12117,6 @@ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, - "structured-source": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/structured-source/-/structured-source-3.0.2.tgz", - "integrity": "sha1-3YAkJeD1PcSm56yjdSkBoczaevU=", - "dev": true, - "requires": { - "boundary": "^1.0.1" - } - }, "style-loader": { "version": "0.21.0", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.21.0.tgz", @@ -11803,17 +12409,17 @@ } }, "tar-stream": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz", - "integrity": "sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", "dev": true, "requires": { "bl": "^1.0.0", - "buffer-alloc": "^1.1.0", + "buffer-alloc": "^1.2.0", "end-of-stream": "^1.0.0", "fs-constants": "^1.0.0", "readable-stream": "^2.3.0", - "to-buffer": "^1.1.0", + "to-buffer": "^1.1.1", "xtend": "^4.0.0" } }, @@ -11987,12 +12593,6 @@ "repeat-string": "^1.6.1" } }, - "to-utf8": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/to-utf8/-/to-utf8-0.0.1.tgz", - "integrity": "sha1-0Xrqcv8vujm55DYBvns/9y4ImFI=", - "dev": true - }, "toml": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.3.tgz", @@ -12167,9 +12767,9 @@ } }, "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", "dev": true }, "unherit": { @@ -12440,17 +13040,10 @@ } } }, - "update-section": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/update-section/-/update-section-0.3.3.tgz", - "integrity": "sha1-RY8Xgg03gg3GDiC4bZQ5GwASMVg=", - "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" }, @@ -12458,8 +13051,7 @@ "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 + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" } } }, @@ -12622,15 +13214,15 @@ } }, "web-ext": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/web-ext/-/web-ext-2.7.0.tgz", - "integrity": "sha512-hXj/MV/x6G0oxplOirV4/j7BJ5MZJ2yZHml0gulBr7mH2BMNyTJHdRi+qzVBNPFdBMLV0/PS05YGZ7xr2YmwVA==", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/web-ext/-/web-ext-2.9.2.tgz", + "integrity": "sha512-eJYKR7BMlpWXSeOP91LvsQkLHKcRE8wWkQYdlEkHzntASlFMbGZcIk6/R5myA/Yo5E87WWoCmqKO9rdUSVtQMA==", "dev": true, "requires": { "@cliqz-oss/firefox-client": "0.3.1", "@cliqz-oss/node-firefox-connect": "1.2.1", "adbkit": "2.11.0", - "addons-linter": "1.0.0", + "addons-linter": "1.3.8", "babel-polyfill": "6.26.0", "babel-runtime": "6.26.0", "bunyan": "1.8.12", @@ -12640,11 +13232,11 @@ "es6-error": "4.1.1", "es6-promisify": "5.0.0", "event-to-promise": "0.8.0", - "firefox-profile": "1.1.0", + "firefox-profile": "1.2.0", "fx-runner": "1.0.9", "git-rev-sync": "1.9.1", - "minimatch": "3.0.4", "mkdirp": "0.5.1", + "multimatch": "2.1.0", "mz": "2.7.0", "node-notifier": "5.2.1", "opn": "5.3.0", @@ -13031,17 +13623,20 @@ } }, "whatwg-encoding": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.3.tgz", - "integrity": "sha512-jLBwwKUhi8WtBfsMQlL4bUUcT8sMkAtQinscJAe/M4KHCkHuUJAF6vuB0tueNIw4c8ziO6AkRmgY+jL3a0iiPw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", "requires": { - "iconv-lite": "0.4.19" + "iconv-lite": "0.4.24" }, "dependencies": { "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } } } }, @@ -13051,9 +13646,9 @@ "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" }, "whatwg-mimetype": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.1.0.tgz", - "integrity": "sha512-FKxhYLytBQiUKjkYteN71fAUA3g6KpNXoho1isLiLSB3N1G4F35Q5vUxWfKFhBwi5IWF27VE6WxhrnnC+m0Mew==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" }, "whatwg-url": { "version": "6.4.1", @@ -13312,6 +13907,12 @@ "pinkie-promise": "^2.0.0" } }, + "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 + }, "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", @@ -13321,6 +13922,15 @@ "number-is-nan": "^1.0.0" } }, + "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" + } + }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -13443,22 +14053,13 @@ } }, "yauzl": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz", - "integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.2.tgz", + "integrity": "sha1-T7G8euH8L1cDe1SvasyP4QMcW3c=", "dev": true, "requires": { "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.0.1" - } - }, - "zip": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/zip/-/zip-1.2.0.tgz", - "integrity": "sha1-rQrUImUwm+QutW/IYZThfCTmapw=", - "dev": true, - "requires": { - "bops": "~0.1.1" + "fd-slicer": "~1.1.0" } }, "zip-dir": { @@ -13476,6 +14077,15 @@ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true + }, + "jszip": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-2.6.1.tgz", + "integrity": "sha1-uI86ey5noqBIFSmCx6N1bZxIKPA=", + "dev": true, + "requires": { + "pako": "~1.0.2" + } } } }, diff --git a/package.json b/package.json index 9f9ac9c..9843bbd 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "stylelint-config-standard": "18.2.0", "tap-mocha-reporter": "3.0.7", "tape": "4.9.1", - "web-ext": "2.7.0", + "web-ext": "2.9.2", "webpack": "4.15.1", "webpack-command": "0.3.1", "webpack-merge": "4.1.4" From d409605737b22471333a9875c05553723f6f712c Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Tue, 27 Nov 2018 13:05:31 -0800 Subject: [PATCH 086/140] Require manual approval to upload XPI files to Test Pilot. --- .circleci/config.yml | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d1e0cf3..3445363 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -37,7 +37,7 @@ jobs: paths: - "*.zip" - deploy: + sign: docker: - image: circleci/python:2.7-node-browsers steps: @@ -60,12 +60,32 @@ jobs: -o "web-ext-artifacts/${XPI_NAME}-signed.xpi" \ -H "Authorization: ${AUTOGRAPH_EDGE_TOKEN}" \ ${AUTOGRAPH_EDGE_URL} - - run: - name: Upload XPI to S3 - command: .circleci/deploy_addon.sh + - persist_to_workspace: + root: web-ext-artifacts + paths: + - "*.xpi" - store_artifacts: path: web-ext-artifacts + upload: + docker: + - image: circleci/python:2.7-node-browsers + steps: + - checkout + - attach_workspace: + at: web-ext-artifacts + - run: + name: Store XPI name in environment variable + command: | + echo 'export XPI_NAME=price_wise-${CIRCLE_TAG:1}' >> $BASH_ENV + - run: + name: Install dependencies + command: | + pipenv install + - run: + name: Upload XPI to S3 + command: echo "hooray!" # .circleci/deploy_addon.sh + workflows: version: 2 build-deploy: @@ -74,7 +94,7 @@ workflows: filters: tags: only: /.*/ - - deploy: # runs only for tags starting with v + - sign: # runs only for tags starting with v requires: - build filters: @@ -82,3 +102,10 @@ workflows: only: /^v.*/ branches: ignore: /.*/ + - hold: # Require manual approval before uploading + type: approval + requires: + - sign + - upload: + requires: + - hold From ea9861acd1b6e20ff90fd9b1cb02cce93f259bc1 Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Tue, 27 Nov 2018 16:34:48 -0800 Subject: [PATCH 087/140] 15.1.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index f33cf85..6ceadb2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "15.0.0", + "version": "15.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 9843bbd..570b0fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "15.0.0", + "version": "15.1.0", "description": "Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy.", "private": true, "author": "Mozilla", From 4085708b5f83533e2a280a25ab0b724e583f288c Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Tue, 27 Nov 2018 16:38:22 -0800 Subject: [PATCH 088/140] Add filters to properly trigger new jobs as part of approval workflow. --- .circleci/config.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3445363..529f517 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -106,6 +106,16 @@ workflows: type: approval requires: - sign + filters: + tags: + only: /^v.*/ + branches: + ignore: /.*/ - upload: requires: - hold + filters: + tags: + only: /^v.*/ + branches: + ignore: /.*/ From dea92fc1352240cc4b40538097f8f4d91fc9a621 Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Tue, 27 Nov 2018 16:42:09 -0800 Subject: [PATCH 089/140] 15.2.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6ceadb2..90fdaeb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "15.1.0", + "version": "15.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 570b0fd..ee3a50c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "15.1.0", + "version": "15.2.0", "description": "Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy.", "private": true, "author": "Mozilla", From 3a614451f536346963920cc7e433dfc5105c67f5 Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Tue, 27 Nov 2018 16:46:59 -0800 Subject: [PATCH 090/140] Restore upload command in CircleCI deploy script. --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 529f517..a632f3a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -84,7 +84,7 @@ jobs: pipenv install - run: name: Upload XPI to S3 - command: echo "hooray!" # .circleci/deploy_addon.sh + command: .circleci/deploy_addon.sh workflows: version: 2 From fec9c8e4671323f7ca82350ef01a01c5c08759ff Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Tue, 27 Nov 2018 16:51:54 -0800 Subject: [PATCH 091/140] 16.0.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 90fdaeb..5fbee43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "15.2.0", + "version": "16.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index ee3a50c..70272eb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "15.2.0", + "version": "16.0.0", "description": "Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy.", "private": true, "author": "Mozilla", From 0f1bcd18d2f2dd58e9e2279d515987bb66548053 Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Tue, 27 Nov 2018 14:28:11 -0800 Subject: [PATCH 092/140] Fix #252: Add `fill-opacity="context-fill-opacity"` to SVG files. --- src/browser_action/index.css | 2 +- src/img/feedback.svg | 2 +- src/img/shopping_add.svg | 4 ++-- src/img/shopping_list.svg | 4 ++-- src/img/trash.svg | 2 +- src/img/undo.svg | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/browser_action/index.css b/src/browser_action/index.css index c281d34..3883657 100644 --- a/src/browser_action/index.css +++ b/src/browser_action/index.css @@ -101,7 +101,7 @@ a:focus { } .button.ghost .icon { - -moz-context-properties: fill; + -moz-context-properties: fill, fill-opacity; fill: var(--grey-90-a80); margin: 0; } diff --git a/src/img/feedback.svg b/src/img/feedback.svg index d2bdf69..8078e8b 100644 --- a/src/img/feedback.svg +++ b/src/img/feedback.svg @@ -2,5 +2,5 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - + diff --git a/src/img/shopping_add.svg b/src/img/shopping_add.svg index 7ff337c..bbc2d22 100644 --- a/src/img/shopping_add.svg +++ b/src/img/shopping_add.svg @@ -2,6 +2,6 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - - + + diff --git a/src/img/shopping_list.svg b/src/img/shopping_list.svg index 1e106b1..b0beb47 100644 --- a/src/img/shopping_list.svg +++ b/src/img/shopping_list.svg @@ -2,6 +2,6 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - - + + diff --git a/src/img/trash.svg b/src/img/trash.svg index ce8163d..cbfb5d9 100644 --- a/src/img/trash.svg +++ b/src/img/trash.svg @@ -1,4 +1,4 @@ - + diff --git a/src/img/undo.svg b/src/img/undo.svg index ad534df..c4d62f0 100644 --- a/src/img/undo.svg +++ b/src/img/undo.svg @@ -1,4 +1,4 @@ - \ No newline at end of file + From 4756acd0ad176174e3aaa1cc4ff934dcf599bb58 Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Tue, 27 Nov 2018 16:32:44 -0800 Subject: [PATCH 093/140] Fix #243: Serve vendor favicons locally instead of remotely. Tracking protection is blocking the eBay favicon from being loaded in private browsing mode, but serving it locally instead of fetching it from the internet avoids being blocked. --- src/img/favicons/amazon.ico | Bin 0 -> 17542 bytes src/img/favicons/bestbuy.ico | Bin 0 -> 4414 bytes src/img/favicons/ebay.ico | Bin 0 -> 1150 bytes src/img/favicons/homedepot.ico | Bin 0 -> 3638 bytes src/img/favicons/walmart.ico | Bin 0 -> 1150 bytes src/state/vendors.js | 10 +++++----- webpack/common.config.js | 1 + 7 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 src/img/favicons/amazon.ico create mode 100644 src/img/favicons/bestbuy.ico create mode 100644 src/img/favicons/ebay.ico create mode 100644 src/img/favicons/homedepot.ico create mode 100644 src/img/favicons/walmart.ico diff --git a/src/img/favicons/amazon.ico b/src/img/favicons/amazon.ico new file mode 100644 index 0000000000000000000000000000000000000000..20a959c12ff9a97e62c9ccb38c74bb0443957160 GIT binary patch literal 17542 zcmeI3U8r406~}iurn1Hkojo#>kicK1*2*!kpDBc*bdGOv+p|#{{&?p(#Z)UGOYtNq9=VPC9ngozyZ2Yshoy|Ls2-Ok^)qa7n_Bgm;VH5y4=1R>CJHVV6Aj zOSmB6cBP*Qu-!R5B>j^T=C<{p{_fl_|LWX#|LENJBs_J|xr67O``T;a{p1zre)~7) zuHPJNnzw|*$E*(W{*VOfY9@MlE8x8MjC0kCb$CHyA8v)1^d>FjdHCl+&&`=7Ht@s} z?taxlo@rxK5%$Bz_r7FsS&S_`5*=*5S|@b*(Y2{Wr9=|0O$v+4Ag?hLea&>>{q$5zrf<~Uy2eQCH+Ly$R8Txl7 z%`q<6_JWNH`sa!dN^8aksRP;@1Qx`+WNlCmt)7i(UOhLE&lOX--*LBx`G+Ha^*@Zzm|RS$s_Li z_3O)o?#`V%*I-h)Ay&*<4-vb~N4@Rax5wab=R0uVk)`UecdyD$@rJfqzG1Y0 zhi<=(G6VimRyKXITOZxB@LT@v z^Yk)_ei+7$ZrfKo_W3ex{EA!k7#7=dcBwv~7HwzWkHMFO|QDn0Yn&{MMHG zoYN(jruHAXRpQ46^yhqk=*QWv1J!pm?LSv{^a;it>{r4zIej(bPY!>YhM!9NV!R~K z_UW7N_WYaTob?@@bga=h9kXWTId6W(MetZVWA{EPk6WP+uVVZ>aiY8iVEx)hVgA+r z+U?`3Si{qnyL}NX!T+)IRjNxEtGc+AANnnuPMtcH!LMU@c^`zfm0!a|eO7^=u~O~T zjsp(*BjXIds_h?n?An$>O#W3+e$HxRY3nxm+kia>_Rrs%MQ`e0_wK&Ex5;?ZHRyo0 z^B2J`JI=FFXwSOm3EtR_r?-75!@9Yz-%mis`O#bpA9QHXsi_X>d$(TjIR@?-a(*|G z@Y)1Di=R)NIBxU+a|ySm$39+UI^Bm?&G|2zUN@#Imd{0f(2ki$3D!4QUw_1>@qIz# zjGR=s2NZvO4*VHOiwmYa%-bOq?Af~iZ^~O;0+L zt_89y%h2`_cR0#_TwJN!@o!+b?=tJNAIUlzuXnsk+gXTneadly+gpcb&1FW zZputqe%D`XJ5NQi_>%ZI_{8|p_&}T| zvbInC9?sMJnYG#DMStvx?Q?CXC|EuqTjg3GKKfxJzh8*29@k*Om&A7)O89(MZt1yw z{vCXB)~7=-^sS3oBg8%T?ixV-?E!1B`d)yZEk+r3Pli2CZ4=Qp!KdH1Z||UW2-qXf zC_i1>(B5+S*e@7D@oY@jC}3d9Xj8a95%DP&>Td|qc9fTm(>~X3CyKR;a~>@1wP?_h z{+ON#TYUOFkG!-Dx(0qxFXc}=q>be5zZm_&!#R0*uSs!r>p#_H$UAk+*qR$>w6CjO z)Luj6^_2w+^@8mQI!4AZIp0tEc=mmxzax*pd0~#)x-U+CZfr@%pU_Wf2O2_K$l;td zE!>Z2w=FyV!Y|Hy?R>M!%H`kK$lnj39a8VPxtY3PZ)8!V?Mv%8w6k)*BcI-@n}C76 zq2gU>EgOB1ewm6dtsmu+iCM#cHItrALZ`01BPPC0skid~qCC7;!bBTr0b<)9wNK75 z*Rk%ot6l>>AkQ;l0LK7AcI*E-@{S$8ETMckRz40S{G~J&isGMbf4n!2AzB`B)D0tbD3=sbp;Q2X&b=)*?j=k46Nl?yYN2{U5m1= zoZ|lRuZ8d3wJeDu!I!nVU#qfi)^)W02c=G94aNGohrS};S~dY&^Isz6tubI-^3+B{ z_}4o6H6eVchk!r&qx15o9_drq#omFWPgy>*a_F-pf;WB`$3trp)DPP~mY0MC4?Y<83wj%je78hi z%24*(_5;t%70liE1pXYQFwfOx-_Y{-7wP_Th3_QuCUddQm-q$*Ai9)-+_;w9n^k>?`O>Ul*K>U-ho@5@G;K39`vjKr|HWx&!h7s`m8i>`~YNwMaY*o z^Qs>!bdDgVZ_uBaE8cip{)@MH%kzMbmiJHfPaKz7GaqP;Y4A$O%eQIT&-Fhhc09|B zS)KB_wq`xg8V;Gt)5@uzJLTE?$nQywGsT1b><8UTVr*v|Q#@eEP)EM{K-iA|HR?O# zVTLGA8*C_y&)xY@eU&C-c%bYzlQh4_Pk#0Pdj4-f-=hzHM?$%mr2;};%J^|E84_lC F{U1e|rd0p{ literal 0 HcmV?d00001 diff --git a/src/img/favicons/bestbuy.ico b/src/img/favicons/bestbuy.ico new file mode 100644 index 0000000000000000000000000000000000000000..063a1b0781828333e35a27efe2b1a4fd4b698121 GIT binary patch literal 4414 zcmeH}KTE?v7{;$vixmgkq39wJQBzbzgIds`gWyp84uas8fH{q$z;;0kf^sqJB!c!bPo$<%F^?Y3S#P7ZX=6N19o-lr< z?jZI2#lH4Plg=MGK80!IF|o0ZIM$%fFYH&l{OLIZ>DC9k2Rgscc|-p22-%AoJ3Gw( zsCmMb*T>JriRzd5vo5aUm}_Agh+lre@Pfo`x(D9?;?w?DagbY-sP(t`_gvM7fKM8> zA2DP#aGB}gTW!NxSNWu24;b(@oDa6~$;l1+*7>BN3ZyNGv+OJ0gLYikFg|IZqtw8G X{||V=8N~vYhz#zuJz@P!dKp~(AL>x%r0{?*$Ll#>YJ^hc2FQqX2N5)L+ zzy3$Y;yc>@BV%N}AU3jI5F1%9h>ffl#2(d8S@;ivw1=KAJ_7}K&;@~f2_Oc^5d!Og z3UaV0$_I*p literal 0 HcmV?d00001 diff --git a/src/img/favicons/homedepot.ico b/src/img/favicons/homedepot.ico new file mode 100644 index 0000000000000000000000000000000000000000..ef22402f9d486da828101e9cb4d038e5fe0318e5 GIT binary patch literal 3638 zcmd^BXwVU<)_UGeBuI-|wW9jR zyAe?jd^0p`_?_OAC>C=j_$e)srUhXVkBz8*{pEw1iGr9mr!qOLU@EO;>N%UqHFM>nR>bSAegOjWm-QY)BjeV8`pF!fo&qzC(UeBWEZG%14V(L1KKdzjw;&NOHl zlc5Wf{U)Z8DyE|sn8vPV3fab_?aOre8dEo5T7ut~?=h`A!sHpnbQ5RK!k(H3OnGOS zOo1sLHk!$lS9^knM@WjzH69v!(V`k>B(y* z^>gg?XF773DLI?z-3O+F`0fZU9pacG55NvQj)>#SSEiT0A!c``fjDRIN?cFeC0S@bmsN_D%&?Z}6Uh z;fkTe@W7ahftbk$!lD;soll0K;M#Y9<`@8-Y9n_iXSP0L=f_ z&oR@U;}f%bk7=Hnl9#)=8JV_jI=G#GjN7y`Ny*7Un`oY~t+tpb^XeEKACi-tOBs#V ziV$mAP3K*T8M?R5Dn}}U4_s%%fC9FuEO?ewTb#|UL z+jq4|kNoy+^eOb{cN^vhi^a->VwWK!r;x)cPrC^NmaiN%^z;(dC~q=9VP=zR*hg$% z;3WE4x>AR!-|viFH@EwW-JBu`E}W$&1Iq-2kKTKECdN=fnP(4v1z-lBsu<$A~dGuNvz@!t-VX1&fD!iNpU zH=SLrgCBqM)axvIcJo1Ol%cm#vnA-Ip0?1aB+S{Nm(f?oOPL-%X0ndfP}{!HQ)oaM z`lZb*=pbr;@loh3>iFtQ=p%YH2Ya4=#Cp`Xq-!*QNq-!AEFb!dzPpNkbHiCq=;e0k z5eoP6;l}IrM~Wu{x3n#IN=-{_|S8N=6N$cfL^VEZj8V= z9fvd7L8IP*hP*U3DZu*Y&ZrQ?T__1s~7OP!cXyiXes*M4E?VM9C8c~?5%x| zy94?W15P9jT9(Fi`yTcJf2VmGYHY?-30>?qf@uh}Far7#jCh^4;g0$RS`Hp85qFcp zxYIr`?fVh@CPTZSosE&BPW_>Omk`%Q@QOTyZAT8*LjyyZK7RqGL0AKxqjo-xR+TRd>v<8A_vVW_WK=wF+mn1gN_PX|{^ffINuapqp& z4@Ye%cQG~d($Kw!xHozue>cI+c=$#x$1Z~}3*ZB`!g6p7%(=*m3};yeF~xy9Z=54( z^X*r_2F?iQ6V?^ujyqEY&cIO@#Mg2T?&}JsEO3y7{McZ>RRohF4Ec;ijl`lxA~m!s z9s5m?Qycu3s6owReH?H)uVvCj9lQa@kHJf$VemN-wE;f&oyJ`XT&Aco3;6R^F@4bB zu6WB-@km3}h^d(+?(zr79ek3HhBA>GQ~2uxd|OfL0}+z~z7n#K1Jq7r2I?_^Y2F^x zB=SLWjFI^NP>cSVfc(uw{VYceAxtjd+XXf3x{b*wP(#l@;6KOD_v&T_s_i(zp5G*$VFZ4eI5?;&JByp`k(X{<6oRwV=cngHehg;&nRyp zIro^m>_MIWjV-3ZSEe=^5K)`k;6PO~?n*Jt_kNY*)3?2Lf>mU=zQ}*AC@hpfs#UrN zU~ro&nLj(}45>YHr64jsDsP(kOPS1XkKG+@uNH_pr;Zz3q7l|2!|G9mu;U0>Nq-?i%51N~Nodcsw2A%BiA6t{ z)Rh^?>MH7mgOjbneGq{y%y z5kS6w{pbR5*7ICN@9%~xl_mZm zqO`ozBhh!wojW)}EDxU~y^3u=dRr7JwPd=k`p;{giY0cLtuQ@c!I*Ff$&;2YeLKq} zepIjhPlSrezjP5s!GlY`f4Lw8X1iC8q7S1ABz`p3VztczaoqY}JAQI(2CJw_w>K7| z@t&f3eq@FI<~br*6Fp$Vj~SBL&OPf5UeR5X>iJR2bo0fcehUiP_+3l^K)duT>=srA zTPM`pLBd+=)X=(6pY2}m4nqE_Mlv7xYWq?&*s(y@Tx<#po1&6^o#{1DGQa8E_LhA3 zpLWTExptI70kqC9U=@DXqpK}aKYg=fLE)npMfDYBKU0X(fF8aVbY=DVtuJ(JJPkUe zijf8Minf0>f0eHEOH2LlM>ba$H&Wx}MZ&pP^I=8xvPMtVc$4^2L5bk75^ zsB7&1!Y`6X-nDg!d-XDJKli$mdU-DLM&gulSLTI0j58tS1#{Kxl_#pErJUHN`k`Xq zPx9_7O?+2AGuDFe$v)5j%6HW@oom1DMErdJ Date: Wed, 28 Nov 2018 13:11:58 -0800 Subject: [PATCH 094/140] Fix #290: Do not allow scrollbars on the entire popup itself. This overflow declaration was added in #215, nominally to help deal with overflow issues when pinned to the overflow menu, but it's not clear how this particular line helps vs the other changes to the width of the onboarding view. My theory on why this is biting us now: - #256 updated the popup to a fixed width when not in the overflow menu, and a flexible width when it is. - When we have more items than the 600px max height in the popup, we overflow and add a vertical toolbar inside. - The vertical toolbar increases the desired width of the popup, causing the body element to add a horizontal scrollbar. - The horizontal scrollbar increases the height beyond the 600px limit (since the initial overflow is contained within the product listing), causing the body element to add a vertical scrollbar. If we force the body element to hide overflow, it refuses to add scrollbars, and the overflow scrollbar on the product listing is overlaid correctly. This should be safe to do now that we flex the width of the popup based on where it is located. --- src/browser_action/index.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser_action/index.css b/src/browser_action/index.css index 3883657..8729651 100644 --- a/src/browser_action/index.css +++ b/src/browser_action/index.css @@ -16,7 +16,7 @@ body { font-size: 13px; margin: 0; max-height: 600px; - overflow: auto; + overflow: hidden; padding: 0; } From 37a8502bf4547a7afb643a8ebbde6765623aa3d4 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Wed, 28 Nov 2018 12:55:30 -0800 Subject: [PATCH 095/140] Fix #266: Update onboarding string to note support for U.S. domains only Also update METRICS.md to add the `'amazon_smile_link'` value for the `element` extra key for the `open_nonproduct_page` event, since that was part of the string change request as well. --- docs/METRICS.md | 1 + src/browser_action/components/EmptyOnboarding.jsx | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/METRICS.md b/docs/METRICS.md index 6b90d88..cbb47fd 100644 --- a/docs/METRICS.md +++ b/docs/METRICS.md @@ -205,6 +205,7 @@ Some `extra_keys` are sent with every telemetry event recorded by the extension: - `'badge_type'`: Indicates what, if any, badge was present on the browserAction toolbar button. One of 'add', 'price_alert', or 'none'. A value of 'unknown' is possible if the badge text is unrecognized. - `'element'`: The extension UI element that the user clicked to open a page in a new tab. Note: All `*_link` elements exist in the Onboarding Popup only. One of... - `'amazon_link'`: Sends the user to Amazon. + - `'amazon_smile_link'`: Sends the user to AmazonSmile. - `'best_buy_link'`: Sends the user to Best Buy. - `'ebay_link'`: Sends the user to eBay. - `'feedback_button'`: Sends the user to a feedback Survey. diff --git a/src/browser_action/components/EmptyOnboarding.jsx b/src/browser_action/components/EmptyOnboarding.jsx index c2e1544..8b7bf30 100644 --- a/src/browser_action/components/EmptyOnboarding.jsx +++ b/src/browser_action/components/EmptyOnboarding.jsx @@ -70,13 +70,14 @@ export default class EmptyOnboarding extends React.Component { {' '} in the spots where whitespace would otherwise be collapsed. */}

- Add products you want to buy from - {' '}Amazon, + Add products from + {' '}Amazon + {' '}and AmazonSmile, {' '}Best Buy, {' '}eBay, - {' '}Home Depot, and + {' '}Home Depot and {' '}Walmart - {' '}to your Price Watcher list, and Firefox will notify you if the price drops. + {' '}(U.S. domains only for now). When Price Wise finds a price drop, the add-on gives you a heads-up about the lower price.

Price Wise keeps track of your saved products by occasionally loading their webpages in From b8cf7fbf4161d947fb902000506556a1c5fc5c03 Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Thu, 29 Nov 2018 10:53:44 -0800 Subject: [PATCH 096/140] 17.0.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5fbee43..563873f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "16.0.0", + "version": "17.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 70272eb..1542479 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "16.0.0", + "version": "17.0.0", "description": "Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy.", "private": true, "author": "Mozilla", From 1a99337db8aa2cbda38d4796c09f19070e1c05f9 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Thu, 29 Nov 2018 15:00:20 -0800 Subject: [PATCH 097/140] Update Release steps in README In light of PRs #285, #288 and #289, which updated our CircleCI config.yml file to add a hold step between signing and uploading the extension. --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index eeb34f7..f444678 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ The following preferences can be set to customize the extension's behavior for t ## Releasing a New Version -Price Wise bumps the major version number for every release, similar to Firefox. Releases are created by tagging a commit that bumps the version number and pushing that tag to the repo. This triggers CircleCI automation that packages, tests, and uploads the new version to the Test Pilot S3 bucket. +Price Wise bumps the major version number for every release, similar to Firefox. Releases are created by tagging a commit that bumps the version number and pushing that tag to the repo. This triggers CircleCI automation that packages, tests, signs and uploads the new version to the Test Pilot S3 bucket. It is strongly recommended that developers creating releases [configure Git to sign their commits and tags][signing]. @@ -144,7 +144,11 @@ To create a new release of Price Wise: git push origin v1.0.0 ``` -You can follow along with the build and upload progress for the new release on the [CircleCI dashboard][]. Once the build finishes, the new version should be available immediately at https://testpilot.firefox.com/files/shopping-testpilot@mozilla.org/latest. +You can follow along with the build and upload progress for the new release on the [CircleCI dashboard][]. Once the build finishes, a signed copy of the new version will be available in the dashboard under Artifacts. The following upload job, however, is gated on a hold job. + +This hold job is intended to provide developers and QA an opportunity for final testing and review of the extension in release channels before uploading. When QA is satisfied, a developer with push access must manually trigger the upload to Test Pilot via the CircleCI dashboard by clicking the hold job and approving the build. + +Once the upload is complete, the new version should be available immediately at https://testpilot.firefox.com/files/shopping-testpilot@mozilla.org/latest. [signing]: https://help.github.com/articles/signing-commits/ [CircleCI dashboard]: https://circleci.com/dashboard From e7dc6706e1f243f71b8ef3ec4f512e907e7454e4 Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Fri, 30 Nov 2018 10:56:10 -0800 Subject: [PATCH 098/140] Remove UR study UI Per sharonbautista in #274, this can now be removed. However, also per sharonbautista, it is possible we will want to recruit study participants from the extension in the future, so I have just turned the feature flag off in config rather than completely reverting PR#278. --- src/config.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/config.js b/src/config.js index a02be41..26017af 100644 --- a/src/config.js +++ b/src/config.js @@ -95,9 +95,8 @@ const CONFIG = { 'www.mkelly.me', ]), - // TODO (bdanforth) Revert PR#278 after 11/26/18 /** Temporary Cyber Monday study UI feature flag */ - enableStudyUI: new BoolValue(true), + enableStudyUI: new BoolValue(false), /** URL for the study's recruitment survey */ studyUrl: new StringValue('https://qsurvey.mozilla.com/s3/Price-Wise-Research-Study'), }; From 1c5ab796ee7e06dc5f4b6899b1820d717e050ffe Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Wed, 5 Dec 2018 10:53:20 -0800 Subject: [PATCH 099/140] 18.0.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 563873f..625ce7d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "17.0.0", + "version": "18.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 1542479..23cef0a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "17.0.0", + "version": "18.0.0", "description": "Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy.", "private": true, "author": "Mozilla", From 019a260e8435f84fc584dc5cd12b0ebb173c4008 Mon Sep 17 00:00:00 2001 From: Sakshi Date: Mon, 14 Jan 2019 22:55:12 -0800 Subject: [PATCH 100/140] Vertically align using padding --- src/browser_action/components/ProductCard.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/browser_action/components/ProductCard.css b/src/browser_action/components/ProductCard.css index a5ff1db..77ec055 100644 --- a/src/browser_action/components/ProductCard.css +++ b/src/browser_action/components/ProductCard.css @@ -23,6 +23,7 @@ .product .prependum { grid-column: 1; grid-row: 1 / 3; + padding-top: 2px; } .product .prependum .icon { From b5de0a98ff703fc815d614385a55f5b2e9487360 Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Tue, 15 Jan 2019 16:01:35 -0800 Subject: [PATCH 101/140] Remove `visit_supported_site` metric. --- docs/METRICS.md | 25 ------------------------- src/extraction/index.js | 5 ----- src/telemetry/events.js | 12 +----------- 3 files changed, 1 insertion(+), 41 deletions(-) diff --git a/docs/METRICS.md b/docs/METRICS.md index cbb47fd..8f14483 100644 --- a/docs/METRICS.md +++ b/docs/METRICS.md @@ -91,19 +91,6 @@ The telemetry category for events is `'extension.price_wise'`. Below is a sample list of events recorded when the user visits a supported page and adds the product on that page. ```javascript -[ - 154572, - "extension.price_wise", - "visit_supported_site", - "supported_site", - null, - { - "tracked_prods": "0", - "privacy_dnt": "false", - "privacy_tp": "private_browsing", - "privacy_cookie": "allow_all" - } -], [ 154592, "extension.price_wise", @@ -228,18 +215,6 @@ Some `extra_keys` are sent with every telemetry event recorded by the extension: ## Collection (User Events) -### `visit_supported_site` - -Fired when the user navigates to a Supported Site. - -#### Payload properties -- `methods`: String - - `'visit_supported_site'` -- `objects`: String - - `'supported_site'` -- `extra_keys`: Object - - [Common extra keys](#common-extra-keys) - ### `open_popup` Fired when the user clicks the Price Wise browserAction toolbar button to open the popup. diff --git a/src/extraction/index.js b/src/extraction/index.js index 0f72486..db15199 100644 --- a/src/extraction/index.js +++ b/src/extraction/index.js @@ -140,11 +140,6 @@ async function attemptExtraction() { return; } - // Record visit_supported_site event - if (!isBackgroundUpdate) { - await recordEvent('visit_supported_site', 'supported_site'); - } - // Extract immediately, and again if the readyState changes. let extractedProduct = await attemptExtraction(); document.addEventListener('readystatechange', async () => { diff --git a/src/telemetry/events.js b/src/telemetry/events.js index a1fdf6a..6209104 100644 --- a/src/telemetry/events.js +++ b/src/telemetry/events.js @@ -167,17 +167,7 @@ const CATEGORY_1_AND_2_EVENTS = { }, }; -export const CATEGORY_3_EVENTS = { - // User visits a supported site - visit_supported_site: { - methods: ['visit_supported_site'], - objects: ['supported_site'], - extra_keys: [ - ...DEFAULT_EXTRAS, - ], - record_on_release: true, - }, -}; +export const CATEGORY_3_EVENTS = {}; export const EVENTS = { ...CATEGORY_1_AND_2_EVENTS, From 6d142949d348778ecd4effde80b306d9aa830eb6 Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Wed, 16 Jan 2019 13:00:07 -0800 Subject: [PATCH 102/140] Remove update URL from manifest, as updates will be going through AMO. --- src/manifest.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/manifest.json b/src/manifest.json index b57f9b2..500dfec 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -8,7 +8,6 @@ "applications": { "gecko": { "id": "shopping-testpilot@mozilla.org", - "update_url": "https://testpilot.firefox.com/files/shopping-testpilot@mozilla.org/updates.json", "strict_min_version": "63.0" } }, From 5e72862fd29e15fa5c21288f722bbd0f67023c0b Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Wed, 16 Jan 2019 13:04:23 -0800 Subject: [PATCH 103/140] 19.0.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 625ce7d..4c58eab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "18.0.0", + "version": "19.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 23cef0a..d7452df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "18.0.0", + "version": "19.0.0", "description": "Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy.", "private": true, "author": "Mozilla", From 6c2730e048b2d3797d53c5a2ca2102c63da4656b Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Wed, 16 Jan 2019 13:04:27 -0800 Subject: [PATCH 104/140] 20.0.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4c58eab..8a864f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "19.0.0", + "version": "20.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d7452df..520e50e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "19.0.0", + "version": "20.0.0", "description": "Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy.", "private": true, "author": "Mozilla", From c0ff58bd21050f2307ab5725617e11bf4dfa20fd Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Thu, 24 Jan 2019 11:35:03 -0800 Subject: [PATCH 105/140] Switch to using a Mozilla-hosted test page. --- src/config.js | 3 +-- src/extraction/selector/selectors.js | 2 +- src/state/vendors.js | 4 ++-- web-ext-config.js | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/config.js b/src/config.js index 26017af..9a35602 100644 --- a/src/config.js +++ b/src/config.js @@ -91,8 +91,7 @@ const CONFIG = { 'www.homedepot.com', 'walmart.com', 'www.walmart.com', - 'mkelly.me', - 'www.mkelly.me', + 'mozilla.github.io', ]), /** Temporary Cyber Monday study UI feature flag */ diff --git a/src/extraction/selector/selectors.js b/src/extraction/selector/selectors.js index f0f723b..08a5a79 100644 --- a/src/extraction/selector/selectors.js +++ b/src/extraction/selector/selectors.js @@ -126,7 +126,7 @@ const fallbackExtractionData = [ }, }, { - domains: ['mkelly.me', 'www.mkelly.me'], + domains: ['mozilla.github.io'], features: { title: [ ['#title', fromProperty('innerText')], diff --git a/src/state/vendors.js b/src/state/vendors.js index 449b0d4..9c92910 100644 --- a/src/state/vendors.js +++ b/src/state/vendors.js @@ -46,8 +46,8 @@ const VENDORS = [ faviconUrl: browser.runtime.getURL('/img/favicons/walmart.ico'), }, { - name: 'mkelly Test', - hostnames: ['mkelly.me', 'www.mkelly.me'], + name: 'Fake Test Page', + hostnames: ['mozilla.github.io'], faviconUrl: '', }, ]; diff --git a/web-ext-config.js b/web-ext-config.js index 122ce7f..9791f8c 100644 --- a/web-ext-config.js +++ b/web-ext-config.js @@ -6,7 +6,7 @@ module.exports = { 'extensions.shopping-testpilot@mozilla.org.iframeTimeout=10000', ], startUrl: [ - 'http://www.mkelly.me/fake-product-page/', + 'http://mozilla.github.io/fake-product-page/', ], }, }; From 93830b1394459441275cfa5f4fd5edcd62443f9e Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Fri, 25 Jan 2019 11:30:03 -0800 Subject: [PATCH 106/140] Add fake product page to README. --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index f444678..ab4f2b4 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,15 @@ Reducers, action creators, etc. are organized into [ducks][] inside the `src/sta ## Testing +### Fake Product Test Page + +A [fake product page][] is available for testing the add-on. The price on the page changes upon refresh, and URL parameters can be used to manually set the price. + +See the [github repo][fake-page-repo] for more details. + +[fake product page]: https://mozilla.github.io/fake-product-page/ +[fake-page-repo]: https://github.com/mozilla/fake-product-page/ + ### Running Tests Automated tests are run in a Firefox browser instance using [Marionette][]. We use the Python client for Marionette since there is no up-to-date JavaScript client. From 60b8c2e884bb10936cd46fa1c344bd7662cd35ed Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Fri, 25 Jan 2019 12:04:01 -0800 Subject: [PATCH 107/140] #302: Remove links to deleted SUMO page. --- docs/METRICS.md | 2 -- .../components/BrowserActionApp.css | 9 ++++++--- .../components/BrowserActionApp.jsx | 17 ---------------- .../components/EmptyOnboarding.jsx | 20 ------------------- src/config.js | 3 --- 5 files changed, 6 insertions(+), 45 deletions(-) diff --git a/docs/METRICS.md b/docs/METRICS.md index 8f14483..07e6787 100644 --- a/docs/METRICS.md +++ b/docs/METRICS.md @@ -196,9 +196,7 @@ Some `extra_keys` are sent with every telemetry event recorded by the extension: - `'best_buy_link'`: Sends the user to Best Buy. - `'ebay_link'`: Sends the user to eBay. - `'feedback_button'`: Sends the user to a feedback Survey. - - `'help_button'`: Sends the user to a Price Wise support.mozilla.org page. - `'home_depot_link'`: Sends the user to Home Depot. - - `'learn_more_link'`: Sends the user to a Price Wise support.mozilla.org page. - `'walmart_link'`: Sends the user to Walmart. - `'extraction_id'`: A unique identifier to associate an extraction attempt to an extraction completion event for a given page. - `'is_bg_update'`: 'true' if the extraction is associated with a background price check; otherwise 'false'. diff --git a/src/browser_action/components/BrowserActionApp.css b/src/browser_action/components/BrowserActionApp.css index e2d9db8..c9c0d0f 100644 --- a/src/browser_action/components/BrowserActionApp.css +++ b/src/browser_action/components/BrowserActionApp.css @@ -5,16 +5,19 @@ /** Top-level components for the toolbar panel */ .title-bar { - align-items: center; border-bottom: 1px solid var(--grey-30); - display: flex; height: 42px; - justify-content: space-between; margin: 0; overflow: hidden; padding: 0 8px; } +.title-bar .feedback { + position: absolute; + top: 5px; + left: 5px; +} + .title-bar .title { font-size: 13px; font-weight: bold; diff --git a/src/browser_action/components/BrowserActionApp.jsx b/src/browser_action/components/BrowserActionApp.jsx index 5050729..a15c44e 100644 --- a/src/browser_action/components/BrowserActionApp.jsx +++ b/src/browser_action/components/BrowserActionApp.jsx @@ -70,15 +70,6 @@ export default class BrowserActionApp extends React.Component { await recordEvent('open_popup', 'toolbar_button', null, {badge_type: await getBadgeType()}); } - /** - * Open the support page and close the panel when the help icon is clicked. - */ - async handleClickHelp() { - browser.tabs.create({url: await config.get('supportUrl')}); - await recordEvent('open_nonproduct_page', 'ui_element', null, {element: 'help_button'}); - window.close(); - } - /** * Open the feedback page and close the panel when the help icon is clicked. */ @@ -138,14 +129,6 @@ export default class BrowserActionApp extends React.Component { />

Products

-
{products.length < 1 ? ( diff --git a/src/browser_action/components/EmptyOnboarding.jsx b/src/browser_action/components/EmptyOnboarding.jsx index 8b7bf30..c34e992 100644 --- a/src/browser_action/components/EmptyOnboarding.jsx +++ b/src/browser_action/components/EmptyOnboarding.jsx @@ -6,7 +6,6 @@ import autobind from 'autobind-decorator'; import React from 'react'; import TrackProductButton from 'commerce/browser_action/components/TrackProductButton'; -import config from 'commerce/config'; import {extractedProductShape} from 'commerce/state/products'; import {recordEvent} from 'commerce/telemetry/extension'; @@ -26,23 +25,6 @@ export default class EmptyOnboarding extends React.Component { extractedProduct: null, } - constructor(props) { - super(props); - this.state = { - learnMoreHref: null, - }; - } - - /** - * Fetch the link to the support page on mount, since we can't fetch it async - * during the render. - */ - async componentDidMount() { - this.setState({ - learnMoreHref: await config.get('supportUrl'), - }); - } - /** * Open a new tab and close the popup when links are clicked. */ @@ -57,7 +39,6 @@ export default class EmptyOnboarding extends React.Component { render() { const {extractedProduct} = this.props; - const {learnMoreHref} = this.state; return (
@@ -83,7 +64,6 @@ export default class EmptyOnboarding extends React.Component { Price Wise keeps track of your saved products by occasionally loading their webpages in the background while Firefox is open.

- Learn More
); diff --git a/src/config.js b/src/config.js index 9a35602..cd89bb6 100644 --- a/src/config.js +++ b/src/config.js @@ -72,9 +72,6 @@ const CONFIG = { /** Color of the toolbar badge when a product on the current page is trackable. */ badgeDetectBackground: new StringValue('#33F70C'), - /** URL for the add-on's page on support.mozilla.org */ - supportUrl: new StringValue('https://support.mozilla.org/kb/new-test-pilot-experiments'), - /** URL for the add-on's feedback form */ feedbackUrl: new StringValue('https://qsurvey.mozilla.com/s3/price-wise'), From de13c87061bb0e833522970ab55ec863eb367f24 Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Tue, 22 Jan 2019 13:48:35 -0800 Subject: [PATCH 108/140] Add first-run prompt that informs the user about data collection. --- src/background/index.js | 5 ++ src/img/menu.svg | 4 ++ src/intro.html | 128 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 src/img/menu.svg create mode 100644 src/intro.html diff --git a/src/background/index.js b/src/background/index.js index 0988eb3..6861b32 100644 --- a/src/background/index.js +++ b/src/background/index.js @@ -22,6 +22,11 @@ import {registerEvents, handleWidgetRemoved} from 'commerce/telemetry/extension' (async function main() { registerEvents(); + // Show the browser action on first install so users see the privacy notice. + browser.runtime.onInstalled.addListener(() => { + browser.tabs.create({url: browser.extension.getURL('intro.html')}); + }); + // Set browser action default badge color, which can't be set via manifest browser.browserAction.setBadgeBackgroundColor({ color: await config.get('badgeAlertBackground'), diff --git a/src/img/menu.svg b/src/img/menu.svg new file mode 100644 index 0000000..b65f05f --- /dev/null +++ b/src/img/menu.svg @@ -0,0 +1,4 @@ + + \ No newline at end of file diff --git a/src/intro.html b/src/intro.html new file mode 100644 index 0000000..2ab4629 --- /dev/null +++ b/src/intro.html @@ -0,0 +1,128 @@ + + + + + Price Wise by Mozilla + + + +

+ + Price Wise +

+
+

Your Privacy

+

We care about your privacy. Price Wise collects some information about your use of the add-on:

+
    +
  • Product Pages: Price Wise collects how often you visit saved product pages.
  • +
  • Product Data: Price Wise collects data about the products you choose to track such as prices change frequency, size, and the accuracy of that information.
  • +
  • Interaction Data: Price Wise collects information about how you use the feature such as how often you add, delete and interact with saved products, number of products you choose to track, and how you engage with messages and push notifications. +
+

If you choose to send data to Mozilla (that’s us), our privacy policy describes how we handle that data.

+

How do I opt-out of sending data to Mozilla?

+

Price Wise uses Firefox's Telemetry system to collect data. You can opt-out of data collection by disabling Firefox Telemetry:

+
    +
  1. Click the menu button and choose Preferences.
  2. +
  3. Select the Privacy & Security panel.
  4. +
  5. Scroll down to the Firefox Data Collection and Use section.
  6. +
  7. Check or uncheck the box next to Allow Firefox to send technical and interaction data to Mozilla.
  8. +
+
+ + From 9e89cbc1d0682bc6977d689d64bebdf393c121fd Mon Sep 17 00:00:00 2001 From: Michael Kelly Date: Mon, 28 Jan 2019 14:18:45 -0800 Subject: [PATCH 109/140] 21.0.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8a864f0..f816fe9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "20.0.0", + "version": "21.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 520e50e..f93d067 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "price-wise", - "version": "20.0.0", + "version": "21.0.0", "description": "Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy.", "private": true, "author": "Mozilla", From 541d3b887d2ffd9ea5ed3f074a4188b2f5fcd8df Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Thu, 21 Feb 2019 10:25:29 -0800 Subject: [PATCH 110/140] Update development dependency packages --- package-lock.json | 4271 ++++++++++++++++++++------------------------- package.json | 6 +- 2 files changed, 1939 insertions(+), 2338 deletions(-) diff --git a/package-lock.json b/package-lock.json index f816fe9..2f3d466 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,208 @@ "@babel/highlight": "7.0.0-beta.44" } }, + "@babel/core": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.3.3.tgz", + "integrity": "sha512-w445QGI2qd0E0GlSnq6huRZWPMmQGCp5gd5ZWS4hagn0EiwzxD5QMFkpchyusAyVC1n27OKXzQ0/88aVU9n4xQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.3.3", + "@babel/helpers": "^7.2.0", + "@babel/parser": "^7.3.3", + "@babel/template": "^7.2.2", + "@babel/traverse": "^7.2.2", + "@babel/types": "^7.3.3", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.11", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.3.tgz", + "integrity": "sha512-aEADYwRRZjJyMnKN7llGIlircxTCofm3dtV5pmY6ob18MSIuipHpA2yZWkPlycwu5HJcx/pADS3zssd8eY7/6A==", + "dev": true, + "requires": { + "@babel/types": "^7.3.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", + "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/template": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" + } + }, + "@babel/traverse": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.2.3.tgz", + "integrity": "sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.2.2", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.2.3", + "@babel/types": "^7.2.2", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + } + }, + "@babel/types": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.3.tgz", + "integrity": "sha512-2tACZ80Wg09UnPg5uGAOUvvInaqLk3l/IAhQzlxLQOIXacr6bMsra5SH6AWw/hIDRCSbCdHP2KzSOD+cT7TzMQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "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" + } + }, + "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" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "globals": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", + "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "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" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, "@babel/generator": { "version": "7.0.0-beta.44", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.44.tgz", @@ -63,6 +265,182 @@ "@babel/types": "7.0.0-beta.44" } }, + "@babel/helpers": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.3.1.tgz", + "integrity": "sha512-Q82R3jKsVpUV99mgX50gOPCWwco9Ec5Iln/8Vyu4osNIOQgSrd9RFrQeUvmvddFNoLwMyOUWU+5ckioEKpDoGA==", + "dev": true, + "requires": { + "@babel/template": "^7.1.2", + "@babel/traverse": "^7.1.5", + "@babel/types": "^7.3.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.3.tgz", + "integrity": "sha512-aEADYwRRZjJyMnKN7llGIlircxTCofm3dtV5pmY6ob18MSIuipHpA2yZWkPlycwu5HJcx/pADS3zssd8eY7/6A==", + "dev": true, + "requires": { + "@babel/types": "^7.3.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", + "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/template": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" + } + }, + "@babel/traverse": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.2.3.tgz", + "integrity": "sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.2.2", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.2.3", + "@babel/types": "^7.2.2", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + } + }, + "@babel/types": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.3.tgz", + "integrity": "sha512-2tACZ80Wg09UnPg5uGAOUvvInaqLk3l/IAhQzlxLQOIXacr6bMsra5SH6AWw/hIDRCSbCdHP2KzSOD+cT7TzMQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "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" + } + }, + "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" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "globals": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", + "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "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" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, "@babel/highlight": { "version": "7.0.0-beta.44", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.44.tgz", @@ -111,66 +489,50 @@ } } }, + "@babel/parser": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.3.tgz", + "integrity": "sha512-xsH1CJoln2r74hR+y7cg2B5JCPaTh+Hd+EbBRk9nWGSNspuo6krjhX0Om6RnRQuIvFq8wVXCLKH3kwKDYhanSg==", + "dev": true + }, "@babel/polyfill": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.0.0.tgz", - "integrity": "sha512-dnrMRkyyr74CRelJwvgnnSUDh2ge2NCTyHVwpOdvRMHtJUyxLtMAfhBN3s64pY41zdw0kgiLPh6S20eb1NcX6Q==", + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.2.5.tgz", + "integrity": "sha512-8Y/t3MWThtMLYr0YNC/Q76tqN1w30+b0uQMeFUYauG2UGTR19zyUtFrAzT23zNtBxPp+LbE5E/nwV/q/r3y6ug==", "dev": true, "requires": { "core-js": "^2.5.7", - "regenerator-runtime": "^0.11.1" + "regenerator-runtime": "^0.12.0" }, "dependencies": { "core-js": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", + "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==", "dev": true } } }, - "@babel/register": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.0.0.tgz", - "integrity": "sha512-f/+CRmaCe7rVEvcvPvxeA8j5aJhHC3aJie7YuqcMDhUOuyWLA7J/aNrTaHIzoWPEhpHA54mec4Mm8fv8KBlv3g==", + "@babel/runtime": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.3.1.tgz", + "integrity": "sha512-7jGW8ppV0ant637pIqAcFfQDDH1orEPGJb8aXfUozuCU3QqX7rX4DA8iwrbPrR1hcH0FTTHz47yQnk+bl5xHQA==", "dev": true, "requires": { - "core-js": "^2.5.7", - "find-cache-dir": "^1.0.0", - "home-or-tmp": "^3.0.0", - "lodash": "^4.17.10", - "mkdirp": "^0.5.1", - "pirates": "^4.0.0", - "source-map-support": "^0.5.9" + "regenerator-runtime": "^0.12.0" }, "dependencies": { - "core-js": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", - "dev": true - }, - "home-or-tmp": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-3.0.0.tgz", - "integrity": "sha1-V6j+JM8zzdUkhgoVgh3cJchmcfs=", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "regenerator-runtime": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==", "dev": true - }, - "source-map-support": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", - "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } } } }, @@ -285,9 +647,9 @@ } }, "@nodelib/fs.stat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.0.tgz", - "integrity": "sha512-LAQ1d4OPfSJ/BMbI2DuizmYrrkD9JMaTdi2hQTlI53lQ4kRQPyZQRS4CYQ7O66bnBBnP/oYdRxbk++X0xuFU6A==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", "dev": true }, "@types/node": { @@ -296,12 +658,39 @@ "integrity": "sha512-m9zXmifkZsMHZBOyxZWilMwmTlpC8x5Ty360JKTiXvlXZfBWYpsg9ZZvP/Ye+iZUh+Q+MxDLjItVTWIsfwz+8Q==", "dev": true }, - "@webassemblyjs/ast": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.5.13.tgz", - "integrity": "sha512-49nwvW/Hx9i+OYHg+mRhKZfAlqThr11Dqz8TsrvqGKMhdI2ijy3KBJOun2Z4770TPjrIJhR6KxChQIDaz8clDA==", - "dev": true, - "requires": { + "@types/unist": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", + "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", + "dev": true + }, + "@types/vfile": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/vfile/-/vfile-3.0.2.tgz", + "integrity": "sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/unist": "*", + "@types/vfile-message": "*" + } + }, + "@types/vfile-message": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/vfile-message/-/vfile-message-1.0.1.tgz", + "integrity": "sha512-mlGER3Aqmq7bqR1tTTIVHq8KSAFFRyGbrxuM8C/H82g6k7r2fS+IMEkIu3D7JHzG10NvPdR8DNx0jr0pwpp4dA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/unist": "*" + } + }, + "@webassemblyjs/ast": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.5.13.tgz", + "integrity": "sha512-49nwvW/Hx9i+OYHg+mRhKZfAlqThr11Dqz8TsrvqGKMhdI2ijy3KBJOun2Z4770TPjrIJhR6KxChQIDaz8clDA==", + "dev": true, + "requires": { "@webassemblyjs/helper-module-context": "1.5.13", "@webassemblyjs/helper-wasm-bytecode": "1.5.13", "@webassemblyjs/wast-parser": "1.5.13", @@ -699,12 +1088,6 @@ } } }, - "@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true - }, "JSONSelect": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.2.1.tgz", @@ -716,12 +1099,6 @@ "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==" }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, "acorn": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", @@ -813,66 +1190,87 @@ } }, "addons-linter": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/addons-linter/-/addons-linter-1.3.8.tgz", - "integrity": "sha512-NFon8Q++k8R6t1lunNPoVPWxVUzC8ED5Cu8VB66HdsaVarLHNhIdpDSqClplefC5Mypx/EEgZhkMZAuaxScyUg==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/addons-linter/-/addons-linter-1.6.1.tgz", + "integrity": "sha512-3+N8cskdXHpId0dhfsldgbYGXamtgfGywvU4oPVb1M7imG3pHFoK+VcAr/kPk1VeYGkSmBl2LxnwGHcw1ERvmA==", "dev": true, "requires": { - "@babel/polyfill": "7.0.0", - "@babel/register": "7.0.0", - "ajv": "6.5.4", + "ajv": "6.9.1", "ajv-merge-patch": "4.1.0", - "chalk": "2.4.0", + "chalk": "2.4.2", "cheerio": "1.0.0-rc.2", "columnify": "1.5.4", "common-tags": "1.8.0", "crx-parser": "0.1.2", - "deepmerge": "2.2.1", - "dispensary": "0.26.0", - "es6-promisify": "5.0.0", - "eslint": "5.0.1", + "deepmerge": "3.1.0", + "dispensary": "0.30.0", + "es6-promisify": "6.0.1", + "eslint": "5.13.0", "eslint-plugin-no-unsafe-innerhtml": "1.0.16", "eslint-visitor-keys": "1.0.0", - "espree": "4.0.0", + "espree": "5.0.0", "esprima": "3.1.3", "first-chunk-stream": "2.0.0", - "fluent-syntax": "0.7.0", - "fsevents": "1.2.4", + "fluent-syntax": "0.10.0", + "fsevents": "2.0.1", "glob": "7.1.3", "is-mergeable-object": "1.1.0", "jed": "1.1.1", - "os-locale": "3.0.1", - "pino": "5.5.0", + "mdn-browser-compat-data": "0.0.66", + "os-locale": "3.1.0", + "pino": "5.11.1", "po2json": "0.4.5", - "postcss": "7.0.5", + "postcss": "7.0.14", "probe-image-size": "4.0.0", + "regenerator-runtime": "0.13.1", "relaxed-json": "1.0.1", "semver": "5.6.0", - "shelljs": "0.8.2", - "snyk": "1.103.2", - "source-map-support": "0.5.6", + "source-map-support": "0.5.10", "strip-bom-stream": "3.0.0", "tosource": "1.0.0", "upath": "1.1.0", "whatwg-url": "7.0.0", "xmldom": "0.1.27", - "yargs": "12.0.2", - "yauzl": "2.9.2" + "yargs": "13.1.0", + "yauzl": "2.10.0" }, "dependencies": { - "acorn-jsx": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz", - "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==", + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", "dev": true, "requires": { - "acorn": "^5.0.3" + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" } }, + "acorn": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.0.tgz", + "integrity": "sha512-MW/FjM+IvU9CgBzjO3UIPCE2pyEwUsoFl+VGdczOPEdxfGFjuKny/gN54mOuX7Qxmb9Rg9MCn2oKiSUeW+pjrw==", + "dev": true + }, + "acorn-jsx": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", + "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", + "dev": true + }, "ajv": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz", - "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", + "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -881,16 +1279,16 @@ "uri-js": "^4.2.2" } }, - "ajv-keywords": { + "ansi-escapes": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", - "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", "dev": true }, "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", + "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", "dev": true }, "ansi-styles": { @@ -902,10 +1300,16 @@ "color-convert": "^1.9.0" } }, + "camelcase": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", + "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", + "dev": true + }, "chalk": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", - "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", + "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", @@ -913,6 +1317,12 @@ "supports-color": "^5.3.0" } }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -927,49 +1337,53 @@ } }, "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" } }, - "decamelize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", - "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", - "dev": true, - "requires": { - "xregexp": "4.0.0" - } + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "es6-promisify": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-6.0.1.tgz", + "integrity": "sha512-J3ZkwbEnnO+fGAKrjVpeUAnZshAdfZvbhQpqfIH9kSAspReRC4nJnu8ewm55b4y9ElyeuhCTzJD0XiH8Tsbhlw==", + "dev": true }, "eslint": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.0.1.tgz", - "integrity": "sha512-D5nG2rErquLUstgUaxJlWB5+gu+U/3VDY0fk/Iuq8y9CUFy/7Y6oF4N2cR1tV8knzQvciIbfqfohd359xTLIKQ==", + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.13.0.tgz", + "integrity": "sha512-nqD5WQMisciZC5EHZowejLKQjWGuFS5c70fxqSKlnDME+oz9zmE8KTlX+lHSg+/5wsC/kf9Q9eMkC8qS3oM2fg==", "dev": true, "requires": { - "ajv": "^6.5.0", - "babel-code-frame": "^6.26.0", + "@babel/code-frame": "^7.0.0", + "ajv": "^6.5.3", "chalk": "^2.1.0", "cross-spawn": "^6.0.5", - "debug": "^3.1.0", + "debug": "^4.0.1", "doctrine": "^2.1.0", "eslint-scope": "^4.0.0", + "eslint-utils": "^1.3.1", "eslint-visitor-keys": "^1.0.0", - "espree": "^4.0.0", + "espree": "^5.0.0", "esquery": "^1.0.1", "esutils": "^2.0.2", "file-entry-cache": "^2.0.0", "functional-red-black-tree": "^1.0.1", "glob": "^7.1.2", - "globals": "^11.5.0", - "ignore": "^3.3.3", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^5.2.0", - "is-resolvable": "^1.1.0", - "js-yaml": "^3.11.0", + "inquirer": "^6.1.0", + "js-yaml": "^3.12.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.3.0", "lodash": "^4.17.5", @@ -978,15 +1392,12 @@ "natural-compare": "^1.4.0", "optionator": "^0.8.2", "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", "progress": "^2.0.0", - "regexpp": "^1.1.0", - "require-uncached": "^1.0.3", - "semver": "^5.5.0", - "string.prototype.matchall": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", "strip-ansi": "^4.0.0", "strip-json-comments": "^2.0.1", - "table": "^4.0.3", + "table": "^5.0.2", "text-table": "^0.2.0" } }, @@ -1001,13 +1412,14 @@ } }, "espree": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz", - "integrity": "sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.0.tgz", + "integrity": "sha512-1MpUfwsdS9MMoN7ZXqAr9e9UKdVHDcvrJpyx7mm1WuQlx/ygErEQBzgi5Nh5qBHIoYweprhtMkTCb9GhcAIcsA==", "dev": true, "requires": { - "acorn": "^5.6.0", - "acorn-jsx": "^4.1.1" + "acorn": "^6.0.2", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" } }, "esprima": { @@ -1016,6 +1428,17 @@ "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", "dev": true }, + "external-editor": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", + "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", @@ -1031,6 +1454,19 @@ "locate-path": "^3.0.0" } }, + "fsevents": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.1.tgz", + "integrity": "sha512-p+CXqK/iLvDESUWdn3NA3JVO9HxdfI+iXx8xR3DqWgKZvQNiEVpAyUQo0lmwz8rqksb4xaGerG291xuwwhX2kA==", + "dev": true, + "optional": true + }, + "get-caller-file": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.1.tgz", + "integrity": "sha512-SpOZHfz845AH0wJYVuZk2jWDqFmu7Xubsx+ldIpwzy5pDUpu7OJHK7QYNSA2NPlDSKQwM1GFaAkciOWjjW92Sg==", + "dev": true + }, "glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", @@ -1046,30 +1482,56 @@ } }, "globals": { - "version": "11.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.9.0.tgz", - "integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", + "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, "inquirer": { - "version": "5.2.0", - "resolved": "http://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", - "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.2.tgz", + "integrity": "sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-width": "^2.0.0", - "external-editor": "^2.1.0", + "external-editor": "^3.0.3", "figures": "^2.0.0", - "lodash": "^4.3.0", + "lodash": "^4.17.11", "mute-stream": "0.0.7", "run-async": "^2.2.0", - "rxjs": "^5.5.2", + "rxjs": "^6.4.0", "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", + "strip-ansi": "^5.0.0", "through": "^2.3.6" + }, + "dependencies": { + "strip-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", + "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", + "dev": true, + "requires": { + "ansi-regex": "^4.0.0" + } + } } }, "json-schema-traverse": { @@ -1095,9 +1557,9 @@ "dev": true }, "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -1119,35 +1581,62 @@ "dev": true }, "postcss": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.5.tgz", - "integrity": "sha512-HBNpviAUFCKvEh7NZhw1e8MBPivRszIiUnhrJ+sBFVSYSqubrzwX3KG51mYgcRHX8j/cAgZJedONZcm5jTBdgQ==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" }, "dependencies": { - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "has-flag": "^3.0.0" } } } }, + "regenerator-runtime": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.1.tgz", + "integrity": "sha512-5KzMIyPLvfdPmvsdlYsHqITrDfK9k7bmvf97HvHSN4810i254ponbxCQ1NukpRWlu6en2MBWzAlhDExEKISwAA==", + "dev": true + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, "semver": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -1155,9 +1644,9 @@ "dev": true }, "source-map-support": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz", - "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==", + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", + "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -1171,6 +1660,14 @@ "dev": true, "requires": { "ansi-regex": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + } } }, "supports-color": { @@ -1183,17 +1680,37 @@ } }, "table": { - "version": "4.0.3", - "resolved": "http://registry.npmjs.org/table/-/table-4.0.3.tgz", - "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz", + "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==", "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" + "ajv": "^6.9.1", + "lodash": "^4.17.11", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "string-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.0.0.tgz", + "integrity": "sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.0.0" + } + }, + "strip-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", + "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", + "dev": true, + "requires": { + "ansi-regex": "^4.0.0" + } + } } }, "upath": { @@ -1213,30 +1730,55 @@ "webidl-conversions": "^4.0.2" } }, - "xregexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", - "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", - "dev": true - }, "yargs": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz", - "integrity": "sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.1.0.tgz", + "integrity": "sha512-1UhJbXfzHiPqkfXNHYhiz79qM/kZqjTE8yGlEjZa85Q+3+OwcV6NRkV7XOV1W2Eom2bzILeUn55pQYffjVOLAg==", "dev": true, "requires": { "cliui": "^4.0.0", - "decamelize": "^2.0.0", "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^2.0.0", + "string-width": "^3.0.0", "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^10.1.0" + "y18n": "^4.0.0", + "yargs-parser": "^13.0.0" + }, + "dependencies": { + "string-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.0.0.tgz", + "integrity": "sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.0.0" + } + }, + "strip-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", + "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", + "dev": true, + "requires": { + "ansi-regex": "^4.0.0" + } + } + } + }, + "yargs-parser": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", + "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } @@ -1247,15 +1789,6 @@ "integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==", "dev": true }, - "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } - }, "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", @@ -1311,12 +1844,6 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, - "ansicolors": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", - "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=", - "dev": true - }, "any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -1379,12 +1906,12 @@ }, "dependencies": { "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "^4.17.11" } } } @@ -1403,12 +1930,6 @@ "readable-stream": "^2.0.0" } }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -1491,12 +2012,6 @@ "es-abstract": "^1.7.0" } }, - "array-iterate": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.2.tgz", - "integrity": "sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ==", - "dev": true - }, "array-map": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", @@ -1530,6 +2045,17 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, + "array.prototype.flat": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz", + "integrity": "sha512-rVqIs330nLJvfC7JqYvEWwqVr5QjYF1ib02i3YJtR/fICO6527Tjpc/e4Mvmxh3GIePPreRXMdaGyC99YphWEw==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.10.0", + "function-bind": "^1.1.1" + } + }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -1594,18 +2120,18 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, - "ast-types": { - "version": "0.11.7", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.7.tgz", - "integrity": "sha512-2mP3TwtkY/aTv5X3ZsMpNAbOnyoC/aMJwJSoaELPkHId0nSQgFcnU4dRW3isxiz7+zBexk0ym3WNVjMiQBnJSw==", - "dev": true - }, "ast-types-flow": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", "dev": true }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, "async": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", @@ -1640,17 +2166,82 @@ "integrity": "sha512-bgyxeRi1R2Q8kWpHsb1c+lXCulbIAHsyZRddaS+agAUX3hFUVZMociwvRgeZi1zWvfqEEjybSv4zxWvFV8ydQQ==" }, "autoprefixer": { - "version": "8.6.5", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-8.6.5.tgz", - "integrity": "sha512-PLWJN3Xo/rycNkx+mp8iBDMTm3FeWe4VmYaZDSqL5QQB9sLsQkG5k8n+LNDFnhh9kdq2K+egL/icpctOmDHwig==", + "version": "9.4.8", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.4.8.tgz", + "integrity": "sha512-DIhd0KMi9Nql3oJkJ2HCeOVihrXFPtWXc6ckwaUNwliDOt9OGr0fk8vV8jCLWXnZc1EXvQ2uLUzGpcPxFAQHEQ==", "dev": true, "requires": { - "browserslist": "^3.2.8", - "caniuse-lite": "^1.0.30000864", + "browserslist": "^4.4.1", + "caniuse-lite": "^1.0.30000938", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", - "postcss": "^6.0.23", - "postcss-value-parser": "^3.2.3" + "postcss": "^7.0.14", + "postcss-value-parser": "^3.3.1" + }, + "dependencies": { + "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" + } + }, + "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" + }, + "dependencies": { + "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" + } + } + } + }, + "postcss": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "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 + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "aws-sign2": { @@ -1925,26 +2516,26 @@ } }, "babel-polyfill": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", - "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.16.0.tgz", + "integrity": "sha1-LUUCHfh+JqN0ttTRqcZZZNF/JCI=", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "regenerator-runtime": "^0.10.5" + "babel-runtime": "^6.9.1", + "core-js": "^2.4.0", + "regenerator-runtime": "^0.9.5" }, "dependencies": { "core-js": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", + "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==", "dev": true }, "regenerator-runtime": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.6.tgz", + "integrity": "sha1-0z65XQ0gAaS+OWWXB8UbDLcc4Ck=", "dev": true } } @@ -2351,13 +2942,14 @@ } }, "browserslist": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", - "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.4.1.tgz", + "integrity": "sha512-pEBxEXg7JwaakBXjATYw/D1YZh4QUSCX/Mnd/wnqSRPPSi1U39iDhDoKGoBUcraKdxDlrYqJxSI5nNvD+dWP2A==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" + "caniuse-lite": "^1.0.30000929", + "electron-to-chromium": "^1.3.103", + "node-releases": "^1.1.3" } }, "buffer": { @@ -2441,12 +3033,6 @@ "safe-json-stringify": "~1" } }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, "cacache": { "version": "10.0.4", "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", @@ -2524,9 +3110,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000865", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000865.tgz", - "integrity": "sha512-vs79o1mOSKRGv/1pSkp4EXgl4ZviWeYReXw60XfacPU64uQWZwJT6vZNmxRF9O+6zu71sJwMxLK5JXxbzuVrLw==", + "version": "1.0.30000938", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000938.tgz", + "integrity": "sha512-ekW8NQ3/FvokviDxhdKLZZAx7PptXNwxKgXtnR5y+PR3hckwuP3yJ1Ir+4/c97dsHNqtAyfKUGdw8P4EYzBNgw==", "dev": true }, "capture-stack-trace": { @@ -2739,38 +3325,6 @@ "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, - "clone-deep": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.3.0.tgz", - "integrity": "sha1-NIxhrpzb4O3+BT2R/0zFIdeQ7eg=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "is-plain-object": "^2.0.1", - "kind-of": "^3.2.2", - "shallow-clone": "^0.1.2" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "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" - } - } - } - }, "clone-regexp": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-1.0.1.tgz", @@ -3255,12 +3809,6 @@ "assert-plus": "^1.0.0" } }, - "data-uri-to-buffer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==", - "dev": true - }, "data-urls": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", @@ -3358,9 +3906,9 @@ "dev": true }, "deepmerge": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", - "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.1.0.tgz", + "integrity": "sha512-/TnecbwXEdycfbsM2++O3eGiatEFHjjNciHEwJclM+T5Kd94qD1AP+2elP/Mq0L5b9VZJao5znR01Mz6eX8Seg==", "dev": true }, "defaults": { @@ -3429,25 +3977,6 @@ "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", "dev": true }, - "degenerator": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", - "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", - "dev": true, - "requires": { - "ast-types": "0.x.x", - "escodegen": "1.x.x", - "esprima": "3.x.x" - }, - "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - } - } - }, "del": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", @@ -3490,12 +4019,6 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, "des.js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", @@ -3554,15 +4077,15 @@ "dev": true }, "dispensary": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/dispensary/-/dispensary-0.26.0.tgz", - "integrity": "sha512-Cw0N6Hf8/y4vH9/NvDPGLd2+Mve9xs+41+sULJ4ODHuhZ+9CnJ2eMl2ju2udL/UACY0Vcxw3TzyoDRBNaU/0DQ==", + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/dispensary/-/dispensary-0.30.0.tgz", + "integrity": "sha512-ZZipc2xaDky03RD3s1UJOM6zgygo2ncEzmjuqpPR6pT7jMo0cxH/FTzGarD3Pw2naAsBOXVGG10Fwxth9OrW0g==", "dev": true, "requires": { "array-from": "~2.1.1", "async": "~2.6.0", "natural-compare-lite": "~1.4.0", - "pino": "~5.8.0", + "pino": "~5.11.0", "request": "~2.88.0", "sha.js": "~2.4.4", "source-map-support": "~0.5.4", @@ -3570,12 +4093,12 @@ }, "dependencies": { "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "^4.17.11" } }, "camelcase": { @@ -3604,9 +4127,9 @@ } }, "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -3627,32 +4150,6 @@ "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", "dev": true }, - "pino": { - "version": "5.8.1", - "resolved": "https://registry.npmjs.org/pino/-/pino-5.8.1.tgz", - "integrity": "sha512-7bVFzUw3ffIfOM3t7MuQ9KsH+wX5bdGdQhGfccKgleoY7qG4FO3CmVSjywlFmmYGyMOISi1LDGC6JMEH7XkZJg==", - "dev": true, - "requires": { - "fast-json-parse": "^1.0.3", - "fast-redact": "^1.2.0", - "fast-safe-stringify": "^2.0.6", - "flatstr": "^1.0.5", - "pino-std-serializers": "^2.3.0", - "pump": "^3.0.0", - "quick-format-unescaped": "^3.0.0", - "sonic-boom": "^0.6.1" - } - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -3660,9 +4157,9 @@ "dev": true }, "source-map-support": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", - "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", + "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -3814,18 +4311,18 @@ } }, "ecdsa-sig-formatter": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz", - "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", "dev": true, "requires": { "safe-buffer": "^5.0.1" } }, "electron-to-chromium": { - "version": "1.3.52", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.52.tgz", - "integrity": "sha1-0tnxJwuko7lnuDHEDvcftNmrXOA=", + "version": "1.3.113", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.113.tgz", + "integrity": "sha512-De+lPAxEcpxvqPTyZAXELNpRZXABRxf+uL/rSykstQhzj/B0l1150G/ExIIxKc16lI89Hgz81J0BHAcbTqK49g==", "dev": true }, "elliptic": { @@ -3843,12 +4340,6 @@ "minimalistic-crypto-utils": "^1.0.0" } }, - "email-validator": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/email-validator/-/email-validator-2.0.4.tgz", - "integrity": "sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ==", - "dev": true - }, "emoji-regex": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.5.1.tgz", @@ -3896,27 +4387,32 @@ "dev": true }, "enzyme": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.3.0.tgz", - "integrity": "sha512-l8csyPyLmtxskTz6pX9W8eDOyH1ckEtDttXk/vlFWCjv00SkjTjtoUrogqp4yEvMyneU9dUJoOLnqFoiHb8IHA==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.9.0.tgz", + "integrity": "sha512-JqxI2BRFHbmiP7/UFqvsjxTirWoM1HfeaJrmVSZ9a1EADKkZgdPcAuISPMpoUiHlac9J4dYt81MC5BBIrbJGMg==", "dev": true, "requires": { + "array.prototype.flat": "^1.2.1", "cheerio": "^1.0.0-rc.2", - "function.prototype.name": "^1.0.3", - "has": "^1.0.1", + "function.prototype.name": "^1.1.0", + "has": "^1.0.3", + "html-element-map": "^1.0.0", "is-boolean-object": "^1.0.0", - "is-callable": "^1.1.3", + "is-callable": "^1.1.4", "is-number-object": "^1.0.3", + "is-regex": "^1.0.4", "is-string": "^1.0.4", "is-subset": "^0.1.1", - "lodash": "^4.17.4", - "object-inspect": "^1.5.0", + "lodash.escape": "^4.0.1", + "lodash.isequal": "^4.5.0", + "object-inspect": "^1.6.0", "object-is": "^1.0.1", "object.assign": "^4.1.0", "object.entries": "^1.0.4", "object.values": "^1.0.4", "raf": "^3.4.0", - "rst-selector-parser": "^2.2.3" + "rst-selector-parser": "^2.2.3", + "string.prototype.trim": "^1.1.2" } }, "enzyme-adapter-react-16": { @@ -4044,9 +4540,9 @@ }, "dependencies": { "es6-promise": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", - "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", + "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==", "dev": true } } @@ -4537,17 +5033,6 @@ "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", "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" - } - }, "slice-ansi": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", @@ -4642,6 +5127,12 @@ "estraverse": "^4.1.1" } }, + "eslint-utils": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", + "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", + "dev": true + }, "eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -4795,57 +5286,6 @@ } } }, - "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" - }, - "dependencies": { - "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" - } - }, - "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" - } - }, - "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" - } - }, - "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" - } - } - } - }, "extend": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", @@ -4961,48 +5401,19 @@ "dev": true }, "fast-glob": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.2.tgz", - "integrity": "sha512-TR6zxCKftDQnUAPvkrCWdBgDq/gbqx8A3ApnBrR5rMvpp6+KMJI0Igw7fkWPgeVK0uhRXTXdvO3O+YP0CaUX2g==", + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.6.tgz", + "integrity": "sha512-0BvMaZc1k9F+MeWWMe8pL6YltFzZYcJsYU7D4JyDA6PAczaXvxqQQ/z+mDF7/4Mw01DeUc+i3CTKajnkANkV4w==", "dev": true, "requires": { "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.0.1", + "@nodelib/fs.stat": "^1.1.2", "glob-parent": "^3.1.0", "is-glob": "^4.0.0", - "merge2": "^1.2.1", + "merge2": "^1.2.3", "micromatch": "^3.1.10" - }, - "dependencies": { - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - } } }, - "fast-json-parse": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz", - "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==", - "dev": true - }, "fast-json-patch": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-2.0.7.tgz", @@ -5023,9 +5434,9 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "fast-redact": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-1.4.0.tgz", - "integrity": "sha512-WsYhPdWJY+6d/pFJbBNWGUd5ENrBAJ6e7yDWcYNoFZoIQUUbKxnIRGS4d0kZkQlMPB4cLK3r4A0BZXpFxdoGhg==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-1.4.4.tgz", + "integrity": "sha512-QOQZ8sDDQPZMJ6x6zlm6hLZ2cjPDqfN3R/AYnAbM+yy8VNPvOnVXdUF/E/xbMv7g44c1krhWuzgjH2u0V5Vhsg==", "dev": true }, "fast-safe-stringify": { @@ -5091,18 +5502,6 @@ "object-assign": "^4.0.1" } }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true - }, - "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": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -5210,15 +5609,21 @@ } }, "flatstr": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.8.tgz", - "integrity": "sha512-YXblbv/vc1zuVVUtnKl1hPqqk7TalZCppnKE7Pr8FI/Rp48vzckS/4SJ4Y9O9RNiI82Vcw/FydmtqdQOg1Dpqw==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.9.tgz", + "integrity": "sha512-qFlJnOBWDfIaunF54/lBqNKmXOI0HqNhu+mHkLmbaBXlS71PUd9OjFOdyevHt/aHoHB1+eW7eKHgRKOG5aHSpw==", + "dev": true + }, + "flatted": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", "dev": true }, "fluent-syntax": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/fluent-syntax/-/fluent-syntax-0.7.0.tgz", - "integrity": "sha512-T0iqfhC40jrs3aDjYOKgzIQjjhsH2Fa6LnXB6naPv0ymW3DeYMUFa89y9aLKMpi1P9nl2vEimK7blx4tVnUWBg==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/fluent-syntax/-/fluent-syntax-0.10.0.tgz", + "integrity": "sha512-6qRhwQXDTgJjS9DW3IiXZWzUMUPqNPzqh+bZZyUOr6t8xYwkIe+5JONYZuvfvbOUk65paAno0kd8s8kUD2ptNA==", "dev": true }, "flush-write-stream": { @@ -5246,15 +5651,6 @@ "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" - } - }, "foreach": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", @@ -5859,42 +6255,6 @@ } } }, - "ftp": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", - "dev": true, - "requires": { - "readable-stream": "1.1.x", - "xregexp": "2.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.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 - } - } - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -5919,13 +6279,13 @@ "dev": true }, "fx-runner": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/fx-runner/-/fx-runner-1.0.9.tgz", - "integrity": "sha1-eyPzdz3HaqzELxHZr/J2lnXLY/A=", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fx-runner/-/fx-runner-1.0.10.tgz", + "integrity": "sha512-tXj0lMnSey89Dx7R3Lq+HMUy3ODmOmj5lhRYBgMWNOqbh7Vx8vPUiWMbyJ3HIzGuLnNeXAPH0x/GdFZ7h6h0vQ==", "dev": true, "requires": { "commander": "2.9.0", - "lodash": "4.17.10", + "lodash": "4.17.11", "shell-quote": "1.6.1", "spawn-sync": "1.0.15", "when": "3.7.7", @@ -6002,20 +6362,6 @@ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, - "get-uri": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.2.tgz", - "integrity": "sha512-ZD325dMZOgerGqF/rF6vZXyFGTAay62svjQIT+X/oU2PtxYpFxvSkbsdi+oxIrsNxlZVd4y8wUDqkaExWTI/Cw==", - "dev": true, - "requires": { - "data-uri-to-buffer": "1", - "debug": "2", - "extend": "3", - "file-uri-to-path": "1", - "ftp": "~0.3.10", - "readable-stream": "2" - } - }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -6077,42 +6423,6 @@ "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" - }, - "dependencies": { - "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" - } - }, - "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-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" - } - } - } - }, "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", @@ -6149,6 +6459,26 @@ "ini": "^1.3.4" } }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "requires": { + "global-prefix": "^3.0.0" + } + }, + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + } + }, "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", @@ -6223,15 +6553,6 @@ "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", "dev": true }, - "graphlib": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.5.tgz", - "integrity": "sha512-XvtbqCcw+EM5SqQrIetIKKD+uZVNQtDPD1goIg7K73RuRZtVI5rYMdcCVSHm/AS1sCBZ7vt0p5WgXouucHQaOA==", - "dev": true, - "requires": { - "lodash": "^4.11.1" - } - }, "growly": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", @@ -6254,9 +6575,9 @@ }, "dependencies": { "ajv": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.5.tgz", - "integrity": "sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", + "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -6347,23 +6668,6 @@ } } }, - "hasbin": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/hasbin/-/hasbin-1.2.3.tgz", - "integrity": "sha1-eMWSaJPIAhXCtWiuH9P8q3omlrA=", - "dev": true, - "requires": { - "async": "~1.5" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - } - } - }, "hash-base": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", @@ -6416,6 +6720,23 @@ "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, + "html-element-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.0.0.tgz", + "integrity": "sha512-/SP6aOiM5Ai9zALvCxDubIeez0LvG3qP7R9GcRDnJEP/HBmv0A8A9K0o8+HFudcFt46+i921ANjzKsjPjb7Enw==", + "dev": true, + "requires": { + "array-filter": "^1.0.0" + }, + "dependencies": { + "array-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=", + "dev": true + } + } + }, "html-encoding-sniffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", @@ -6444,39 +6765,6 @@ "readable-stream": "^2.0.2" } }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true, - "requires": { - "agent-base": "4", - "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==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -6493,33 +6781,6 @@ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", "dev": true }, - "https-proxy-agent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", - "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", - "dev": true, - "requires": { - "agent-base": "^4.1.0", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, "iconv-lite": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", @@ -6561,11 +6822,23 @@ "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", "dev": true }, - "immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", - "dev": true + "import-fresh": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz", + "integrity": "sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + } + } }, "import-lazy": { "version": "3.1.0", @@ -6717,12 +6990,6 @@ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, "irregular-plurals": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-2.0.0.tgz", @@ -6879,21 +7146,6 @@ "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", @@ -7048,18 +7300,6 @@ "isobject": "^3.0.1" } }, - "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-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", @@ -7219,12 +7459,6 @@ "integrity": "sha1-LPn7rkbYB0/Ba33gBxyO/rykc6Y=", "dev": true }, - "js-base64": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.6.tgz", - "integrity": "sha512-O9SR2NVICx6rCqh1qsU91QZ5IoNa+2T1ROJ0OQlfvATKGmnjsAvg3r0E5ufPZ4a95jdKTPXhFWiE/sOZ7a5Rtg==", - "dev": true - }, "js-select": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/js-select/-/js-select-0.6.0.tgz", @@ -7518,76 +7752,32 @@ } }, "jszip": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.1.5.tgz", - "integrity": "sha512-5W8NUaFRFRqTOL7ZDDrx5qWHJyBXy6velVudIzQUSoqAAYqzSh2Z7/m0Rf1QbmQJccegD0r+YZxBjzqoBiEeJQ==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-2.6.1.tgz", + "integrity": "sha1-uI86ey5noqBIFSmCx6N1bZxIKPA=", "dev": true, "requires": { - "core-js": "~2.3.0", - "es6-promise": "~3.0.2", - "lie": "~3.1.0", - "pako": "~1.0.2", - "readable-stream": "~2.0.6" - }, - "dependencies": { - "core-js": { - "version": "2.3.0", - "resolved": "http://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz", - "integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU=", - "dev": true - }, - "es6-promise": { - "version": "3.0.2", - "resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", - "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=", - "dev": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "readable-stream": { - "version": "2.0.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" - } - }, - "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 - } + "pako": "~1.0.2" } }, "jwa": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.6.tgz", - "integrity": "sha512-tBO/cf++BUsJkYql/kBbJroKOgHWEigTKBAjjBEmrMGYd1QMBC74Hr4Wo2zCZw6ZrVhlJPvoMrkcOnlWR/DJfw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.3.0.tgz", + "integrity": "sha512-SxObIyzv9a6MYuZYaSN6DhSm9j3+qkokwvCB0/OTSV5ylPq1wUQiygZQcHT5Qlux0I5kmISx3J86TxKhuefItg==", "dev": true, "requires": { "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.10", + "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "jws": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.5.tgz", - "integrity": "sha512-GsCSexFADNQUr8T5HPJvayTjvPIfoyJPtLQBwn5a4WZQchcrPMPMAWcC1AzJVRDKyD6ZPROPAxgv6rfHViO4uQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.1.tgz", + "integrity": "sha512-bGA2omSrFUkd72dhh05bIAN832znP4wOU3lfuXtRBuGTbsmNmDXMQg28f0Vsxaxgk4myF5YkKQpz6qeRpMgX9g==", "dev": true, "requires": { - "jwa": "^1.1.5", + "jwa": "^1.2.0", "safe-buffer": "^5.0.1" } }, @@ -7598,9 +7788,9 @@ "dev": true }, "known-css-properties": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.6.1.tgz", - "integrity": "sha512-nQRpMcHm1cQ6gmztdvLcIvxocznSMqH/y6XtERrWrHaymOYdDGroRqetJvJycxGEr1aakXiigDgn7JnzuXlk6A==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.11.0.tgz", + "integrity": "sha512-bEZlJzXo5V/ApNNa5z375mJC6Nrz4vG43UgcSCrg2OHC+yuB6j0iDSrY7RQ/+PRofFB03wNIIt9iXIVLr4wc7w==", "dev": true }, "latest-version": { @@ -7612,12 +7802,6 @@ "package-json": "^4.0.0" } }, - "lazy-cache": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", - "integrity": "sha1-f+3fLctu23fRHvHRF6tf/fCrG2U=", - "dev": true - }, "lazystream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", @@ -7641,6 +7825,12 @@ "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==" }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "dev": true + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -7650,15 +7840,6 @@ "type-check": "~0.3.2" } }, - "lie": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", - "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", - "dev": true, - "requires": { - "immediate": "~3.0.5" - } - }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -7707,55 +7888,31 @@ } }, "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" }, "lodash-es": { "version": "4.17.10", "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.10.tgz", "integrity": "sha512-iesFYPmxYYGTcmQK0sL8bX3TGHyM6b2qREaB4kamHfQyfPJP0xgoGxp19nsH16nsfquLdiyKyX3mQkfiSGV8Rg==" }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", - "dev": true - }, - "lodash.assignin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", - "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=", - "dev": true - }, "lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", "dev": true }, - "lodash.clone": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", - "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", - "dev": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", "dev": true }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "lodash.escape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", + "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=", "dev": true }, "lodash.flattendeep": { @@ -7764,12 +7921,6 @@ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, "lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -7782,6 +7933,12 @@ "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=", "dev": true }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, "lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", @@ -7827,12 +7984,6 @@ "resolved": "https://registry.npmjs.org/lodash.orderby/-/lodash.orderby-4.6.0.tgz", "integrity": "sha1-5pfwTOXXhSL1TZM4syuBozk+TrM=" }, - "lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=", - "dev": true - }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -7934,12 +8085,6 @@ "yallist": "^2.1.2" } }, - "macos-release": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-1.1.0.tgz", - "integrity": "sha512-mmLbumEYMi5nXReB9js3WGsB8UE6cDBWyIO62Z4DNx6GbRhDxHNjA1MlzSpJ2S2KM1wyiPRA0d19uHWYYvMHjA==", - "dev": true - }, "make-dir": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", @@ -7997,12 +8142,6 @@ "integrity": "sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==", "dev": true }, - "math-random": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", - "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", - "dev": true - }, "mathml-tag-names": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.0.tgz", @@ -8020,15 +8159,31 @@ } }, "mdast-util-compact": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", - "integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.2.tgz", + "integrity": "sha512-d2WS98JSDVbpSsBfVvD9TaDMlqPRz7ohM/11G0rp5jOBb5q96RJ6YLszQ/09AAixyzh23FeIpCGqfaamEADtWg==", "dev": true, "requires": { - "unist-util-modify-children": "^1.0.0", "unist-util-visit": "^1.1.0" } }, + "mdn-browser-compat-data": { + "version": "0.0.66", + "resolved": "https://registry.npmjs.org/mdn-browser-compat-data/-/mdn-browser-compat-data-0.0.66.tgz", + "integrity": "sha512-Exx+o05KYCltHmY2thfCoufBaHeqbIzqZHQPDtmcC+nkeFG++ONzwddBtgDBAKeI0IFFKqGIbRT1QBRwmk9QKA==", + "dev": true, + "requires": { + "extend": "3.0.2" + }, + "dependencies": { + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + } + } + }, "meant": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/meant/-/meant-1.0.1.tgz", @@ -8036,14 +8191,14 @@ "dev": true }, "mem": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz", - "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.1.0.tgz", + "integrity": "sha512-I5u6Q1x7wxO0kdOpYBB28xueHADYps5uty/zg936CiG8NTe5sJL8EjrCuLneuDW3PlMdZBGDIn8BirEVdovZvg==", "dev": true, "requires": { "map-age-cleaner": "^0.1.1", "mimic-fn": "^1.0.0", - "p-is-promise": "^1.1.0" + "p-is-promise": "^2.0.0" } }, "memory-fs": { @@ -8124,100 +8279,30 @@ } }, "merge2": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.2.tgz", - "integrity": "sha512-bgM8twH86rWni21thii6WCMQMRMmwqqdW3sGWi9IipnVAszdLXRjwDwAnyrVXo6DuP3AjRMMttZKUB48QWIFGg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.3.tgz", + "integrity": "sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==", "dev": true }, "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" - }, - "dependencies": { - "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" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "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" - } - }, - "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" - } - }, - "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" - } - }, - "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-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" - } - }, - "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" - } - } + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" } }, "miller-rabin": { @@ -8325,24 +8410,6 @@ } } }, - "mixin-object": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", - "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", - "dev": true, - "requires": { - "for-in": "^0.1.3", - "is-extendable": "^0.1.1" - }, - "dependencies": { - "for-in": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", - "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", - "dev": true - } - } - }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -8353,9 +8420,9 @@ } }, "moment": { - "version": "2.22.2", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", - "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=", + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==", "dev": true, "optional": true }, @@ -8490,169 +8557,40 @@ "integrity": "sha1-F7CVgZiJef3a/gIB6TG6kzyWy7Q=", "dev": true }, - "nconf": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.10.0.tgz", - "integrity": "sha512-fKiXMQrpP7CYWJQzKkPPx9hPgmq+YLDyxcG9N8RpiE9FoCkCbzD0NyW0YhE3xn3Aupe7nnDeIx4PFzYehpHT9Q==", + "ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", + "dev": true, + "optional": true + }, + "nearley": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.16.0.tgz", + "integrity": "sha512-Tr9XD3Vt/EujXbZBv6UAHYoLUSMQAxSsTnm9K3koXzjzNWY195NqALeyrzLZBKzAkL3gl92BcSogqrHjD8QuUg==", "dev": true, "requires": { - "async": "^1.4.0", - "ini": "^1.3.0", - "secure-keys": "^1.0.0", - "yargs": "^3.19.0" + "commander": "^2.19.0", + "moo": "^0.4.3", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6", + "semver": "^5.4.1" }, "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "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" - } - }, - "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 - }, - "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" - } - }, - "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" - } - }, - "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" - } - }, - "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" - } - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "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" - } - } - } - }, - "ncp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", - "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", - "dev": true, - "optional": true - }, - "nearley": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.15.0.tgz", - "integrity": "sha512-ZjzdO+yBtMrRrBbr+BJ35ECla6PGCAb/6hqpBQe7bmhEJabQ4rpVdj4sadP1Z1jQGyaDmm1GciQWsGVxIZ3uJA==", - "dev": true, - "requires": { - "moo": "^0.4.3", - "nomnom": "~1.6.2", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6", - "semver": "^5.4.1" - }, - "dependencies": { - "nomnom": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz", - "integrity": "sha1-hKZqJgF0QI/Ft3oY+IjszET7aXE=", - "dev": true, - "requires": { - "colors": "0.5.x", - "underscore": "~1.4.4" - } - }, - "underscore": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", - "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=", + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", "dev": true } } }, - "needle": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.4.tgz", - "integrity": "sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==", - "dev": true, - "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, "neo-async": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.1.tgz", "integrity": "sha512-3KL3fvuRkZ7s4IFOMfztb7zJp3QaVWnBeGoJlgB38XnCRPj/0tLzzLG5IB8NYOHbJ8g8UGrgZv44GLDk6CxTxA==", "dev": true }, - "netmask": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", - "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", - "dev": true - }, "next-tick": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", @@ -8711,12 +8649,6 @@ "vm-browserify": "0.0.4" } }, - "node-modules-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", - "dev": true - }, "node-notifier": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.2.1.tgz", @@ -8729,6 +8661,15 @@ "which": "^1.3.0" } }, + "node-releases": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.8.tgz", + "integrity": "sha512-gQm+K9mGCiT/NXHy+V/ZZS1N/LOaGGqRAAJJs3X9Ah1g+CIbRcBgNyoNYQ+SEtcyAtB9KqDruu+fF7nWjsqRaA==", + "dev": true, + "requires": { + "semver": "^5.3.0" + } + }, "nomnom": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", @@ -8931,16 +8872,6 @@ "has": "^1.0.1" } }, - "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.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -9075,12 +9006,12 @@ "dev": true }, "os-locale": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz", - "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { - "execa": "^0.10.0", + "execa": "^1.0.0", "lcid": "^2.0.0", "mem": "^4.0.0" }, @@ -9099,32 +9030,41 @@ } }, "execa": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", - "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, "requires": { "cross-spawn": "^6.0.0", - "get-stream": "^3.0.0", + "get-stream": "^4.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", "signal-exit": "^3.0.0", "strip-eof": "^1.0.0" } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } } } }, - "os-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-2.0.1.tgz", - "integrity": "sha1-uaOGNhwXrjohc27wWZQFyajF3F4=", - "dev": true, - "requires": { - "macos-release": "^1.0.0", - "win-release": "^1.0.0" - } - }, "os-shim": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz", @@ -9150,9 +9090,9 @@ "dev": true }, "p-is-promise": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.0.0.tgz", + "integrity": "sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg==", "dev": true }, "p-limit": { @@ -9179,52 +9119,6 @@ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, - "pac-proxy-agent": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-2.0.2.tgz", - "integrity": "sha512-cDNAN1Ehjbf5EHkNY5qnRhGPUCp6SnpyVof5fRzN800QV1Y2OkzbH9rmjZkbBRa8igof903yOnjIl6z0SlAhxA==", - "dev": true, - "requires": { - "agent-base": "^4.2.0", - "debug": "^3.1.0", - "get-uri": "^2.0.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "pac-resolver": "^3.0.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "^3.0.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "pac-resolver": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", - "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", - "dev": true, - "requires": { - "co": "^4.6.0", - "degenerator": "^1.0.4", - "ip": "^1.1.5", - "netmask": "^1.0.6", - "thunkify": "^2.1.2" - } - }, "package-json": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", @@ -9254,6 +9148,23 @@ "readable-stream": "^2.1.5" } }, + "parent-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.0.tgz", + "integrity": "sha512-8Mf5juOMmiE4FcmzYc4IaiS9L3+9paz2KOiXzkRviCP6aDmN49Hz6EMWz0lGNp9pX80GvvAuLADtyGfW/Em3TA==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + }, + "dependencies": { + "callsites": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.0.0.tgz", + "integrity": "sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw==", + "dev": true + } + } + }, "parse-asn1": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", @@ -9268,9 +9179,9 @@ } }, "parse-entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.2.tgz", - "integrity": "sha512-5N9lmQ7tmxfXf+hO3X6KRG6w7uYO/HL9fHalSySTdyn63C3WNvTM/1R8tn1u1larNcEbo3Slcy2bsVDQqvEpUg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.0.tgz", + "integrity": "sha512-XXtDdOPLSB0sHecbEapQi6/58U/ODj/KWfIXmmMCJF/eRn8laX6LZbOyioMoETOOJoWRW8/qTSl5VQkUIfKM5g==", "dev": true, "requires": { "character-entities": "^1.0.0", @@ -9281,35 +9192,6 @@ "is-hexadecimal": "^1.0.0" } }, - "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" - }, - "dependencies": { - "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-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" - } - } - } - }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -9334,16 +9216,6 @@ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, - "path": { - "version": "0.12.7", - "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", - "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=", - "dev": true, - "requires": { - "process": "^0.11.1", - "util": "^0.10.3" - } - }, "path-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", @@ -9441,31 +9313,17 @@ } }, "pino": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-5.5.0.tgz", - "integrity": "sha512-cCaBKVwutiaGwgKXyOvsRSCeBxgi2j0X1PEK1cog1/9SMDhgL8+iJwWvTKUef20HDyGfZIUq5KaH0ZOhWLHYSw==", + "version": "5.11.1", + "resolved": "https://registry.npmjs.org/pino/-/pino-5.11.1.tgz", + "integrity": "sha512-NIua0mGb9Adknq35ONvQmvh93LCUVUjp2+1q1EcvIkJmpJnSd3E5rHVKlKNjzMXFl/z3fI+QA0xXCjPEKNiLvQ==", "dev": true, "requires": { - "fast-json-parse": "^1.0.3", - "fast-redact": "^1.2.0", + "fast-redact": "^1.4.2", "fast-safe-stringify": "^2.0.6", - "flatstr": "^1.0.5", - "pino-std-serializers": "^2.2.1", - "pump": "^3.0.0", + "flatstr": "^1.0.9", + "pino-std-serializers": "^2.3.0", "quick-format-unescaped": "^3.0.0", - "sonic-boom": "^0.6.1" - }, - "dependencies": { - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } + "sonic-boom": "^0.7.1" } }, "pino-std-serializers": { @@ -9474,15 +9332,6 @@ "integrity": "sha512-klfGoOsP6sJH7ON796G4xoUSx2fkpFgKHO4YVVO2zmz31jR+etzc/QzGJILaOIiCD6HTCFgkPx+XN8nk+ruqPw==", "dev": true }, - "pirates": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.0.tgz", - "integrity": "sha512-8t5BsXy1LUIjn3WWOlOuFDuKswhQb/tkak641lvBgmPOBUQHXveORtlMCp6OdPV1dtuTaEahKA8VNz6uLfKBtA==", - "dev": true, - "requires": { - "node-modules-regexp": "^1.0.0" - } - }, "pkg-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", @@ -9577,59 +9426,131 @@ } }, "postcss-html": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-0.28.0.tgz", - "integrity": "sha512-H+ucbGVR+lsZySspOApeQU9yC6Q3t75lwJYa3Im93fKAUt5DScKOSErShC0aC7USdn2jsT1LxubcC5vYu/VJYw==", + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-0.36.0.tgz", + "integrity": "sha512-HeiOxGcuwID0AFsNAL0ox3mW6MHH5cstWN1Z3Y+n6H+g12ih7LHdYxWwEA/QmrebctLjo79xz9ouK3MroHwOJw==", + "dev": true, + "requires": { + "htmlparser2": "^3.10.0" + }, + "dependencies": { + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dev": true, + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + } + }, + "readable-stream": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz", + "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "postcss-jsx": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/postcss-jsx/-/postcss-jsx-0.36.0.tgz", + "integrity": "sha512-/lWOSXSX5jlITCKFkuYU2WLFdrncZmjSVyNpHAunEgirZXLwI8RjU556e3Uz4mv0WVHnJA9d3JWb36lK9Yx99g==", "dev": true, "requires": { - "htmlparser2": "^3.9.2" + "@babel/core": ">=7.1.0" } }, "postcss-less": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-2.0.0.tgz", - "integrity": "sha512-pPNsVnpCB13nBMOcl5GVh8JGmB0JGFjqkLUDzKdVpptFFKEe9wFdEzvh2j4lD2AD+7qcrUfw9Ta+oi5+Fw7jjQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-3.1.2.tgz", + "integrity": "sha512-66ZBVo1JGkQ7r13M97xcHcyarWpgg21RaqIZWZXHE3XOtb5+ywK1uZWeY1DYkYRkIX/l8Hvxnx9iSKB68nFr+w==", "dev": true, "requires": { - "postcss": "^5.2.16" + "postcss": "^7.0.14" }, "dependencies": { - "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 + "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" + } + }, + "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" + }, + "dependencies": { + "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" + } + } + } }, "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "^3.0.0" } } } }, "postcss-markdown": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/postcss-markdown/-/postcss-markdown-0.28.0.tgz", - "integrity": "sha512-F0Vc8eHKDKTmensntXpd35LSAoXXtykhPY+IRfn4AnN4m+irav3QawmtSWLhsmbElKna8l1/HObYnbiM/Wok9Q==", + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/postcss-markdown/-/postcss-markdown-0.36.0.tgz", + "integrity": "sha512-rl7fs1r/LNSB2bWRhyZ+lM/0bwKv9fhl38/06gF6mKMo/NPnp55+K1dSTosSVjFZc0e1ppBlu+WT91ba0PMBfQ==", "dev": true, "requires": { - "remark": "^9.0.0", + "remark": "^10.0.1", "unist-util-find-all-after": "^1.0.2" } }, @@ -9679,15 +9600,15 @@ } }, "postcss-reporter": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-5.0.0.tgz", - "integrity": "sha512-rBkDbaHAu5uywbCR2XE8a25tats3xSOsGNx6mppK6Q9kSFGKc/FyAzfci+fWM2l+K402p1D0pNcfDGxeje5IKg==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-6.0.1.tgz", + "integrity": "sha512-LpmQjfRWyabc+fRygxZjpRxfhRf9u/fdlKf4VHG4TSPbV2XNsuISzYW1KL+1aQzx53CAppa1bKG4APIB/DOXXw==", "dev": true, "requires": { - "chalk": "^2.0.1", - "lodash": "^4.17.4", - "log-symbols": "^2.0.0", - "postcss": "^6.0.8" + "chalk": "^2.4.1", + "lodash": "^4.17.11", + "log-symbols": "^2.2.0", + "postcss": "^7.0.7" }, "dependencies": { "ansi-styles": { @@ -9700,9 +9621,9 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "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", @@ -9710,10 +9631,38 @@ "supports-color": "^5.3.0" } }, + "postcss": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "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" @@ -9728,22 +9677,81 @@ "dev": true }, "postcss-safe-parser": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-3.0.1.tgz", - "integrity": "sha1-t1Pv9sfArqXoN1++TN6L+QY/8UI=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-4.0.1.tgz", + "integrity": "sha512-xZsFA3uX8MO3yAda03QrG3/Eg1LN3EPfjjf07vke/46HERLZyHrTsQ9E1r1w1W//fWEhtYNndo2hQplN2cVpCQ==", "dev": true, "requires": { - "postcss": "^6.0.6" + "postcss": "^7.0.0" + }, + "dependencies": { + "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" + } + }, + "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" + }, + "dependencies": { + "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" + } + } + } + }, + "postcss": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss-sass": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/postcss-sass/-/postcss-sass-0.3.2.tgz", - "integrity": "sha512-0HgxikiZ07VKYr98KT+k7/rAzyMgZlP+3+R8vUti56T2dPdhW0OhPGDQzddxY/N2iDtBVZQqCHRDA09j5I6EWg==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/postcss-sass/-/postcss-sass-0.3.5.tgz", + "integrity": "sha512-B5z2Kob4xBxFjcufFnhQ2HqJQ2y/Zs/ic5EZbCywCkxKd756Q40cIQ/veRDwSrw1BF6+4wUgmpm0sBASqVi65A==", "dev": true, "requires": { - "gonzales-pe": "4.2.3", - "postcss": "6.0.22" + "gonzales-pe": "^4.2.3", + "postcss": "^7.0.1" }, "dependencies": { "ansi-styles": { @@ -9756,25 +9764,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "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" + }, + "dependencies": { + "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" + } + } } }, "postcss": { - "version": "6.0.22", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.22.tgz", - "integrity": "sha512-Toc9lLoUASwGqxBSJGTVcOQiDqjK+Z2XlWBg+IgYwQMY9vA2f7iMpXVc1GpPcfTSyM5lkxNo0oDwDRO+wm7XHA==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.4.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -9784,9 +9803,9 @@ "dev": true }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -9795,12 +9814,71 @@ } }, "postcss-scss": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-1.0.6.tgz", - "integrity": "sha512-4EFYGHcEw+H3E06PT/pQQri06u/1VIIPjeJQaM8skB80vZuXMhp4cSNV5azmdNkontnOID/XYWEvEEELLFB1ww==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-2.0.0.tgz", + "integrity": "sha512-um9zdGKaDZirMm+kZFKKVsnKPF7zF7qBAtIfTSnZXD1jZ0JNZIxdB6TxQOjCnlSzLRInVl2v3YdBh/M881C4ug==", "dev": true, "requires": { - "postcss": "^6.0.23" + "postcss": "^7.0.0" + }, + "dependencies": { + "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" + } + }, + "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" + }, + "dependencies": { + "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" + } + } + } + }, + "postcss": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss-selector-parser": { @@ -9815,9 +9893,9 @@ } }, "postcss-syntax": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.28.0.tgz", - "integrity": "sha512-9W3T1fSE9QWKyW6s84kZapv0BP5uvj7mNBp34kwI93uGWULzZjaKv4xR4phubBD53cRgaM/qnvquVK1KLsl+Kg==", + "version": "0.36.2", + "resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.36.2.tgz", + "integrity": "sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==", "dev": true }, "postcss-value-parser": { @@ -9837,12 +9915,6 @@ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, "pretty-bytes": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.1.0.tgz", @@ -9867,6 +9939,14 @@ "next-tick": "^1.0.0", "request": "^2.83.0", "stream-parser": "~0.3.1" + }, + "dependencies": { + "deepmerge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", + "dev": true + } } }, "process": { @@ -9910,45 +9990,6 @@ "object-assign": "^4.1.1" } }, - "proxy-agent": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-2.3.1.tgz", - "integrity": "sha512-CNKuhC1jVtm8KJYFTS2ZRO71VCBx3QSA92So/e6NrY6GoJonkx3Irnk4047EsCcswczwqAekRj3s8qLRGahSKg==", - "dev": true, - "requires": { - "agent-base": "^4.2.0", - "debug": "^3.1.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "lru-cache": "^4.1.2", - "pac-proxy-agent": "^2.0.1", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^3.0.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", - "dev": true - }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -10023,9 +10064,9 @@ "dev": true }, "quick-format-unescaped": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-3.0.1.tgz", - "integrity": "sha512-Tnk4iJQ8x3V8ml3x9sLIf4tSDaVB9OJY/5gOrnxgK63CXKphhn8oYOPI4tqnXPQcZ3tCv7GFjeoYY5h6UAvuzg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-3.0.2.tgz", + "integrity": "sha512-FXTaCkwvpIlkdKeGDNgcq07SXWS383noQUuZjvdE1QcTt+eLuqof6/BDiEPqB59FWLie/l91+HtlJSw7iCViSA==", "dev": true }, "quick-lru": { @@ -10035,9 +10076,9 @@ "dev": true }, "raf": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.0.tgz", - "integrity": "sha512-pDP/NMRAXoTfrhCfyfSEwJAKLaxBU9eApMeBPB1TkDouZmvPerIClV8lTAd+uF8ZiTaVl69e1FCxQrAd/VTjGw==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", "dev": true, "requires": { "performance-now": "^2.1.0" @@ -10059,25 +10100,6 @@ "ret": "~0.1.10" } }, - "randomatic": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz", - "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", - "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 - } - } - }, "randombytes": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", @@ -10097,18 +10119,6 @@ "safe-buffer": "^5.1.0" } }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "dev": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - } - }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -10296,15 +10306,6 @@ "resolve": "^1.1.6" } }, - "recursive-readdir": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", - "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", - "dev": true, - "requires": { - "minimatch": "3.0.4" - } - }, "redent": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", @@ -10341,15 +10342,6 @@ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true }, - "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" - } - }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -10360,15 +10352,6 @@ "safe-regex": "^1.1.0" } }, - "regexp.prototype.flags": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", - "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", - "dev": true, - "requires": { - "define-properties": "^1.1.2" - } - }, "regexpp": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", @@ -10439,20 +10422,20 @@ } }, "remark": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", - "integrity": "sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/remark/-/remark-10.0.1.tgz", + "integrity": "sha512-E6lMuoLIy2TyiokHprMjcWNJ5UxfGQjaMSMhV+f4idM625UjjK4j798+gPs5mfjzDE6vL0oFKVeZM6gZVSVrzQ==", "dev": true, "requires": { - "remark-parse": "^5.0.0", - "remark-stringify": "^5.0.0", - "unified": "^6.0.0" + "remark-parse": "^6.0.0", + "remark-stringify": "^6.0.0", + "unified": "^7.0.0" } }, "remark-parse": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", - "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-6.0.3.tgz", + "integrity": "sha512-QbDXWN4HfKTUC0hHa4teU463KclLAnwpn/FBn87j9cKYJWWawbiLgMfP2Q4XwhxxuuuOxHlw+pSN0OKuJwyVvg==", "dev": true, "requires": { "collapse-white-space": "^1.0.2", @@ -10473,9 +10456,9 @@ } }, "remark-stringify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", - "integrity": "sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-6.0.4.tgz", + "integrity": "sha512-eRWGdEPMVudijE/psbIDNcnJLRVx3xhfuEsTDGgH4GsFF91dVhw5nhmnBppafJ7+NWINW6C7ZwWbi30ImJzqWg==", "dev": true, "requires": { "ccount": "^1.0.0", @@ -10562,18 +10545,18 @@ "dev": true }, "mime-db": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", - "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", + "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==", "dev": true }, "mime-types": { - "version": "2.1.21", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", - "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", + "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", "dev": true, "requires": { - "mime-db": "~1.37.0" + "mime-db": "~1.38.0" } }, "tough-cookie": { @@ -10754,20 +10737,12 @@ } }, "rxjs": { - "version": "5.5.12", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", - "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", "dev": true, "requires": { - "symbol-observable": "1.0.1" - }, - "dependencies": { - "symbol-observable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", - "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", - "dev": true - } + "tslib": "^1.9.0" } }, "safe-buffer": { @@ -10843,12 +10818,6 @@ } } }, - "secure-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/secure-keys/-/secure-keys-1.0.0.tgz", - "integrity": "sha1-8MgtmKOxOah3aogIBQuCRDEIf8o=", - "dev": true - }, "semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", @@ -10910,12 +10879,6 @@ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, "sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", @@ -10926,29 +10889,6 @@ "safe-buffer": "^5.0.1" } }, - "shallow-clone": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", - "integrity": "sha1-WQnodLp3EG1zrEFM/sH/yofZcGA=", - "dev": true, - "requires": { - "is-extendable": "^0.1.1", - "kind-of": "^2.0.1", - "lazy-cache": "^0.2.3", - "mixin-object": "^2.0.1" - }, - "dependencies": { - "kind-of": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", - "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", - "dev": true, - "requires": { - "is-buffer": "^1.0.2" - } - } - } - }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -10977,9 +10917,9 @@ } }, "shelljs": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.2.tgz", - "integrity": "sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ==", + "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", @@ -11011,23 +10951,6 @@ "when": "3.7.7" }, "dependencies": { - "babel-polyfill": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.16.0.tgz", - "integrity": "sha1-LUUCHfh+JqN0ttTRqcZZZNF/JCI=", - "dev": true, - "requires": { - "babel-runtime": "^6.9.1", - "core-js": "^2.4.0", - "regenerator-runtime": "^0.9.5" - } - }, - "core-js": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", - "dev": true - }, "es6-error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.0.0.tgz", @@ -11061,12 +10984,6 @@ "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", "dev": true }, - "regenerator-runtime": { - "version": "0.9.6", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.6.tgz", - "integrity": "sha1-0z65XQ0gAaS+OWWXB8UbDLcc4Ck=", - "dev": true - }, "request": { "version": "2.87.0", "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", @@ -11095,639 +11012,152 @@ "uuid": "^3.1.0" } }, - "source-map-support": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.6.tgz", - "integrity": "sha1-MlUqpktFg5KoXqs7C17mFScWeus=", - "dev": true, - "requires": { - "source-map": "^0.5.3" - } - } - } - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "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" - } - }, - "smart-buffer": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", - "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "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" - } - } - } - }, - "snyk": { - "version": "1.103.2", - "resolved": "https://registry.npmjs.org/snyk/-/snyk-1.103.2.tgz", - "integrity": "sha512-rmMsNW94SQdmWQEtVDW1hiGKb3r7Gx1hVb0bTuK9mCm4/lHGmyuAG7QYdcwdhMrhGjg7yQDWCEXorEnq2JLs7Q==", - "dev": true, - "requires": { - "abbrev": "^1.1.1", - "ansi-escapes": "^3.1.0", - "chalk": "^2.4.1", - "configstore": "^3.1.2", - "debug": "^3.1.0", - "hasbin": "^1.2.3", - "inquirer": "^3.0.0", - "lodash": "^4.17.5", - "needle": "^2.2.4", - "opn": "^5.2.0", - "os-name": "^2.0.1", - "proxy-agent": "^2.0.0", - "proxy-from-env": "^1.0.0", - "recursive-readdir": "^2.2.2", - "semver": "^5.5.0", - "snyk-config": "2.2.0", - "snyk-docker-plugin": "1.12.0", - "snyk-go-plugin": "1.5.2", - "snyk-gradle-plugin": "2.1.0", - "snyk-module": "1.8.2", - "snyk-mvn-plugin": "2.0.0", - "snyk-nodejs-lockfile-parser": "1.5.1", - "snyk-nuget-plugin": "1.6.5", - "snyk-php-plugin": "1.5.1", - "snyk-policy": "1.12.0", - "snyk-python-plugin": "1.8.2", - "snyk-resolve": "1.0.1", - "snyk-resolve-deps": "4.0.1", - "snyk-sbt-plugin": "2.0.0", - "snyk-tree": "^1.0.0", - "snyk-try-require": "1.3.1", - "source-map-support": "^0.5.9", - "tempfile": "^2.0.0", - "then-fs": "^2.0.0", - "undefsafe": "^2.0.0", - "uuid": "^3.2.1" - }, - "dependencies": { - "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" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", - "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.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" - } - } - } - }, - "snyk-config": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/snyk-config/-/snyk-config-2.2.0.tgz", - "integrity": "sha512-mq0wbP/AgjcmRq5i5jg2akVVV3iSYUPTowZwKn7DChRLDL8ySOzWAwan+ImXiyNbrWo87FNI/15O6MpOnTxOIg==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "lodash": "^4.17.5", - "nconf": "^0.10.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "snyk-docker-plugin": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/snyk-docker-plugin/-/snyk-docker-plugin-1.12.0.tgz", - "integrity": "sha512-QqKq2bGdnf1L2PNGQrHoqcoaV/PIlJv1qjKIzwA93gfhToKGkgJ31oPXwfef/l9N+ui0Y44c4POBHFbFf8PlJw==", - "dev": true, - "requires": { - "debug": "^3", - "tslib": "^1" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "snyk-go-plugin": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/snyk-go-plugin/-/snyk-go-plugin-1.5.2.tgz", - "integrity": "sha512-XWajcSh6Ld+I+WdcyU3DGDuE2ydThQd8ORkESy0nQ2LwekygLYVYN66OBy0uxpqYfd4qoqeg+J8lb4oGzCmyGA==", - "dev": true, - "requires": { - "graphlib": "^2.1.1", - "tmp": "0.0.33", - "toml": "^2.3.2" - } - }, - "snyk-gradle-plugin": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/snyk-gradle-plugin/-/snyk-gradle-plugin-2.1.0.tgz", - "integrity": "sha512-9gYJluomFZ5kaww5FoBvp4zUIsr27pEJ12jQJaVf0FJ0BmyYHmbCoxvHdqjCSYS2fVtF+fmPnvw0XKQOIwA1SA==", - "dev": true, - "requires": { - "clone-deep": "^0.3.0" - } - }, - "snyk-module": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/snyk-module/-/snyk-module-1.8.2.tgz", - "integrity": "sha512-XqhdbZ/CUuJ5gSaYdYfapLqx9qm2Mp6nyRMBCLXe9tJSiohOJsc9fQuUDbdOiRCqpA4BD6WLl+qlwOJmJoszBg==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "hosted-git-info": "^2.1.4" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "source-map-support": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.6.tgz", + "integrity": "sha1-MlUqpktFg5KoXqs7C17mFScWeus=", "dev": true, "requires": { - "ms": "^2.1.1" + "source-map": "^0.5.3" } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true } } }, - "snyk-mvn-plugin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/snyk-mvn-plugin/-/snyk-mvn-plugin-2.0.0.tgz", - "integrity": "sha512-9jAhZhv+7YcqtoQYCYlgMoxK+dWBKlk+wkX27Ebg3vNddNop9q5jZitRXTjsXwfSUZHRt+Ptw1f8vei9kjzZVg==", + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, - "snyk-nodejs-lockfile-parser": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/snyk-nodejs-lockfile-parser/-/snyk-nodejs-lockfile-parser-1.5.1.tgz", - "integrity": "sha512-rfFcW+ZrOEH3NxufUCpMBpNLSb4BPOxLbAM6MoRqfYH5DhSdTHsecwRDf1gU6XzQok/9Koav+1qtP8+welJC2A==", + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "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": { - "@yarnpkg/lockfile": "^1.0.2", - "lodash": "4.17.10", - "path": "0.12.7", - "source-map-support": "^0.5.7" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", - "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - } + "is-fullwidth-code-point": "^2.0.0" } }, - "snyk-nuget-plugin": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/snyk-nuget-plugin/-/snyk-nuget-plugin-1.6.5.tgz", - "integrity": "sha512-3qIndzkxCxiaGvAwMkqChbChGdwhNePPyfi0WjhC/nJGwecqU3Fb/NeTW7lgyT+xoq/dFnzW0DgBJ4+AyNA2gA==", + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, "requires": { - "debug": "^3.1.0", - "jszip": "^3.1.5", - "lodash": "^4.17.10", - "xml2js": "^0.4.17" + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" }, "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "ms": "^2.1.1" + "is-descriptor": "^0.1.0" } }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "snyk-php-plugin": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/snyk-php-plugin/-/snyk-php-plugin-1.5.1.tgz", - "integrity": "sha512-g5QSHBsRJ2O4cNxKC4zlWwnQYiSgQ77Y6QgGmo3ihPX3VLZrc1amaZIpPsNe1jwXirnGj2rvR5Xw+jDjbzvHFw==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "lodash": "^4.17.5", - "path": "0.12.7" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "ms": "^2.1.1" + "is-extendable": "^0.1.0" } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true } } }, - "snyk-policy": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/snyk-policy/-/snyk-policy-1.12.0.tgz", - "integrity": "sha512-CEioNnDzccHyid7UIVl3bJ1dnG4co4ofI+KxuC1mo0IUXy64gxnBTeVoZF5gVLWbAyxGxSeW8f0+8GmWMHVb7w==", + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "requires": { - "debug": "^3.1.0", - "email-validator": "^2.0.3", - "js-yaml": "^3.5.3", - "lodash.clonedeep": "^4.3.1", - "semver": "^5.5.0", - "snyk-module": "^1.8.2", - "snyk-resolve": "^1.0.1", - "snyk-try-require": "^1.1.1", - "then-fs": "^2.0.0" + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" }, "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "ms": "^2.1.1" + "is-descriptor": "^1.0.0" } }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "snyk-python-plugin": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/snyk-python-plugin/-/snyk-python-plugin-1.8.2.tgz", - "integrity": "sha512-LBvjztnXarSHKyhivzM567icOOLOB98I7S9EEnjepuG+EZ0jiZzqOEMVRmzuYi+hRq3Cwh0hhjkwgJAQpKDz+g==", - "dev": true, - "requires": { - "tmp": "0.0.33" - } - }, - "snyk-resolve": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/snyk-resolve/-/snyk-resolve-1.0.1.tgz", - "integrity": "sha512-7+i+LLhtBo1Pkth01xv+RYJU8a67zmJ8WFFPvSxyCjdlKIcsps4hPQFebhz+0gC5rMemlaeIV6cqwqUf9PEDpw==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "then-fs": "^2.0.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "kind-of": "^6.0.0" } }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "snyk-resolve-deps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/snyk-resolve-deps/-/snyk-resolve-deps-4.0.1.tgz", - "integrity": "sha512-gieaYoOuJLXzUmDDKfQJAqfwaxa43KmSqN2d9abRfgMXnLlX9IqyoZ1wqZMbd3WN7tsHSkpWvVwc4FHdQEkUKA==", - "dev": true, - "requires": { - "ansicolors": "^0.3.2", - "debug": "^3.2.5", - "lodash.assign": "^4.2.0", - "lodash.assignin": "^4.2.0", - "lodash.clone": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.get": "^4.4.2", - "lodash.set": "^4.3.2", - "lru-cache": "^4.0.0", - "semver": "^5.5.1", - "snyk-module": "^1.6.0", - "snyk-resolve": "^1.0.0", - "snyk-tree": "^1.0.0", - "snyk-try-require": "^1.1.1", - "then-fs": "^2.0.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "kind-of": "^6.0.0" } }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", - "dev": true + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, - "snyk-sbt-plugin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/snyk-sbt-plugin/-/snyk-sbt-plugin-2.0.0.tgz", - "integrity": "sha512-bOUqsQ1Lysnwfnvf4QQIBfC0M0ZVuhlshTKd7pNwgAJ41YEPJNrPEpzOePl/HfKtwilEEwHh5YHvjYGegEKx0A==", - "dev": true - }, - "snyk-tree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/snyk-tree/-/snyk-tree-1.0.0.tgz", - "integrity": "sha1-D7cxdtvzLngvGRAClBYESPkRHMg=", - "dev": true, - "requires": { - "archy": "^1.0.0" - } - }, - "snyk-try-require": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/snyk-try-require/-/snyk-try-require-1.3.1.tgz", - "integrity": "sha1-bgJvkuZK9/zM6h7lPVJIQeQYohI=", + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, "requires": { - "debug": "^3.1.0", - "lodash.clonedeep": "^4.3.0", - "lru-cache": "^4.0.0", - "then-fs": "^2.0.0" + "kind-of": "^3.2.0" }, "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "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": { - "ms": "^2.1.1" + "is-buffer": "^1.1.5" } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true } } }, - "socks": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz", - "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", - "dev": true, - "requires": { - "ip": "^1.1.4", - "smart-buffer": "^1.0.13" - } - }, - "socks-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz", - "integrity": "sha512-ZwEDymm204mTzvdqyUqOdovVr2YRd2NYskrYrF2LXyZ9qDiMAoFESGK8CRphiO7rtbo2Y757k2Nia3x2hGtalA==", - "dev": true, - "requires": { - "agent-base": "^4.1.0", - "socks": "^1.1.10" - } - }, "sonic-boom": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-0.6.3.tgz", - "integrity": "sha512-TMhj6kDJk9LLzCTTL8+HPCfFn4MwkE4P6k2Up89Rz949+DSRw90V62upRKC99rJEOmu4E9ljH5Otu2JSRmx+bg==", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-0.7.3.tgz", + "integrity": "sha512-A9EyoIeLD+g9vMLYQKjNCatJtAKdBQMW03+L8ZWWX/A6hq+srRCwdqHrBD1R8oSMLXov3oHN13dljtZf12q2Ow==", "dev": true, "requires": { - "flatstr": "^1.0.8" + "flatstr": "^1.0.9" } }, "source-list-map": { @@ -11813,9 +11243,9 @@ "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==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz", + "integrity": "sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==", "dev": true }, "split": { @@ -11894,12 +11324,6 @@ } } }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, "stealthy-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", @@ -12020,19 +11444,6 @@ } } }, - "string.prototype.matchall": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-2.0.0.tgz", - "integrity": "sha512-WoZ+B2ypng1dp4iFLF2kmZlwwlE19gmjgKuhL1FJfDgCREWb3ye3SDVHSzLH6bxfnvYmkCxbzkmWcQZHA4P//Q==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.10.0", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "regexp.prototype.flags": "^1.2.0" - } - }, "string.prototype.trim": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", @@ -12134,56 +11545,78 @@ "dev": true }, "stylelint": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-9.3.0.tgz", - "integrity": "sha512-u59pWTlrdwjqriJtTvO1a0wRK1mfbQQp7jLt27SX4zl2HmtVHOM/I1wd43xHTvUJZDKp1PTOpqRAamU3gFvmOA==", + "version": "9.10.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-9.10.1.tgz", + "integrity": "sha512-9UiHxZhOAHEgeQ7oLGwrwoDR8vclBKlSX7r4fH0iuu0SfPwFaLkb1c7Q2j1cqg9P7IDXeAV2TvQML/fRQzGBBQ==", "dev": true, "requires": { - "autoprefixer": "^8.0.0", + "autoprefixer": "^9.0.0", "balanced-match": "^1.0.0", "chalk": "^2.4.1", "cosmiconfig": "^5.0.0", - "debug": "^3.0.0", + "debug": "^4.0.0", "execall": "^1.0.0", - "file-entry-cache": "^2.0.0", + "file-entry-cache": "^4.0.0", "get-stdin": "^6.0.0", - "globby": "^8.0.0", + "global-modules": "^2.0.0", + "globby": "^9.0.0", "globjoin": "^0.1.4", "html-tags": "^2.0.0", - "ignore": "^3.3.3", + "ignore": "^5.0.4", "import-lazy": "^3.1.0", "imurmurhash": "^0.1.4", - "known-css-properties": "^0.6.0", + "known-css-properties": "^0.11.0", + "leven": "^2.1.0", "lodash": "^4.17.4", "log-symbols": "^2.0.0", "mathml-tag-names": "^2.0.1", "meow": "^5.0.0", - "micromatch": "^2.3.11", + "micromatch": "^3.1.10", "normalize-selector": "^0.2.0", - "pify": "^3.0.0", - "postcss": "^6.0.16", - "postcss-html": "^0.28.0", - "postcss-less": "^2.0.0", - "postcss-markdown": "^0.28.0", + "pify": "^4.0.0", + "postcss": "^7.0.13", + "postcss-html": "^0.36.0", + "postcss-jsx": "^0.36.0", + "postcss-less": "^3.1.0", + "postcss-markdown": "^0.36.0", "postcss-media-query-parser": "^0.2.3", - "postcss-reporter": "^5.0.0", + "postcss-reporter": "^6.0.0", "postcss-resolve-nested-selector": "^0.1.1", - "postcss-safe-parser": "^3.0.1", - "postcss-sass": "^0.3.0", - "postcss-scss": "^1.0.2", + "postcss-safe-parser": "^4.0.0", + "postcss-sass": "^0.3.5", + "postcss-scss": "^2.0.0", "postcss-selector-parser": "^3.1.0", - "postcss-syntax": "^0.28.0", + "postcss-syntax": "^0.36.2", "postcss-value-parser": "^3.3.0", "resolve-from": "^4.0.0", "signal-exit": "^3.0.2", - "specificity": "^0.3.1", - "string-width": "^2.1.0", + "slash": "^2.0.0", + "specificity": "^0.4.1", + "string-width": "^3.0.0", "style-search": "^0.1.0", - "sugarss": "^1.0.0", + "sugarss": "^2.0.0", "svg-tags": "^1.0.0", - "table": "^4.0.1" + "table": "^5.0.0" }, "dependencies": { + "ajv": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", + "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", + "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", + "dev": true + }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -12194,9 +11627,9 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "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", @@ -12205,27 +11638,136 @@ } }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" + } + }, + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "requires": { + "path-type": "^3.0.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "file-entry-cache": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-4.0.0.tgz", + "integrity": "sha512-AVSwsnbV8vH/UVbvgEhf3saVQXORNv0ZzSkvkhQIaia5Tia+JhGTaa/ePUSVoPHQyGayQNmYfkzFi3WZV5zcpA==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "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" } }, "globby": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.1.tgz", - "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-9.0.0.tgz", + "integrity": "sha512-q0qiO/p1w/yJ0hk8V9x1UXlgsXUxlGd0AHUOXZVXBO6aznDtpx7M8D1kBrCAItoPm+4l8r6ATXV1JpjY2SBQOw==", + "dev": true, + "requires": { + "array-union": "^1.0.2", + "dir-glob": "^2.2.1", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" + }, + "dependencies": { + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + } + } + }, + "ignore": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.0.5.tgz", + "integrity": "sha512-kOC8IUb8HSDMVcYrDVezCxpJkzSQWTAzf3olpKM6o9rM5zpojx23O0Fl8Wr4+qJ6ZbPEHqf1fdwev/DS7v7pmA==", + "dev": true + }, + "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 + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "postcss": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "array-union": "^1.0.1", - "dir-glob": "^2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "resolve-from": { @@ -12234,14 +11776,87 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, + "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" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "string-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.0.0.tgz", + "integrity": "sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.0.0" + } + }, + "strip-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", + "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", + "dev": true, + "requires": { + "ansi-regex": "^4.0.0" + } + }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "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": "5.2.3", + "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz", + "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==", + "dev": true, + "requires": { + "ajv": "^6.9.1", + "lodash": "^4.17.11", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + } + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } } } }, @@ -12261,12 +11876,71 @@ } }, "sugarss": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-1.0.1.tgz", - "integrity": "sha512-3qgLZytikQQEVn1/FrhY7B68gPUUGY3R1Q1vTiD5xT+Ti1DP/8iZuwFet9ONs5+bmL8pZoDQ6JrQHVgrNlK6mA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-2.0.0.tgz", + "integrity": "sha512-WfxjozUk0UVA4jm+U1d736AUpzSrNsQcIbyOkoE364GrtWmIrFdk5lksEupgWMD4VaT/0kVx1dobpiDumSgmJQ==", "dev": true, "requires": { - "postcss": "^6.0.14" + "postcss": "^7.0.2" + }, + "dependencies": { + "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" + } + }, + "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" + }, + "dependencies": { + "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" + } + } + } + }, + "postcss": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "supports-color": { @@ -12423,22 +12097,6 @@ "xtend": "^4.0.0" } }, - "temp-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", - "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", - "dev": true - }, - "tempfile": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz", - "integrity": "sha1-awRGhWqbERTRhW/8vlCczLCXcmU=", - "dev": true, - "requires": { - "temp-dir": "^1.0.0", - "uuid": "^3.0.1" - } - }, "term-size": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", @@ -12454,15 +12112,6 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "then-fs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/then-fs/-/then-fs-2.0.0.tgz", - "integrity": "sha1-cveS3Z0xcFqRrhnr/Piz+WjIHaI=", - "dev": true, - "requires": { - "promise": ">=3.2 <8" - } - }, "thenify": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", @@ -12497,12 +12146,6 @@ "xtend": "~4.0.1" } }, - "thunkify": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", - "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", - "dev": true - }, "timed-out": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", @@ -12593,12 +12236,6 @@ "repeat-string": "^1.6.1" } }, - "toml": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.3.tgz", - "integrity": "sha512-O7L5hhSQHxuufWUdcTRPfuTh3phKfAZ/dqfxZFoxPCj2RYmpaSGLEIs016FCXItQwNr08yefUB5TSjzRYnajTA==", - "dev": true - }, "tosource": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/tosource/-/tosource-1.0.0.tgz", @@ -12659,9 +12296,9 @@ "dev": true }, "trough": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.2.tgz", - "integrity": "sha512-FHkoUZvG6Egrv9XZAyYGKEyb1JMsFphgPjoczkZC2y6W93U1jswcVURB8MUvtsahEPEVACyxD47JAL63vF4JsQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.3.tgz", + "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==", "dev": true }, "tslib": { @@ -12757,15 +12394,6 @@ } } }, - "undefsafe": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.2.tgz", - "integrity": "sha1-Il9rngM3Zj4Njnz9aG/Cg2zKznY=", - "dev": true, - "requires": { - "debug": "^2.2.0" - } - }, "underscore": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", @@ -12793,16 +12421,18 @@ } }, "unified": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", - "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-7.1.0.tgz", + "integrity": "sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw==", "dev": true, "requires": { + "@types/unist": "^2.0.0", + "@types/vfile": "^3.0.0", "bail": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^1.1.0", "trough": "^1.0.0", - "vfile": "^2.0.0", + "vfile": "^3.0.0", "x-is-string": "^0.1.0" } }, @@ -12889,15 +12519,6 @@ "integrity": "sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw==", "dev": true }, - "unist-util-modify-children": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.2.tgz", - "integrity": "sha512-GRi04yhng1WqBf5RBzPkOtWAadcZS2gvuOgNn/cyJBYNxtTuyYqTKN0eg4rC1YJwGnzrqfRB3dSKm8cNCjNirg==", - "dev": true, - "requires": { - "array-iterate": "^1.0.0" - } - }, "unist-util-remove-position": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz", @@ -12914,12 +12535,21 @@ "dev": true }, "unist-util-visit": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.1.tgz", - "integrity": "sha512-0fdB9EQJU0tho5tK0VzOJzAQpPv2LyLZ030b10GxuzAWEfvd54mpY7BMjQ1L69k2YNvL+SvxRzH0yUIehOO8aA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.0.tgz", + "integrity": "sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw==", + "dev": true, + "requires": { + "unist-util-visit-parents": "^2.0.0" + } + }, + "unist-util-visit-parents": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz", + "integrity": "sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA==", "dev": true, "requires": { - "unist-util-is": "^2.1.1" + "unist-util-is": "^2.1.2" } }, "universalify": { @@ -12928,12 +12558,6 @@ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -13150,27 +12774,35 @@ } }, "vfile": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", - "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-3.0.1.tgz", + "integrity": "sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ==", "dev": true, "requires": { - "is-buffer": "^1.1.4", + "is-buffer": "^2.0.0", "replace-ext": "1.0.0", "unist-util-stringify-position": "^1.0.0", "vfile-message": "^1.0.0" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", + "dev": true + } } }, "vfile-location": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.3.tgz", - "integrity": "sha512-zM5/l4lfw1CBoPx3Jimxoc5RNDAHHpk6AM6LM0pTIkm5SUSsx8ZekZ0PVdf0WEZ7kjlhSt7ZlqbRL6Cd6dBs6A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.4.tgz", + "integrity": "sha512-KRL5uXQPoUKu+NGvQVL4XLORw45W62v4U4gxJ3vRlDfI9QsT4ZN1PNXn/zQpKUulqGDpYuT0XDfp5q9O87/y/w==", "dev": true }, "vfile-message": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.1.tgz", - "integrity": "sha512-vSGCkhNvJzO6VcWC6AlJW4NtYOVtS+RgCaqFIYUjoGIlHnFL+i0LbtYvonDWOMcB97uTPT4PRsyYY7REWC9vug==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", + "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", "dev": true, "requires": { "unist-util-stringify-position": "^1.1.1" @@ -13214,17 +12846,17 @@ } }, "web-ext": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/web-ext/-/web-ext-2.9.2.tgz", - "integrity": "sha512-eJYKR7BMlpWXSeOP91LvsQkLHKcRE8wWkQYdlEkHzntASlFMbGZcIk6/R5myA/Yo5E87WWoCmqKO9rdUSVtQMA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/web-ext/-/web-ext-3.0.0.tgz", + "integrity": "sha512-pUT2YYSnECH/SqKXB0m92HWzAAOt97wJpkSHu7AddyxzclN3R9A2IHq+KUzaXEjiwWzVs/+yUOSpmuwCDouNNg==", "dev": true, "requires": { + "@babel/polyfill": "7.2.5", + "@babel/runtime": "7.3.1", "@cliqz-oss/firefox-client": "0.3.1", "@cliqz-oss/node-firefox-connect": "1.2.1", "adbkit": "2.11.0", - "addons-linter": "1.3.8", - "babel-polyfill": "6.26.0", - "babel-runtime": "6.26.0", + "addons-linter": "1.6.1", "bunyan": "1.8.12", "camelcase": "4.1.0", "debounce": "1.1.0", @@ -13233,7 +12865,7 @@ "es6-promisify": "5.0.0", "event-to-promise": "0.8.0", "firefox-profile": "1.2.0", - "fx-runner": "1.0.9", + "fx-runner": "1.0.10", "git-rev-sync": "1.9.1", "mkdirp": "0.5.1", "multimatch": "2.1.0", @@ -13241,7 +12873,6 @@ "node-notifier": "5.2.1", "opn": "5.3.0", "parse-json": "4.0.0", - "regenerator-runtime": "0.11.1", "require-uncached": "1.0.3", "sign-addon": "0.3.1", "source-map-support": "0.5.3", @@ -13287,12 +12918,6 @@ "requires": { "source-map": "^0.6.0" } - }, - "xregexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", - "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", - "dev": true } } }, @@ -13690,21 +13315,6 @@ "string-width": "^2.1.1" } }, - "win-release": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/win-release/-/win-release-1.1.1.tgz", - "integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=", - "dev": true, - "requires": { - "semver": "^5.0.1" - } - }, - "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 - }, "winreg": { "version": "0.0.12", "resolved": "https://registry.npmjs.org/winreg/-/winreg-0.0.12.tgz", @@ -13836,9 +13446,9 @@ "dev": true }, "xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", + "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", "dev": true }, "xtend": { @@ -14053,9 +13663,9 @@ } }, "yauzl": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.2.tgz", - "integrity": "sha1-T7G8euH8L1cDe1SvasyP4QMcW3c=", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", "dev": true, "requires": { "buffer-crc32": "~0.2.3", @@ -14077,15 +13687,6 @@ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true - }, - "jszip": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-2.6.1.tgz", - "integrity": "sha1-uI86ey5noqBIFSmCx6N1bZxIKPA=", - "dev": true, - "requires": { - "pako": "~1.0.2" - } } } }, diff --git a/package.json b/package.json index f93d067..f0ac93b 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "babel-preset-react": "6.24.1", "copy-webpack-plugin": "4.5.2", "css-loader": "1.0.0", - "enzyme": "3.3.0", + "enzyme": "3.9.0", "enzyme-adapter-react-16": "1.1.1", "eslint": "4.19.1", "eslint-config-airbnb": "17.0.0", @@ -39,11 +39,11 @@ "generate-json-webpack-plugin": "0.3.1", "null-loader": "0.1.1", "style-loader": "0.21.0", - "stylelint": "9.3.0", + "stylelint": "9.10.1", "stylelint-config-standard": "18.2.0", "tap-mocha-reporter": "3.0.7", "tape": "4.9.1", - "web-ext": "2.9.2", + "web-ext": "3.0.0", "webpack": "4.15.1", "webpack-command": "0.3.1", "webpack-merge": "4.1.4" From 63d8b6099ce803d90eda0175130fd62bf514428e Mon Sep 17 00:00:00 2001 From: Bianca Danforth Date: Tue, 19 Mar 2019 12:23:50 -0700 Subject: [PATCH 111/140] Change name to Price Tracker Find and replace all instances of "Price Wise", "price-wise" and "price_wise" (case insensitive) with the following exceptions: * The telemetry event category, 'extension.price_wise' for continuity. * The survey URLs (for [feedback](https://qsurvey.mozilla.com/s3/price-wise) linked to in the popup and the now flagged off [UR study](https://qsurvey.mozilla.com/s3/Price-Wise-Research-Study)). Note: Updating the name of the project in `package.json` and calling `npm install` also triggered adding an additional [`optional`](https://docs.npmjs.com/files/package-lock.json#optional) key in `package-lock.json` for some devDeps. --- .circleci/config.yml | 4 +- .circleci/deploy_addon.sh | 2 +- README.md | 16 +++---- docs/METRICS.md | 8 ++-- package-lock.json | 43 +++++++++++++------ package.json | 10 ++--- .../components/EmptyOnboarding.jsx | 4 +- src/browser_action/components/StudyFooter.jsx | 2 +- .../components/StudyInvitation.jsx | 2 +- src/browser_action/index.html | 2 +- src/intro.html | 16 +++---- src/manifest.json | 4 +- 12 files changed, 66 insertions(+), 47 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a632f3a..acf1353 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -47,7 +47,7 @@ jobs: - run: name: Store XPI name in environment variable command: | - echo 'export XPI_NAME=price_wise-${CIRCLE_TAG:1}' >> $BASH_ENV + echo 'export XPI_NAME=price_tracker-${CIRCLE_TAG:1}' >> $BASH_ENV - run: name: Install dependencies command: | @@ -77,7 +77,7 @@ jobs: - run: name: Store XPI name in environment variable command: | - echo 'export XPI_NAME=price_wise-${CIRCLE_TAG:1}' >> $BASH_ENV + echo 'export XPI_NAME=price_tracker-${CIRCLE_TAG:1}' >> $BASH_ENV - run: name: Install dependencies command: | diff --git a/.circleci/deploy_addon.sh b/.circleci/deploy_addon.sh index 91bc835..8848bca 100755 --- a/.circleci/deploy_addon.sh +++ b/.circleci/deploy_addon.sh @@ -9,7 +9,7 @@ set -e ADDON_ID="shopping-testpilot@mozilla.org" ADDON_VERSION=${CIRCLE_TAG:1} -ADDON_FILE="web-ext-artifacts/price_wise-${ADDON_VERSION}-signed.xpi" +ADDON_FILE="web-ext-artifacts/price_tracker-${ADDON_VERSION}-signed.xpi" test -f $ADDON_FILE MAX_AGE=30 # We can up this at some point, but keeping it low while we work out the kinks diff --git a/README.md b/README.md index ab4f2b4..6b11ab1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Price Wise +# Price Tracker -Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy. +Price Tracker is a Firefox extension that tracks price changes to help you find the best time to buy. ## Data Collection @@ -17,8 +17,8 @@ Prerequisites: 1. Clone the repository: ```sh - git clone https://github.com/mozilla/price-wise.git - cd price-wise + git clone https://github.com/mozilla/price-tracker.git + cd price-tracker ``` 2. Install dependencies: @@ -97,7 +97,7 @@ With these installed, you can set up the test suite: 2. Save the path to your Firefox binary with `npm`: ```sh - npm config set price-wise:firefox_bin + npm config set price-tracker:firefox_bin ``` After this, you can run `pipenv run test` to run the automated test suite. @@ -132,12 +132,12 @@ The following preferences can be set to customize the extension's behavior for t ## Releasing a New Version -Price Wise bumps the major version number for every release, similar to Firefox. Releases are created by tagging a commit that bumps the version number and pushing that tag to the repo. This triggers CircleCI automation that packages, tests, signs and uploads the new version to the Test Pilot S3 bucket. +Price Tracker bumps the major version number for every release, similar to Firefox. Releases are created by tagging a commit that bumps the version number and pushing that tag to the repo. This triggers CircleCI automation that packages, tests, signs and uploads the new version to the Test Pilot S3 bucket. It is strongly recommended that developers creating releases [configure Git to sign their commits and tags][signing]. -To create a new release of Price Wise: +To create a new release of Price Tracker: 1. Increment the version number in `package.json`, create a new commit on the `master` branch with this change, and create a new git tag pointing to the commit with a name of the form `v1.0.0`, where `1.0.0` is the new version number. @@ -146,7 +146,7 @@ To create a new release of Price Wise: ```sh npm version major ``` -2. Push the updated `master` branch and the new tag to the remote for the Mozilla Price Wise repository (named `origin` in the example below): +2. Push the updated `master` branch and the new tag to the remote for the Mozilla Price Tracker repository (named `origin` in the example below): ```sh git push origin master diff --git a/docs/METRICS.md b/docs/METRICS.md index 07e6787..9e62ea7 100644 --- a/docs/METRICS.md +++ b/docs/METRICS.md @@ -3,7 +3,7 @@ # Metrics -A summary of the metrics the Price Wise extension will record. +A summary of the metrics the Price Tracker extension will record. ## Definitions @@ -14,14 +14,14 @@ A summary of the metrics the Price Wise extension will record. * **Price Alert**: An alert that occurs when a tracked product's price _decreases_ below a certain absolute or percentage threshold. For the MVP, the default thresholds are specified in `./src/config.js`. * **Product Card**: A product list item in the list of tracked products for which the user has opted to receive Price Alerts displayed on the browserAction popup. Each Product Card displays the product title, image and price among other information. * **Product Page**: A webpage displaying a single product that the user could purchase online. -* **Supported Sites**: For the initial launch (a.k.a. MVP, Minimum Viable Product) of this extension, we are limiting the sites supported by this feature to [five websites](https://github.com/mozilla/price-wise/issues/36#issuecomment-409641491): Amazon, eBay, Walmart, Home Depot and Best Buy. +* **Supported Sites**: For the initial launch (a.k.a. MVP, Minimum Viable Product) of this extension, we are limiting the sites supported by this feature to [five websites](https://github.com/mozilla/price-tracker/issues/36#issuecomment-409641491): Amazon, eBay, Walmart, Home Depot and Best Buy. * **Survey**: a short survey collecting user feedback. * **Onboarding Popup**: The popup displayed when the user has zero products tracked, including the first time the popup is opened. ## Analysis -Data collected by the Price Wise extension will be used to answer the following questions: +Data collected by the Price Tracker extension will be used to answer the following questions: Note: For any questions related to general user shopping behavior, the data about what sites users visit is limited to the Supported Sites for the MVP. @@ -215,7 +215,7 @@ Some `extra_keys` are sent with every telemetry event recorded by the extension: ### `open_popup` -Fired when the user clicks the Price Wise browserAction toolbar button to open the popup. +Fired when the user clicks the Price Tracker browserAction toolbar button to open the popup. #### Payload properties - `methods`: String diff --git a/package-lock.json b/package-lock.json index 2f3d466..f55ab5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "price-wise", + "name": "price-tracker", "version": "21.0.0", "lockfileVersion": 1, "requires": true, @@ -5746,7 +5746,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -5767,12 +5768,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5787,17 +5790,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -5914,7 +5920,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -5926,6 +5933,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5940,6 +5948,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5947,12 +5956,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -5971,6 +5982,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -6051,7 +6063,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -6063,6 +6076,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -6148,7 +6162,8 @@ "safe-buffer": { "version": "5.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -6184,6 +6199,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6203,6 +6219,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6246,12 +6263,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, diff --git a/package.json b/package.json index f0ac93b..4e9149f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "price-wise", + "name": "price-tracker", "version": "21.0.0", - "description": "Price Wise is a Firefox extension that tracks price changes to help you find the best time to buy.", + "description": "Price Tracker is a Firefox extension that tracks price changes to help you find the best time to buy.", "private": true, "author": "Mozilla", "license": "MPL-2.0", @@ -65,11 +65,11 @@ }, "repository": { "type": "git", - "url": "https://github.com/mozilla/price-wise.git" + "url": "https://github.com/mozilla/price-tracker.git" }, "keywords": [], "bugs": { - "url": "https://github.com/mozilla/price-wise/issues" + "url": "https://github.com/mozilla/price-tracker/issues" }, - "homepage": "https://github.com/mozilla/price-wise" + "homepage": "https://github.com/mozilla/price-tracker" } diff --git a/src/browser_action/components/EmptyOnboarding.jsx b/src/browser_action/components/EmptyOnboarding.jsx index c34e992..7527566 100644 --- a/src/browser_action/components/EmptyOnboarding.jsx +++ b/src/browser_action/components/EmptyOnboarding.jsx @@ -58,10 +58,10 @@ export default class EmptyOnboarding extends React.Component { {' '}eBay, {' '}Home Depot and {' '}Walmart - {' '}(U.S. domains only for now). When Price Wise finds a price drop, the add-on gives you a heads-up about the lower price. + {' '}(U.S. domains only for now). When Price Tracker finds a price drop, the add-on gives you a heads-up about the lower price.

- Price Wise keeps track of your saved products by occasionally loading their webpages in + Price Tracker keeps track of your saved products by occasionally loading their webpages in the background while Firefox is open.

diff --git a/src/browser_action/components/StudyFooter.jsx b/src/browser_action/components/StudyFooter.jsx index 286eae1..6a3fdba 100644 --- a/src/browser_action/components/StudyFooter.jsx +++ b/src/browser_action/components/StudyFooter.jsx @@ -25,7 +25,7 @@ export default class StudyFooter extends React.Component { className="menu-item study" onClick={this.props.onClick} > - Help us improve Price Wise… + Help us improve Price Tracker… ); } diff --git a/src/browser_action/components/StudyInvitation.jsx b/src/browser_action/components/StudyInvitation.jsx index 0c90d72..2ec85dd 100644 --- a/src/browser_action/components/StudyInvitation.jsx +++ b/src/browser_action/components/StudyInvitation.jsx @@ -40,7 +40,7 @@ export default class StudyInvitation extends React.Component {

- {"Help us improve Price Wise by participating in a research study. Take this 5-minute survey to learn more about the study and see if you're a fit."} + {"Help us improve Price Tracker by participating in a research study. Take this 5-minute survey to learn more about the study and see if you're a fit."}