diff --git a/.distignore b/.distignore new file mode 100644 index 00000000000..cbeeef597c5 --- /dev/null +++ b/.distignore @@ -0,0 +1,26 @@ +.* +.*/ +*.lock +*.md +*.zip +/bin/ +/build/ +/node_modules/ +/tests/ +babel.config.js +CHANGELOG.txt +composer.* +contributors.html +docker-compose.yaml +Dockerfile +Gruntfile.js +none +package-lock.json +package.json +packages/woocommerce-admin/docs +phpcs.xml +phpunit.xml +phpunit.xml.dist +README.md +renovate.json +webpack.config.js diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index f38d1a2ab7f..00000000000 --- a/.eslintrc +++ /dev/null @@ -1,40 +0,0 @@ -{ - "root": true, - "env": { - "browser": true, - "es6": true, - "node": true, - "jest/globals": true - }, - "globals": { - "wp": true, - "wpApiSettings": true, - "wcSettings": true, - "es6": true, - "page": true, - "browser": true, - "context": true, - "jestPuppeteer": true - }, - "rules": { - "camelcase": 0, - "indent": 0, - "max-len": [ 2, { "code": 140 } ], - "no-console": 1 - }, - "plugins": [ - "jest" - ], - "extends": [ - "plugin:jest/recommended" - ], - "parser": "babel-eslint", - "parserOptions": { - "ecmaVersion": 8, - "ecmaFeatures": { - "modules": true, - "experimentalObjectRestSpread": true, - "jsx": true - } - } -} diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000000..d152f7b934a --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,35 @@ +/** @format */ +const baseConfig = require( '@woocommerce/e2e-environment' ).esLintConfig; + +module.exports = { + ...baseConfig, + root: true, + env: { + ...baseConfig.env, + browser: true, + es6: true, + node: true + }, + globals: { + ...baseConfig.globals, + wp: true, + wpApiSettings: true, + wcSettings: true, + es6: true + }, + rules: { + camelcase: 0, + indent: 0, + 'max-len': [ 2, { 'code': 140 } ], + 'no-console': 1 + }, + parser: 'babel-eslint', + parserOptions: { + ecmaVersion: 8, + ecmaFeatures: { + modules: true, + experimentalObjectRestSpread: true, + jsx: true + } + }, +}; diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 3019353697d..82dc600b065 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,48 +1,7 @@ - + - +**Prerequisites (mark completed items with an [x]):** +- [ ] I have checked that my issue type is not listed here https://github.com/woocommerce/woocommerce/issues/new/choose +- [ ] My issue is not a security issue, support request, bug report, enhancement or feature request (Please use the link above if it is). - - - - - - -## Prerequisites - - - -- [ ] I have searched for similar issues in both open and closed tickets and cannot find a duplicate -- [ ] The issue still exists against the latest `master` branch of WooCommerce on Github (this is **not** the same version as on WordPress.org!) -- [ ] I have attempted to find the simplest possible steps to reproduce the issue -- [ ] I have included a failing test as a pull request (Optional) - -## Steps to reproduce the issue - - - -1. -2. -3. - -## Expected/actual behavior - -When I follow those steps, I see... - -I was expecting to see... - -## Isolating the problem - - - -- [ ] This bug happens with only WooCommerce plugin active -- [ ] This bug happens with a default WordPress theme active, or [Storefront](https://woocommerce.com/storefront/) -- [ ] I can reproduce this bug consistently using the steps above - -## WordPress Environment - -
-``` -Copy and paste the system status report from **WooCommerce > System Status** in WordPress admin here. -``` -
+**Issue Description:** diff --git a/.github/ISSUE_TEMPLATE/1-Security-issue.md b/.github/ISSUE_TEMPLATE/1-Security-issue.md index 9775c1c2c0c..7c78be16976 100644 --- a/.github/ISSUE_TEMPLATE/1-Security-issue.md +++ b/.github/ISSUE_TEMPLATE/1-Security-issue.md @@ -1,5 +1,5 @@ --- -name: "\U0001F46E‍♂️ Security issue" +name: "\U0001F512 Security issue" about: Please report security issues *only* via https://www.hackerone.com title: '' labels: '' diff --git a/.github/ISSUE_TEMPLATE/2-External-issues.md b/.github/ISSUE_TEMPLATE/2-External-issues.md index 5d1e0e7c6ab..59f52cf6770 100644 --- a/.github/ISSUE_TEMPLATE/2-External-issues.md +++ b/.github/ISSUE_TEMPLATE/2-External-issues.md @@ -1,10 +1,18 @@ --- name: "\U0001F47D External issues" -about: Please report WooCommerce REST API or WooCommerce Gutenberg Products Blocks issues directly to their respective repositories. +about: Please report WooCommerce REST API, WooCommerce Admin or WooCommerce Gutenberg Products Blocks issues directly to their respective repositories. title: '' labels: '' assignees: '' --- -Please report WooCommerce REST API (https://github.com/woocommerce/woocommerce-rest-api) or WooCommerce Gutenberg Products Blocks (https://github.com/woocommerce/woocommerce-gutenberg-products-block) issues directly to their respective repositories. +Please report issues for the following features directly to their respective repositories. + +WooCommerce REST API: https://github.com/woocommerce/woocommerce-rest-api + +WooCommerce Admin: https://github.com/woocommerce/woocommerce-admin + +WooCommerce Gutenberg Products Blocks: https://github.com/woocommerce/woocommerce-gutenberg-products-block + +Action Scheduler: https://github.com/woocommerce/action-scheduler diff --git a/.github/ISSUE_TEMPLATE/3-Support.md b/.github/ISSUE_TEMPLATE/3-Support.md index 6804c6d2c99..3ae796e2030 100644 --- a/.github/ISSUE_TEMPLATE/3-Support.md +++ b/.github/ISSUE_TEMPLATE/3-Support.md @@ -16,10 +16,13 @@ Usage docs can be found here: https://docs.woocommerce.com/ If you have a problem, you may want to start with the self help guide here: https://docs.woocommerce.com/document/woocommerce-self-service-guide/ **Technical support for premium extensions or if you're a WooCommerce.com customer** - from a human being - submit a ticket via the helpdesk +Contact WooCommerce support by opening a ticket. https://woocommerce.com/contact-us/ +**For help with custom code** +WooCommerce Slack Community: https://woocommerce.com/community-slack/ in the `#developers` channel. + **General usage and development questions** - WooCommerce Slack Community: https://woocommerce.com/community-slack/ - WordPress.org Forums: https://wordpress.org/support/plugin/woocommerce -- The WooCommerce Help and Share Facebook group +- The Official WooCommerce Facebook Group https://www.facebook.com/groups/advanced.woocommerce/ diff --git a/.github/ISSUE_TEMPLATE/4-Bug-report.md b/.github/ISSUE_TEMPLATE/4-Bug-report.md index 261ca9edb8b..c0316763647 100644 --- a/.github/ISSUE_TEMPLATE/4-Bug-report.md +++ b/.github/ISSUE_TEMPLATE/4-Bug-report.md @@ -8,11 +8,30 @@ assignees: '' --- -**Describe the bug** -A clear and concise description of what the bug is. Please be as descriptive as possible; issues lacking detail, or for any other reason than to report a bug, may be closed without action. +Please provide us with the information requested in this bug report. Without these details, we won't be able to fully evaluate this issue. +Bug reports lacking detail, or for any other reason than to report a bug, may be closed without action. -**To Reproduce** -Steps to reproduce the behavior: + + + + + + +**Prerequisites (mark completed items with an [x]):** +- [ ] I have have carried out troubleshooting steps and I believe I have found a bug. +- [ ] I have searched for similar bugs in both open and closed issues and cannot find a duplicate. + +**Describe the bug** +A clear and concise description of what the bug is. + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Actual behavior** +A clear and concise description of what actually happens. Please be as descriptive as possible; + +**Steps to reproduce the bug (We need to be able to reproduce the bug in order to fix it.)** +Steps to reproduce the bug: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' @@ -21,8 +40,7 @@ Steps to reproduce the behavior: **Screenshots** If applicable, add screenshots to help explain your problem. -**Expected behavior** -A clear and concise description of what you expected to happen. + **Isolating the problem (mark completed items with an [x]):** - [ ] I have deactivated other plugins and confirmed this bug occurs when only WooCommerce plugin is active. @@ -30,8 +48,11 @@ A clear and concise description of what you expected to happen. - [ ] I can reproduce this bug consistently using the steps above. **WordPress Environment** +We use the [WooCommerce System Status Report](https://docs.woocommerce.com/document/understanding-the-woocommerce-system-status-report/) to help us evaluate the issue. +Without this report we won't be able to fully evaluate this issue.
``` -Copy and paste the system status report from **WooCommerce > System Status** in WordPress admin. +The System Status Report is found in your WordPress admin under **WooCommerce > Status**. +Please select “Get system report”, then “Copy for support”, and then paste it here. ```
diff --git a/.github/ISSUE_TEMPLATE/5-Enhancement.md b/.github/ISSUE_TEMPLATE/5-Enhancement.md index 9f625ac6afc..b616509eedd 100644 --- a/.github/ISSUE_TEMPLATE/5-Enhancement.md +++ b/.github/ISSUE_TEMPLATE/5-Enhancement.md @@ -8,6 +8,10 @@ assignees: '' --- + + + + **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] diff --git a/.github/ISSUE_TEMPLATE/6-Feature-request.md b/.github/ISSUE_TEMPLATE/6-Feature-request.md index 4b05fbc4035..e20ce518c65 100644 --- a/.github/ISSUE_TEMPLATE/6-Feature-request.md +++ b/.github/ISSUE_TEMPLATE/6-Feature-request.md @@ -8,6 +8,10 @@ assignees: '' --- + + + + **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml new file mode 100644 index 00000000000..3cfefb166e2 --- /dev/null +++ b/.github/workflows/build-release.yml @@ -0,0 +1,25 @@ +name: Build release asset +on: + release: + types: [published] +jobs: + build: + name: Build release asset + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Build + id: build + uses: woocommerce/action-build@master + with: + generate-zip: true + - name: Upload release asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ${{ steps.build.outputs.zip_path }} + asset_name: woocommerce.zip + asset_content_type: application/zip diff --git a/.gitignore b/.gitignore index 9b99f73835d..4906d0e7c9e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,9 +10,10 @@ project.properties *.sublime-project *.sublime-workspace .sublimelinterrc +*.swp # Grunt -/node_modules/ +node_modules/ none # Sass @@ -42,8 +43,12 @@ tests/cli/vendor # Unit tests /tmp /tests/bin/tmp -/tests/e2e-tests/config/local-*.json -/tests/e2e-tests/config/local.json +/tests/e2e/config/local-*.json +/tests/e2e/config/local.json +/tests/e2e/docker +/tests/e2e/env/docker/wp-cli/initialize.sh +/tests/e2e/env/build/ +/tests/e2e/env/build-module/ # Logs /logs @@ -51,6 +56,7 @@ tests/cli/vendor # Composer /vendor/ contributors.md +contributors.html # Packages /packages/* @@ -61,3 +67,6 @@ contributors.md # Language files i18n/languages/woocommerce.pot + +# Build +build/ diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 07172a9bfb1..00000000000 --- a/.jshintrc +++ /dev/null @@ -1,26 +0,0 @@ -{ - "boss": true, - "curly": true, - "eqeqeq": true, - "eqnull": true, - "es3": true, - "expr": true, - "immed": true, - "noarg": true, - "onevar": true, - "quotmark": "single", - "trailing": true, - "undef": true, - "unused": true, - "multistr": true, - - "browser": true, - - "globals": { - "_": false, - "Backbone": false, - "jQuery": false, - "JSON": false, - "wp": false - } -} diff --git a/.travis.yml b/.travis.yml index 4efa981ff5d..c8bca1a3bb9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,18 @@ +version: ~> 1.0 + language: php dist: xenial +cache: + directories: + - vendor + - $HOME/.composer/cache + # Since Xenial services are not started by default, we need to instruct it below to start. services: - xvfb - mysql - docker - - docker-compose - -sudo: false - -cache: - directories: - - vendor - - $HOME/.composer/cache # Test main supported versions of PHP against latest WP. php: @@ -28,39 +27,39 @@ env: # Additional tests against stable PHP (min version is 7.0) # and code coverage report. -matrix: +jobs: fast_finish: true include: - - name: "Coding standard check" - php: 7.4 - env: WP_VERSION=latest WP_MULTISITE=0 RUN_PHPCS=1 - - name: "E2E tests" + - name: "Core E2E Tests" php: 7.4 + env: WP_VERSION=latest WP_MULTISITE=0 RUN_E2E=1 script: - composer require wp-cli/i18n-command - npm run build - - docker-compose up --build -d - - bash tests/bin/run-e2e-CI.sh + - npm run build:packages + - npm install jest --global + - npm run docker:up + - npm run test:e2e after_script: - - docker-compose down -v - - name: "Unit tests code coverage" - php: 7.4 - env: WP_VERSION=latest WP_MULTISITE=0 RUN_CODE_COVERAGE=1 - - name: "WooCommerce unit tests using WordPress nightly" + - npm run docker:down + - name: "WP Nightly" php: 7.4 env: WP_VERSION=nightly WP_MULTISITE=0 - - name: "WP latest - 1" + - name: "WP Latest" + php: 7.2 + env: WP_VERSION=5.4 WP_MULTISITE=0 + - name: "WP Latest - 1" php: 7.2 env: WP_VERSION=5.3 WP_MULTISITE=0 - - name: "WP latest - 2" + - name: "WP Latest - 2" php: 7.2 env: WP_VERSION=5.2 WP_MULTISITE=0 - - name: "WP 5.1" - php: 7.2 - env: WP_VERSION=5.1 WP_MULTISITE=0 - - name: "WP 5.0" - php: 7.0 - env: WP_VERSION=5.0 WP_MULTISITE=0 + - name: "Code Standards" + php: 7.4 + env: WP_VERSION=latest WP_MULTISITE=0 RUN_PHPCS=1 + - name: "Code Coverage" + php: 7.4 + env: WP_VERSION=latest WP_MULTISITE=0 RUN_CODE_COVERAGE=1 allow_failures: - php: 7.4 env: WP_VERSION=latest WP_MULTISITE=0 RUN_CODE_COVERAGE=1 diff --git a/CHANGELOG.txt b/CHANGELOG.txt index a6b1ec8d479..0df226a570a 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,5 +1,128 @@ == Changelog == += 4.2.0 - 2020-06-02 = + +**WooCommerce** +* Enhancement - Added Ghanaian regions to the state dropdown. #26273 +* Enhancement - Added Mozambique provinces to the state dropdown. #26162 +* Enhancement - Added support for the new group descriptions available on WordPress privacy exporters as of WP 5.3. #25575 +* Fix - Fixed false positives when checking if uploads directory is public. #26600 +* Fix - Introduced a new admin body class for supporting styling issues in WP 5.3+. #26251 +* Fix - Removed case conversion of meta keys from CSV imports. #25517 +* Fix - Allow schedule coupons via CRUD. #26387 +* Fix - Password visibility toggle when password strength check fails. #26132 +* Fix - Cross-sell placement when product has no description. #26334 +* Fix - Display of the rate limit warning during payment method creation. #26411 +* Fix - Made the shipping zone matching query's `zone_id` field more specific. #26308 +* Fix - Corrected the display of RTL languages on the WooCommerce.com addons page. #26080 +* Fix - Removed the postcode field for Ghana. #26272 +* Fix - Made the hiding of state fields more explicit for Germany, Denmark, and Sweden. #25598 +* Fix - Ensured that global attribute prefixes are passed to the `woocommerce_attribute_label` filter. #26022 +* Dev - Increased WordPress minimum version to 5.2 according to policy. #26550 +* Dev - Added the customer as a third argument to the `woocommerce_matched_rates` filter. #26361 +* Dev - Introduced `woocommerce_menu_order_count` filter. #26044 +* Dev - Introduced `should_send_ajax_request.adding_to_cart `cart event to allow short-circuiting cart addition. #25760 +* Dev - Made the jQuery selector for checkout form rows less specific. #25654 +* Dev - Changed the `{site_address}` placeholder to `{site_url}` for clarity. #25630 +* Dev - Deprecated `.wp-policy-help` and replaced with with the `.privacy-policy-tutorial` and `.wp-suggested-text` classes added in WP 5.1. #26072 +* Dev - Updated `automattic/jetpack-autoloader` to 1.7.0. #26559 +* Dev - Add a way to fetch basic object data. #26025 + +**REST API 1.0.8** +* Enhancement - Add support for trash status for products in V2 and V3 API. #184 +* Dev - Updated minimum PHP requirement to 7.0 to keep up with WooCommerce Core. +* Dev - Fixed failing unit tests. #105 + +**WooCommerce Admin 1.2.3** +* Enhancement - Add onboarding payments note #4157 +* Enhancement - Marketing Inbox Note #4030 +* Performance - Use Route based code splitting to reduce bundle size #4094 +* Performance - trim down inbox note API request. #3977 +* Fix - Proper display of elements in wc-admin pages when in a RTL environment. #4051 +* Fix - Update UX when knowledge base articles fail to retrieve #4133 +* Fix - Updated messaging after last step in OBW. #4148 +* Fix - Reset profiler when visiting old OBW URL #4166. +* Fix - Dashboard flash before OBW chunk loads #4259 +* Tweak - Enable the default homepage template to be filtered #4072 +* Tweak - Create admin note if Jetpack or WooCommerce Services plugin doesn't get installed due to an error during OBW #3888 +* Tweak - Update Email Marketing note. #4167 +* Tweak - Adjust "demo products" verbiage to "Sample Products" #4184 +* Tweak - Don't reschedule imports on failed imports #4263 +* Tweak - Remove obsolete inbox messages #4182 +* Tweak - Updates to WooCommerce Payments in Setup Checklist #4293 +* Dev - Make query selector for admin alerts more specific #4289 +* Dev - Guard against null themes in OBW #4244 +* Dev - Update wcadmin db version after db callback #4323 +* Dev - Only migrate options on version change #4324 +* Dev - Use `PAGE_ROOT` constant to reduce redundant strings #4238 +* Dev - Decouple Plugins DataStore from onboarding feature #4048 +* Dev - Move API out of Onboarding #4093 +* Dev - Add Profiler Step View Tracks #4141 +* Dev - Add React Testing Library #4221 +* Dev - Add List and Link components to Storybook #4219 +* Dev - Cast Shipping Total to float #4042 +* Dev - Dynamic Currency with Context API #4027 +* Dev - Remove Duplicate array entry #4049 + += 4.1.1 - 2020-05-19 = + +* Enhancement - Added notice about public uploads directory. #26207 +* Tweak - Disallow directory listing in woocommerce_uploads when "Redirect only" it's the selected download method. #26399 +* Fix - Added correct handling of nonces to database update notice dismissal. #26500 +* Dev - Updated WooCommerce admin version to 1.1.3 and Action Scheduler to 3.1.6. +* Dev - Add prop `isEnabled` and a function to dynamically enable tracks. #26493 + +**WooCommerce Admin** +* Tweak - Onboarding: Add Jetpack flow back to onboarding profiler. #4382 +* Fix - Respect tracking opt-in before new page load. #4368 + +**ActionScheduler** +* Fix - Shutdown deprecated notice changed to a warning when as_* functions called without data store initialization. #546 + += 4.1.0 - 2020-05-05 = + +**WooCommerce** +* Enhancement - Update dependency woocommerce/woocommerce-admin to v1.1.0 #26057 +* Enhancement - Updated jetpack-autoloader to 1.6 and woocommerce-blocks to 2.5.16. #26099 +* Enhancement - Added option to ignore discounts from cart's total amount to enable free shipping. #24776 +* Enhancement - Changed show password icon color to a darker grey hue. #25625 +* Enhancement - Use new Setup Wizard for all users. #26016 +* Security - Fixed unescaped meta data while duplicating products. Reported by Slavco. +* Tweak - Show notice for WP min version to WP 5.2. #26094 +* Tweak - Improve the string for untested WooCommerce extensions in the system status page to avoid confusion. #25904 +* Tweak - Updated KZT (₸) symbol. #25609 +* Tweak - Trim whitespaces and strip slashes from MaxMind License Key. #25466 +* Tweak - Updated "Help" tabs documentation. #25826 +* Tweak - Update serbian currency symbol to рсд from дин. #25885 +* Fix - Password visibility toggle to hide password again from text. #25627 +* Fix - Undefined property error when attempting to modify the coupon post meta. #25755 +* Fix - Remove some of the individual rounding logic to make sure we round at certain places only. #25800 +* Fix - Order totals calculation if the order contains taxable and non-taxable products and percentage coupons. #25092 +* Fix - Wording for cancelled order email. #25316 +* Fix - Removed guided tour videos link on setup wizard (since current link only redirects to the docs). #25823 +* Fix - Add RTL style to the onboarding wizard. #25835 +* Fix - Trigger change and set val to qty on the frontend so that it properly updates event handlers. #25903 +* Fix - Corrected the way percent coupons apply remainders across the order. #25943 +* Fix - Clarified the error messaging for WooCommerce.com package update failures. #26034 +* Fix - Enforce per user usage limit check for a coupon on guest users based on email. #26066 +* Fix - Remove elements with style=display:none explicitly to address a regression causing broken email html. #26075 +* Dev - Added woocommerce_can_restock_refunded_items filter. #25728 +* Dev - Added woocommerce_order_get_tax_location filter. #25727 +* Dev - Updated stock handling to prevent race conditions when orders come in at the same time. #25708 +* Dev - Updated /myaccount/form-login.php to use consistent kebab-case class names for woocommerce-form-row. #25668 +* Dev - Add filter woocommerce_product_upsells_products_heading to allow heading modification without having to override the template file. #25628 +* Dev - Added woocommerce_order_get_tax_location filter. #25727 +* Dev - Added the get_woocommerce_currency_symbols function to allow develops to get an array of all the currency symbol registered with WooCommerce. #25733 +* Dev - Changed string typed label_class to array in checkout fields. +* Dev - Added "woocommerce_emogrifier" action before the content of the emails is "emogrified". #25801 +* Dev - Add Ability to Filter Event Props. #25851 +* Dev - Updated the unit test install script to support paths to MySQL sockets that contain spaces. #25923 +* Dev - Made the default test source folders support the system tmp folder. #25923 +* Dev - Add cart & checkout block/shortcode info to tracker data. #25932 +* Dev - Make WC_Product_Data_Store_CPT::update_product_stock operations atomic. #26039 +* Dev - Adds usage data for the of cart & checkout blocks (currently in development in WooCommmerce Blocks plugin) to the WC Tracker snapshot. #26084 +* Dev - Implement some additional tracks for coupons, orders, and products. #26085 + = 4.0.1 - 2020-03-18 = **WooCommerce** diff --git a/Dockerfile b/Dockerfile index ef53cc1b22a..538e25c9a70 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1 +1 @@ -FROM wordpress:5.4.0 +FROM wordpress:5.4.2 diff --git a/Gruntfile.js b/Gruntfile.js index bb38d5151fc..d831b5da2b2 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,4 +1,3 @@ -/* jshint node:true */ module.exports = function( grunt ) { 'use strict'; var sass = require( 'node-sass' ); @@ -14,12 +13,9 @@ module.exports = function( grunt ) { php: 'includes' }, - // JavaScript linting with JSHint. - jshint: { - options: { - jshintrc: '.jshintrc' - }, - all: [ + // JavaScript linting with ESLint. + eslint: { + src: [ '<%= dirs.js %>/admin/*.js', '!<%= dirs.js %>/admin/*.min.js', '<%= dirs.js %>/frontend/*.js', @@ -192,62 +188,13 @@ module.exports = function( grunt ) { }, js: { files: [ + 'GruntFile.js', '<%= dirs.js %>/admin/*js', '<%= dirs.js %>/frontend/*js', '!<%= dirs.js %>/admin/*.min.js', '!<%= dirs.js %>/frontend/*.min.js' ], - tasks: ['jshint', 'uglify'] - } - }, - - // Exec shell commands. - shell: { - options: { - stdout: true, - stderr: true - }, - e2e_test: { - command: 'npm run --silent test:single tests/e2e-tests/' + grunt.option( 'file' ) - }, - e2e_tests: { - command: 'npm run --silent test' - }, - e2e_tests_grep: { - command: 'npm run --silent test:grep "' + grunt.option( 'grep' ) + '"' - }, - contributors: { - command: [ - 'echo "Generating contributor list since <%= fromDate %>"', - './node_modules/.bin/githubcontrib --owner woocommerce --repo woocommerce --fromDate <%= fromDate %>' + - ' --authToken <%= authToken %> --cols 6 --sortBy contributions --format md --sortOrder desc' + - ' --showlogin true --sha <%= sha %> --filter renovate-bot > contributors.md' - ].join( '&&' ) - } - }, - - prompt: { - contributors: { - options: { - questions: [ - { - config: 'fromDate', - type: 'input', - message: 'What date (YYYY-MM-DD) should we get contributions since?' - }, - { - config: 'sha', - type: 'input', - message: 'What branch should we get contributors from?' - }, - { - config: 'authToken', - type: 'input', - message: '(optional) Provide a personal access token.' + - ' This will allow 5000 requests per hour rather than 60 - use if nothing is generated.' - } - ] - } + tasks: ['eslint','uglify'] } }, @@ -286,19 +233,17 @@ module.exports = function( grunt ) { // Load NPM tasks to be used here. grunt.loadNpmTasks( 'grunt-sass' ); - grunt.loadNpmTasks( 'grunt-shell' ); grunt.loadNpmTasks( 'grunt-phpcs' ); grunt.loadNpmTasks( 'grunt-rtlcss' ); grunt.loadNpmTasks( 'grunt-postcss' ); grunt.loadNpmTasks( 'grunt-stylelint' ); - grunt.loadNpmTasks( 'grunt-contrib-jshint' ); + grunt.loadNpmTasks( 'gruntify-eslint' ); grunt.loadNpmTasks( 'grunt-contrib-uglify' ); grunt.loadNpmTasks( 'grunt-contrib-cssmin' ); grunt.loadNpmTasks( 'grunt-contrib-concat' ); grunt.loadNpmTasks( 'grunt-contrib-copy' ); grunt.loadNpmTasks( 'grunt-contrib-watch' ); grunt.loadNpmTasks( 'grunt-contrib-clean' ); - grunt.loadNpmTasks( 'grunt-prompt' ); // Register tasks. grunt.registerTask( 'default', [ @@ -307,7 +252,7 @@ module.exports = function( grunt ) { ]); grunt.registerTask( 'js', [ - 'jshint', + 'eslint', 'uglify:admin', 'uglify:frontend' ]); @@ -332,25 +277,8 @@ module.exports = function( grunt ) { 'css' ]); - grunt.registerTask( 'contributors', [ - 'prompt:contributors', - 'shell:contributors' - ]); - // Only an alias to 'default' task. grunt.registerTask( 'dev', [ 'default' ]); - - grunt.registerTask( 'e2e-tests', [ - 'shell:e2e_tests' - ]); - - grunt.registerTask( 'e2e-tests-grep', [ - 'shell:e2e_tests_grep' - ]); - - grunt.registerTask( 'e2e-test', [ - 'shell:e2e_test' - ]); }; diff --git a/README.md b/README.md index ae91337621f..91334b368fa 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Welcome to the WooCommerce repository on GitHub. Here you can browse the source, If you are not a developer, please use the [WooCommerce plugin page](https://wordpress.org/plugins/woocommerce/) on WordPress.org. ## Documentation -* [WooCommerce Documentation](https://docs.woocommerce.com/documentation/plugins/woocommerce/) +* [WooCommerce Documentation](https://docs.woocommerce.com/) * [WooCommerce Developer Documentation](https://github.com/woocommerce/woocommerce/wiki) * [WooCommerce Code Reference](https://docs.woocommerce.com/wc-apidocs/) * [WooCommerce REST API Docs](https://woocommerce.github.io/woocommerce-rest-api-docs/) diff --git a/assets/css/activation.scss b/assets/css/activation.scss index 1823bd69dce..30ad30bc07a 100644 --- a/assets/css/activation.scss +++ b/assets/css/activation.scss @@ -9,7 +9,10 @@ div.woocommerce-message { overflow: hidden; position: relative; - border-left-color: #cc99c2 !important; + + &.updated { + border-left-color: #cc99c2 !important; + } } p.woocommerce-actions, diff --git a/assets/css/admin.scss b/assets/css/admin.scss index 67ae21ee00f..4276487feb3 100644 --- a/assets/css/admin.scss +++ b/assets/css/admin.scss @@ -541,9 +541,12 @@ .woocommerce-message { position: relative; - border-left-color: #cc99c2 !important; overflow: hidden; + &.updated { + border-left-color: #cc99c2 !important; + } + a.skip, a.docs { text-decoration: none !important; @@ -637,7 +640,7 @@ mark.amount { } } -.branch-5-3 { +.wc-wp-version-gte-53 { .woocommerce-help-tip { font-size: 1.2em; @@ -2167,7 +2170,7 @@ ul.wc_coupon_list_block { } } -.branch-5-3 { +.wc-wp-version-gte-53 { .widefat { @@ -4123,7 +4126,7 @@ img.help_tip { } } -.branch-5-3 { +.wc-wp-version-gte-53 { .woocommerce { @@ -6694,7 +6697,7 @@ table.bar_chart { min-width: 400px !important; } -.branch-5-3 { +.wc-wp-version-gte-53 { .select2-results { @@ -6831,7 +6834,7 @@ table.bar_chart { @each $name, $color in $wp_admin_colors { - &-#{$name}.branch-5-3 { + &-#{$name}.wc-wp-version-gte-53 { .select2-dropdown { border-color: $color; diff --git a/assets/css/privacy.scss b/assets/css/privacy.scss new file mode 100644 index 00000000000..4636aca879b --- /dev/null +++ b/assets/css/privacy.scss @@ -0,0 +1,56 @@ +/** + * privacy.scss + * Styles applied to the Privacy Policy Guide to support WooCommerce content. + * Adds support for styling ul/ol elements. + */ + +/** + * Styling begins + */ + +// Support for indented bullet-lists. +.policy-text ul { + list-style: disc; +} + +.policy-text ol { + list-style: decimal; +} + +.policy-text ul li, +.policy-text ol li { + margin-left: 2em; +} + +// Pre-5.4 support for italics. +.branch-5-2 .policy-text ul, +.branch-5-2 .policy-text ol, +.branch-5-3 .policy-text ul, +.branch-5-3 .policy-text ol { + font-style: italic; +} + +// 5.4 support for white background and padding. +.branch-5-4 .policy-text ul:not(.privacy-policy-tutorial):not(.wp-policy-help), +.branch-5-4 .policy-text ol:not(.privacy-policy-tutorial):not(.wp-policy-help) { + background-color: #fff; + margin: 0; + padding: 1em; +} + +.branch-5-4 .hide-privacy-policy-tutorial ul:not(.privacy-policy-tutorial):not(.wp-policy-help), +.branch-5-4 .hide-privacy-policy-tutorial ol:not(.privacy-policy-tutorial):not(.wp-policy-help) { + margin: 1em 0; + padding: 0; +} + +.policy-text p:not(.privacy-policy-tutorial):not(.wp-policy-help) + ul:not(.privacy-policy-tutorial):not(.wp-policy-help), +.policy-text p:not(.privacy-policy-tutorial):not(.wp-policy-help) + ol:not(.privacy-policy-tutorial):not(.wp-policy-help), +.policy-text ul:not(.privacy-policy-tutorial):not(.wp-policy-help) + p:not(.privacy-policy-tutorial):not(.wp-policy-help), +.policy-text ul:not(.privacy-policy-tutorial):not(.wp-policy-help) + ul:not(.privacy-policy-tutorial):not(.wp-policy-help), +.policy-text ul:not(.privacy-policy-tutorial):not(.wp-policy-help) + ol:not(.privacy-policy-tutorial):not(.wp-policy-help), +.policy-text ol:not(.privacy-policy-tutorial):not(.wp-policy-help) + p:not(.privacy-policy-tutorial):not(.wp-policy-help), +.policy-text ol:not(.privacy-policy-tutorial):not(.wp-policy-help) + ul:not(.privacy-policy-tutorial):not(.wp-policy-help), +.policy-text ol:not(.privacy-policy-tutorial):not(.wp-policy-help) + ol:not(.privacy-policy-tutorial):not(.wp-policy-help) { + padding-top: 0; +} diff --git a/assets/css/twenty-twenty.scss b/assets/css/twenty-twenty.scss index b7dce2f6d79..eab9fb5f2d2 100644 --- a/assets/css/twenty-twenty.scss +++ b/assets/css/twenty-twenty.scss @@ -170,6 +170,7 @@ a.button { } .wc-block-grid__products { + .wc-block-grid__product-onsale { position: absolute; top: 0; @@ -296,6 +297,7 @@ a.button { } #site-content { + .post-inner { padding-top: 0; } @@ -319,7 +321,7 @@ a.button { /* Make thumbnails in the gallery affect parent's height and wrapping */ .flex-control-nav::after { clear: both; - content: ''; + content: ""; display: table; } @@ -501,7 +503,7 @@ dl.variation, .product_meta { clear: both; - font-size: .7em; + font-size: 0.7em; padding-top: 0.5em; margin-top: 3rem; } @@ -726,7 +728,7 @@ a.reset_variations { margin: 4rem 0 2rem; /* reset description tab width to full width */ - #tab-description{ + #tab-description { h2, p { @@ -836,7 +838,7 @@ a.reset_variations { } } - .comment-form-rating{ + .comment-form-rating { label { max-width: 58rem; @@ -910,7 +912,7 @@ a.reset_variations { } .comment-form-author, - .comment-form-email{ + .comment-form-email { float: none; margin-left: auto; } @@ -924,6 +926,8 @@ a.reset_variations { .related.products, .up-sells { + clear: both; + ul.products { display: flex; justify-content: space-evenly; @@ -1185,6 +1189,7 @@ a.reset_variations { } form { + h3 { margin-top: 0; } @@ -1215,7 +1220,7 @@ a.reset_variations { } } - table.account-orders-table:not( .has-background ) { + table.account-orders-table:not(.has-background) { tbody { @@ -1343,6 +1348,7 @@ a.reset_variations { } tbody { + tr { border-top: 1px solid #eee; } @@ -1399,7 +1405,7 @@ a.reset_variations { width: 100%; } - input[type='radio'].shipping_method { + input[type="radio"].shipping_method { display: none; & + label { @@ -1713,9 +1719,9 @@ a.reset_variations { } tbody::after { - content: ''; - display: block; - height: 2rem; + content: ""; + display: block; + height: 2rem; } .woocommerce-Price-amount { @@ -1723,7 +1729,7 @@ a.reset_variations { } .cart-subtotal, - .order-total{ + .order-total { border-top: 1px solid #ddd; } } @@ -1774,6 +1780,7 @@ a.reset_variations { } .woocommerce-form-login { + p.form-row.form-row-first, p.form-row.form-row-last { float: none; @@ -1836,7 +1843,7 @@ a.reset_variations { .woocommerce-checkout-review-order-table { - input[type='radio'].shipping_method { + input[type="radio"].shipping_method { display: none; & + label { @@ -2134,13 +2141,15 @@ ul.wc-block-grid__products { .wc-block-grid__product-rating { .star-rating { - font-size: 0.7em + font-size: 0.7em; } } } @media only screen and (max-width: 600px) { + .woocommerce { + .woocommerce-ordering { float: left; clear: both; @@ -2265,7 +2274,7 @@ ul.wc-block-grid__products { } &::before { - content: ''; + content: ""; } } } @@ -2385,8 +2394,8 @@ ul.wc-block-grid__products { table.account-orders-table { .button { - padding-left: .5em; - padding-right: .5em; + padding-left: 0.5em; + padding-right: 0.5em; width: 100%; margin: 2rem 0; } @@ -2427,6 +2436,7 @@ ul.wc-block-grid__products { } .wc-block-grid__products { + .wc-block-grid__product-onsale { font-size: 1.5rem; padding: 1rem; @@ -2587,6 +2597,7 @@ ul.wc-block-grid__products { } .wc-block-grid__products { + .wc-block-grid__product-onsale { font-size: 1.7rem; padding: 1.5rem; diff --git a/assets/css/wc-setup.scss b/assets/css/wc-setup.scss index d6d26e38f32..ccb0f2691d1 100644 --- a/assets/css/wc-setup.scss +++ b/assets/css/wc-setup.scss @@ -1185,7 +1185,7 @@ h3.jetpack-reasons { } .branch-5-2, -.branch-5-3 { +.wc-wp-version-gte-53 { .location-input { margin: 0; @@ -1415,7 +1415,7 @@ p.jetpack-terms { } .branch-5-2, -.branch-5-3 { +.wc-wp-version-gte-53 { .wc-wizard-service-setting-stripe_create_account, .wc-wizard-service-setting-ppec_paypal_reroute_requests { diff --git a/assets/js/admin/api-keys.js b/assets/js/admin/api-keys.js index 760e883be27..4a5c0dd7ceb 100644 --- a/assets/js/admin/api-keys.js +++ b/assets/js/admin/api-keys.js @@ -142,7 +142,9 @@ $( '#key_permissions', self.el ).val( data.permissions ); } } else { - $( 'h2, h3', self.el ).first().append( '

' + response.data.message + '

' ); + $( 'h2, h3', self.el ) + .first() + .append( '

' + response.data.message + '

' ); } self.unblock(); diff --git a/assets/js/admin/backbone-modal.js b/assets/js/admin/backbone-modal.js index 7aa02f8a90f..63cca56422a 100644 --- a/assets/js/admin/backbone-modal.js +++ b/assets/js/admin/backbone-modal.js @@ -130,7 +130,10 @@ var button = e.keyCode || e.which; // Enter key - if ( 13 === button && ! ( e.target.tagName && ( e.target.tagName.toLowerCase() === 'input' || e.target.tagName.toLowerCase() === 'textarea' ) ) ) { + if ( + 13 === button && + ! ( e.target.tagName && ( e.target.tagName.toLowerCase() === 'input' || e.target.tagName.toLowerCase() === 'textarea' ) ) + ) { this.addButton( e ); } diff --git a/assets/js/admin/meta-boxes-order.js b/assets/js/admin/meta-boxes-order.js index 603ba14733f..3175beb5760 100644 --- a/assets/js/admin/meta-boxes-order.js +++ b/assets/js/admin/meta-boxes-order.js @@ -1,3 +1,4 @@ +// eslint-disable-next-line max-len /*global woocommerce_admin_meta_boxes, woocommerce_admin, accounting, woocommerce_admin_meta_boxes_order, wcSetClipboard, wcClearClipboard */ jQuery( function ( $ ) { @@ -11,7 +12,12 @@ jQuery( function ( $ ) { var wc_meta_boxes_order = { states: null, init: function() { - if ( ! ( typeof woocommerce_admin_meta_boxes_order === 'undefined' || typeof woocommerce_admin_meta_boxes_order.countries === 'undefined' ) ) { + if ( + ! ( + typeof woocommerce_admin_meta_boxes_order === 'undefined' || + typeof woocommerce_admin_meta_boxes_order.countries === 'undefined' + ) + ) { /* State/Country select boxes */ this.states = $.parseJSON( woocommerce_admin_meta_boxes_order.countries.replace( /"/g, '"' ) ); } @@ -380,11 +386,19 @@ jQuery( function ( $ ) { $( 'input.line_tax', $row ).each( function() { var $line_total_tax = $( this ); var tax_id = $line_total_tax.data( 'tax_id' ); - var unit_total_tax = accounting.unformat( $line_total_tax.attr( 'data-total_tax' ), woocommerce_admin.mon_decimal_point ) / o_qty; + var unit_total_tax = accounting.unformat( + $line_total_tax.attr( 'data-total_tax' ), + woocommerce_admin.mon_decimal_point + ) / o_qty; var $line_subtotal_tax = $( 'input.line_subtotal_tax[data-tax_id="' + tax_id + '"]', $row ); - var unit_subtotal_tax = accounting.unformat( $line_subtotal_tax.attr( 'data-subtotal_tax' ), woocommerce_admin.mon_decimal_point ) / o_qty; + var unit_subtotal_tax = accounting.unformat( + $line_subtotal_tax.attr( 'data-subtotal_tax' ), + woocommerce_admin.mon_decimal_point + ) / o_qty; var round_at_subtotal = 'yes' === woocommerce_admin_meta_boxes.round_at_subtotal; - var precision = woocommerce_admin_meta_boxes[ round_at_subtotal ? 'rounding_precision' : 'currency_format_num_decimals' ]; + var precision = woocommerce_admin_meta_boxes[ + round_at_subtotal ? 'rounding_precision' : 'currency_format_num_decimals' + ]; if ( 0 < unit_total_tax ) { $line_total_tax.val( @@ -877,7 +891,10 @@ jQuery( function ( $ ) { $( '.refund input.refund_line_total' ).each(function( index, item ) { if ( $( item ).closest( 'tr' ).data( 'order_item_id' ) ) { - line_item_totals[ $( item ).closest( 'tr' ).data( 'order_item_id' ) ] = accounting.unformat( item.value, woocommerce_admin.mon_decimal_point ); + line_item_totals[ $( item ).closest( 'tr' ).data( 'order_item_id' ) ] = accounting.unformat( + item.value, + woocommerce_admin.mon_decimal_point + ); } }); @@ -889,7 +906,10 @@ jQuery( function ( $ ) { line_item_tax_totals[ $( item ).closest( 'tr' ).data( 'order_item_id' ) ] = {}; } - line_item_tax_totals[ $( item ).closest( 'tr' ).data( 'order_item_id' ) ][ tax_id ] = accounting.unformat( item.value, woocommerce_admin.mon_decimal_point ); + line_item_tax_totals[ $( item ).closest( 'tr' ).data( 'order_item_id' ) ][ tax_id ] = accounting.unformat( + item.value, + woocommerce_admin.mon_decimal_point + ); } }); @@ -1018,11 +1038,16 @@ jQuery( function ( $ ) { var $refund_line_total_tax = $( this ); var tax_id = $refund_line_total_tax.data( 'tax_id' ); var line_total_tax = $( 'input.line_tax[data-tax_id="' + tax_id + '"]', $row ); - var unit_total_tax = accounting.unformat( line_total_tax.data( 'total_tax' ), woocommerce_admin.mon_decimal_point ) / qty; + var unit_total_tax = accounting.unformat( + line_total_tax.data( 'total_tax' ), + woocommerce_admin.mon_decimal_point + ) / qty; if ( 0 < unit_total_tax ) { var round_at_subtotal = 'yes' === woocommerce_admin_meta_boxes.round_at_subtotal; - var precision = woocommerce_admin_meta_boxes[ round_at_subtotal ? 'rounding_precision' : 'currency_format_num_decimals' ]; + var precision = woocommerce_admin_meta_boxes[ + round_at_subtotal ? 'rounding_precision' : 'currency_format_num_decimals' + ]; $refund_line_total_tax.val( parseFloat( accounting.formatNumber( unit_total_tax * refund_qty, precision, '' ) ) @@ -1059,8 +1084,17 @@ jQuery( function ( $ ) { var index = $items.find('tr').length + 1; var $row = '' + '' + - '' + - '' + + '' + + '' + '' + '' + ''; diff --git a/assets/js/admin/meta-boxes-product.js b/assets/js/admin/meta-boxes-product.js index f21e2cc9ceb..efbae1dbf4d 100644 --- a/assets/js/admin/meta-boxes-product.js +++ b/assets/js/admin/meta-boxes-product.js @@ -476,7 +476,9 @@ jQuery( function( $ ) { $( '.product_attributes .woocommerce_attribute' ).each( function( index, el ) { if ( $( el ).css( 'display' ) !== 'none' && $( el ).is( '.taxonomy' ) ) { - $( 'select.attribute_taxonomy' ).find( 'option[value="' + $( el ).data( 'taxonomy' ) + '"]' ).prop( 'disabled', true ); + $( 'select.attribute_taxonomy' ) + .find( 'option[value="' + $( el ).data( 'taxonomy' ) + '"]' ) + .prop( 'disabled', true ); } }); diff --git a/assets/js/admin/product-ordering.js b/assets/js/admin/product-ordering.js index 9c2075eb5cd..c030871a48b 100644 --- a/assets/js/admin/product-ordering.js +++ b/assets/js/admin/product-ordering.js @@ -38,17 +38,24 @@ jQuery( function( $ ) { var nextpostid = ui.item.next().find( '.check-column input' ).val(); // Show Spinner - ui.item.find( '.check-column input' ).hide().after( 'processing' ); + ui.item + .find( '.check-column input' ) + .hide() + .after( 'processing' ); // Go do the sorting stuff via ajax - $.post( ajaxurl, { action: 'woocommerce_product_ordering', id: postid, previd: prevpostid, nextid: nextpostid }, function( response ) { - $.each( response, function( key, value ) { - $( '#inline_' + key + ' .menu_order' ).html( value ); - }); - ui.item.find( '.check-column input' ).show().siblings( 'img' ).remove(); - $( 'table.widefat tbody th, table.widefat tbody td' ).css( 'cursor', 'move' ); - $( 'table.widefat tbody' ).sortable( 'enable' ); - }); + $.post( + ajaxurl, + { action: 'woocommerce_product_ordering', id: postid, previd: prevpostid, nextid: nextpostid }, + function( response ) { + $.each( response, function( key, value ) { + $( '#inline_' + key + ' .menu_order' ).html( value ); + }); + ui.item.find( '.check-column input' ).show().siblings( 'img' ).remove(); + $( 'table.widefat tbody th, table.widefat tbody td' ).css( 'cursor', 'move' ); + $( 'table.widefat tbody' ).sortable( 'enable' ); + } + ); // fix cell colors $( 'table.widefat tbody tr' ).each( function() { diff --git a/assets/js/admin/quick-edit.js b/assets/js/admin/quick-edit.js index 74f2f94c866..56bd651779d 100644 --- a/assets/js/admin/quick-edit.js +++ b/assets/js/admin/quick-edit.js @@ -45,6 +45,7 @@ jQuery(function( $ ) { $( 'input[name="_stock"]', '.inline-edit-row' ).val( stock ); $( 'input[name="menu_order"]', '.inline-edit-row' ).val( menu_order ); + // eslint-disable-next-line max-len $( 'select[name="_tax_status"] option, select[name="_tax_class"] option, select[name="_visibility"] option, select[name="_stock_status"] option, select[name="_backorders"] option' ).removeAttr( 'selected' ); $( 'select[name="_tax_status"] option[value="' + tax_status + '"]', '.inline-edit-row' ).attr( 'selected', 'selected' ); diff --git a/assets/js/admin/reports.js b/assets/js/admin/reports.js index 3173462e470..f419f16fc03 100644 --- a/assets/js/admin/reports.js +++ b/assets/js/admin/reports.js @@ -222,7 +222,13 @@ jQuery(function( $ ) { csv_data += '"' + index + '",'; } else { if ( groupby === 'day' ) { - csv_data += '"' + date.getUTCFullYear() + '-' + parseInt( date.getUTCMonth() + 1, 10 ) + '-' + date.getUTCDate() + '",'; + csv_data += '"' + + date.getUTCFullYear() + + '-' + + parseInt( date.getUTCMonth() + 1, 10 ) + + '-' + + date.getUTCDate() + + '",'; } else { csv_data += '"' + date.getUTCFullYear() + '-' + parseInt( date.getUTCMonth() + 1, 10 ) + '",'; } diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 9d6793aa173..061c2bd1af7 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -165,7 +165,8 @@ minLength: 3 }); - // Postcode and city don't have `name` values by default. They're only created if the contents changes, to save on database queries (I think) + // Postcode and city don't have `name` values by default. + // They're only created if the contents changes, to save on database queries (I think) this.$el.find( 'td.postcode input, td.city input' ).change( function() { $( this ).attr( 'name', $( this ).data( 'name' ) ); }); @@ -232,7 +233,9 @@ reordered_rates = _.map( rates_to_reorder, function( rate ) { rate.tax_rate_order++; - changes[ rate.tax_rate_id ] = _.extend( changes[ rate.tax_rate_id ] || {}, { tax_rate_order : rate.tax_rate_order } ); + changes[ rate.tax_rate_id ] = _.extend( + changes[ rate.tax_rate_id ] || {}, { tax_rate_order : rate.tax_rate_order } + ); return rate; } ); } else { diff --git a/assets/js/admin/term-ordering.js b/assets/js/admin/term-ordering.js index 302f6854d6e..1a1a99d8d97 100644 --- a/assets/js/admin/term-ordering.js +++ b/assets/js/admin/term-ordering.js @@ -30,7 +30,13 @@ jQuery( function( $ ) { }; $( document ).ajaxComplete( function( event, request, options ) { - if ( request && 4 === request.readyState && 200 === request.status && options.data && ( 0 <= options.data.indexOf( '_inline_edit' ) || 0 <= options.data.indexOf( 'add-tag' ) ) ) { + if ( + request && + 4 === request.readyState && + 200 === request.status && + options.data && + ( 0 <= options.data.indexOf( '_inline_edit' ) || 0 <= options.data.indexOf( 'add-tag' ) ) + ) { $.wc_add_missing_sort_handles(); $( document.body ).trigger( 'init_tooltips' ); } @@ -80,25 +86,41 @@ jQuery( function( $ ) { } } - // If previous and next not at same tree level, or next not at same tree level and the previous is the parent of the next, or just moved item beneath its own children - if ( ( prevtermid === undefined && nexttermid === undefined ) || ( nexttermid === undefined && nexttermparent === prevtermid ) || ( nexttermid !== undefined && prevtermparent === termid ) ) { + // If previous and next not at same tree level, or next not at same tree level and + // the previous is the parent of the next, or just moved item beneath its own children. + if ( + ( prevtermid === undefined && nexttermid === undefined ) || + ( nexttermid === undefined && nexttermparent === prevtermid ) || + ( nexttermid !== undefined && prevtermparent === termid ) + ) { $( table_selector ).sortable( 'cancel' ); return; } // Show Spinner ui.item.find( '.check-column input' ).hide(); - ui.item.find( '.check-column' ).append( 'processing' ); + ui.item + .find( '.check-column' ) + .append( 'processing' ); - // Go do the sorting stuff via ajax - $.post( ajaxurl, { action: 'woocommerce_term_ordering', id: termid, nextid: nexttermid, thetaxonomy: woocommerce_term_ordering_params.taxonomy }, function(response){ - if ( response === 'children' ) { - window.location.reload(); - } else { - ui.item.find( '.check-column input' ).show(); - ui.item.find( '.check-column' ).find( 'img' ).remove(); + // Go do the sorting stuff via ajax. + $.post( + ajaxurl, + { + action: 'woocommerce_term_ordering', + id: termid, + nextid: nexttermid, + thetaxonomy: woocommerce_term_ordering_params.taxonomy + }, + function(response) { + if ( response === 'children' ) { + window.location.reload(); + } else { + ui.item.find( '.check-column input' ).show(); + ui.item.find( '.check-column' ).find( 'img' ).remove(); + } } - }); + ); // Fix cell colors $( 'table.widefat tbody tr' ).each( function() { diff --git a/assets/js/admin/wc-product-import.js b/assets/js/admin/wc-product-import.js index 0af872bcd8a..7ba790ed5e6 100644 --- a/assets/js/admin/wc-product-import.js +++ b/assets/js/admin/wc-product-import.js @@ -58,7 +58,15 @@ $this.$form.find('.woocommerce-importer-progress').val( response.data.percentage ); if ( 'done' === response.data.position ) { - window.location = response.data.url + '&products-imported=' + parseInt( $this.imported, 10 ) + '&products-failed=' + parseInt( $this.failed, 10 ) + '&products-updated=' + parseInt( $this.updated, 10 ) + '&products-skipped=' + parseInt( $this.skipped, 10 ); + window.location = response.data.url + + '&products-imported=' + + parseInt( $this.imported, 10 ) + + '&products-failed=' + + parseInt( $this.failed, 10 ) + + '&products-updated=' + + parseInt( $this.updated, 10 ) + + '&products-skipped=' + + parseInt( $this.skipped, 10 ); } else { $this.run_import(); } diff --git a/assets/js/admin/wc-shipping-zone-methods.js b/assets/js/admin/wc-shipping-zone-methods.js index 813b7ebda9a..17289866132 100644 --- a/assets/js/admin/wc-shipping-zone-methods.js +++ b/assets/js/admin/wc-shipping-zone-methods.js @@ -34,11 +34,16 @@ this.trigger( 'change:methods' ); }, save: function() { - $.post( ajaxurl + ( ajaxurl.indexOf( '?' ) > 0 ? '&' : '?' ) + 'action=woocommerce_shipping_zone_methods_save_changes', { - wc_shipping_zones_nonce : data.wc_shipping_zones_nonce, - changes : this.changes, - zone_id : data.zone_id - }, this.onSaveResponse, 'json' ); + $.post( + ajaxurl + ( ajaxurl.indexOf( '?' ) > 0 ? '&' : '?' ) + 'action=woocommerce_shipping_zone_methods_save_changes', + { + wc_shipping_zones_nonce : data.wc_shipping_zones_nonce, + changes : this.changes, + zone_id : data.zone_id + }, + this.onSaveResponse, + 'json' + ); }, onSaveResponse: function( response, textStatus ) { if ( 'success' === textStatus ) { @@ -46,7 +51,11 @@ if ( response.data.zone_id !== data.zone_id ) { data.zone_id = response.data.zone_id; if ( window.history.pushState ) { - window.history.pushState({}, '', 'admin.php?page=wc-settings&tab=shipping&zone_id=' + response.data.zone_id ); + window.history.pushState( + {}, + '', + 'admin.php?page=wc-settings&tab=shipping&zone_id=' + response.data.zone_id + ); } } shippingMethod.set( 'methods', response.data.methods ); @@ -72,7 +81,12 @@ $( window ).on( 'beforeunload', { view: this }, this.unloadConfirmation ); $save_button.on( 'click', { view: this }, this.onSubmit ); - $( document.body ).on( 'input change', '#zone_name, #zone_locations, #zone_postcodes', { view: this }, this.onUpdateZone ); + $( document.body ).on( + 'input change', + '#zone_name, #zone_locations, #zone_postcodes', + { view: this }, + this.onUpdateZone + ); $( document.body ).on( 'click', '.wc-shipping-zone-method-settings', { view: this }, this.onConfigureShippingMethod ); $( document.body ).on( 'click', '.wc-shipping-zone-add-method', { view: this }, this.onAddShippingMethod ); $( document.body ).on( 'wc_backbone_modal_response', this.onConfigureShippingMethodSubmitted ); @@ -128,9 +142,13 @@ // Populate $tbody with the current methods $.each( methods, function( id, rowData ) { if ( 'yes' === rowData.enabled ) { - rowData.enabled_icon = '' + data.strings.yes + ''; + rowData.enabled_icon = '' + + data.strings.yes + + ''; } else { - rowData.enabled_icon = '' + data.strings.no + ''; + rowData.enabled_icon = '' + + data.strings.no + + ''; } view.$el.append( view.rowTemplate( rowData ) ); @@ -138,7 +156,9 @@ var $tr = view.$el.find( 'tr[data-id="' + rowData.instance_id + '"]'); if ( ! rowData.has_settings ) { - $tr.find( '.wc-shipping-zone-method-title > a' ).replaceWith('' + $tr.find( '.wc-shipping-zone-method-title > a' ).text() + '' ); + $tr + .find( '.wc-shipping-zone-method-title > a' ) + .replaceWith('' + $tr.find( '.wc-shipping-zone-method-title > a' ).text() + '' ); var $del = $tr.find( '.wc-shipping-zone-method-delete' ); $tr.find( '.wc-shipping-zone-method-title .row-actions' ).empty().html($del); } @@ -241,7 +261,9 @@ if ( old_position !== new_position ) { methods[ method.instance_id ].method_order = new_position; changes.methods = changes.methods || { methods : {} }; - changes.methods[ method.instance_id ] = _.extend( changes.methods[ method.instance_id ] || {}, { method_order : new_position } ); + changes.methods[ method.instance_id ] = _.extend( + changes.methods[ method.instance_id ] || {}, { method_order : new_position } + ); } } ); @@ -281,30 +303,35 @@ shippingMethodView.block(); // Save method settings via ajax call - $.post( ajaxurl + ( ajaxurl.indexOf( '?' ) > 0 ? '&' : '?' ) + 'action=woocommerce_shipping_zone_methods_save_settings', { - wc_shipping_zones_nonce : data.wc_shipping_zones_nonce, - instance_id : posted_data.instance_id, - data : posted_data - }, function( response, textStatus ) { - if ( 'success' === textStatus && response.success ) { - $( 'table.wc-shipping-zone-methods' ).parent().find( '#woocommerce_errors' ).remove(); + $.post( + ajaxurl + ( ajaxurl.indexOf( '?' ) > 0 ? '&' : '?' ) + 'action=woocommerce_shipping_zone_methods_save_settings', + { + wc_shipping_zones_nonce : data.wc_shipping_zones_nonce, + instance_id : posted_data.instance_id, + data : posted_data + }, + function( response, textStatus ) { + if ( 'success' === textStatus && response.success ) { + $( 'table.wc-shipping-zone-methods' ).parent().find( '#woocommerce_errors' ).remove(); - // If there were errors, prepend the form. - if ( response.data.errors.length > 0 ) { - shippingMethodView.showErrors( response.data.errors ); - } + // If there were errors, prepend the form. + if ( response.data.errors.length > 0 ) { + shippingMethodView.showErrors( response.data.errors ); + } - // Method was saved. Re-render. - if ( _.size( shippingMethodView.model.changes ) ) { - shippingMethodView.model.save(); + // Method was saved. Re-render. + if ( _.size( shippingMethodView.model.changes ) ) { + shippingMethodView.model.save(); + } else { + shippingMethodView.model.onSaveResponse( response, textStatus ); + } } else { - shippingMethodView.model.onSaveResponse( response, textStatus ); + window.alert( data.strings.save_failed ); + shippingMethodView.unblock(); } - } else { - window.alert( data.strings.save_failed ); - shippingMethodView.unblock(); - } - }, 'json' ); + }, + 'json' + ); } }, showErrors: function( errors ) { @@ -343,7 +370,11 @@ if ( response.data.zone_id !== data.zone_id ) { data.zone_id = response.data.zone_id; if ( window.history.pushState ) { - window.history.pushState({}, '', 'admin.php?page=wc-settings&tab=shipping&zone_id=' + response.data.zone_id ); + window.history.pushState( + {}, + '', + 'admin.php?page=wc-settings&tab=shipping&zone_id=' + response.data.zone_id + ); } } // Trigger save if there are changes, or just re-render diff --git a/assets/js/admin/wc-shipping-zones.js b/assets/js/admin/wc-shipping-zones.js index 79026f2d964..093170a1ca9 100644 --- a/assets/js/admin/wc-shipping-zones.js +++ b/assets/js/admin/wc-shipping-zones.js @@ -161,7 +161,9 @@ class_name = 'method_enabled'; } - $method_list.append( '
  • ' + shipping_method.title + '
  • ' ); + $method_list.append( + '
  • ' + shipping_method.title + '
  • ' + ); } ); } else { $method_list.append( '
  • ' + data.strings.no_shipping_methods_offered + '
  • ' ); diff --git a/assets/js/admin/woocommerce_admin.js b/assets/js/admin/woocommerce_admin.js index 51351a52839..5070f3f5508 100644 --- a/assets/js/admin/woocommerce_admin.js +++ b/assets/js/admin/woocommerce_admin.js @@ -12,10 +12,22 @@ if ( 0 === $blankslate.length ) { if ( woocommerce_admin.urls.export_products ) { - $title_action.after('' + woocommerce_admin.strings.export_products + ''); + $title_action.after( + '' + + woocommerce_admin.strings.export_products + + '' + ); } if ( woocommerce_admin.urls.import_products ) { - $title_action.after( '' + woocommerce_admin.strings.import_products + '' ); + $title_action.after( + '' + + woocommerce_admin.strings.import_products + + '' + ); } } else { $title_action.hide(); @@ -60,70 +72,85 @@ $( '.wc_error_tip' ).fadeOut( '100', function() { $( this ).remove(); } ); }) - .on( 'change', '.wc_input_price[type=text], .wc_input_decimal[type=text], .wc-order-totals #refund_amount[type=text]', function() { - var regex, decimalRegex, - decimailPoint = woocommerce_admin.decimal_point; + .on( + 'change', + '.wc_input_price[type=text], .wc_input_decimal[type=text], .wc-order-totals #refund_amount[type=text]', + function() { + var regex, decimalRegex, + decimailPoint = woocommerce_admin.decimal_point; - if ( $( this ).is( '.wc_input_price' ) || $( this ).is( '#refund_amount' ) ) { - decimailPoint = woocommerce_admin.mon_decimal_point; + if ( $( this ).is( '.wc_input_price' ) || $( this ).is( '#refund_amount' ) ) { + decimailPoint = woocommerce_admin.mon_decimal_point; + } + + regex = new RegExp( '[^\-0-9\%\\' + decimailPoint + ']+', 'gi' ); + decimalRegex = new RegExp( '\\' + decimailPoint + '+', 'gi' ); + + var value = $( this ).val(); + var newvalue = value.replace( regex, '' ).replace( decimalRegex, decimailPoint ); + + if ( value !== newvalue ) { + $( this ).val( newvalue ); + } } + ) - regex = new RegExp( '[^\-0-9\%\\' + decimailPoint + ']+', 'gi' ); - decimalRegex = new RegExp( '\\' + decimailPoint + '+', 'gi' ); + .on( + 'keyup', + // eslint-disable-next-line max-len + '.wc_input_price[type=text], .wc_input_decimal[type=text], .wc_input_country_iso[type=text], .wc-order-totals #refund_amount[type=text]', + function() { + var regex, error, decimalRegex; + var checkDecimalNumbers = false; - var value = $( this ).val(); - var newvalue = value.replace( regex, '' ).replace( decimalRegex, decimailPoint ); + if ( $( this ).is( '.wc_input_price' ) || $( this ).is( '#refund_amount' ) ) { + checkDecimalNumbers = true; + regex = new RegExp( '[^\-0-9\%\\' + woocommerce_admin.mon_decimal_point + ']+', 'gi' ); + decimalRegex = new RegExp( '[^\\' + woocommerce_admin.mon_decimal_point + ']', 'gi' ); + error = 'i18n_mon_decimal_error'; + } else if ( $( this ).is( '.wc_input_country_iso' ) ) { + regex = new RegExp( '([^A-Z])+|(.){3,}', 'im' ); + error = 'i18n_country_iso_error'; + } else { + checkDecimalNumbers = true; + regex = new RegExp( '[^\-0-9\%\\' + woocommerce_admin.decimal_point + ']+', 'gi' ); + decimalRegex = new RegExp( '[^\\' + woocommerce_admin.decimal_point + ']', 'gi' ); + error = 'i18n_decimal_error'; + } - if ( value !== newvalue ) { - $( this ).val( newvalue ); + var value = $( this ).val(); + var newvalue = value.replace( regex, '' ); + + // Check if newvalue have more than one decimal point. + if ( checkDecimalNumbers && 1 < newvalue.replace( decimalRegex, '' ).length ) { + newvalue = newvalue.replace( decimalRegex, '' ); + } + + if ( value !== newvalue ) { + $( document.body ).triggerHandler( 'wc_add_error_tip', [ $( this ), error ] ); + } else { + $( document.body ).triggerHandler( 'wc_remove_error_tip', [ $( this ), error ] ); + } } - }) - - .on( 'keyup', '.wc_input_price[type=text], .wc_input_decimal[type=text], .wc_input_country_iso[type=text], .wc-order-totals #refund_amount[type=text]', function() { - var regex, error, decimalRegex; - var checkDecimalNumbers = false; - - if ( $( this ).is( '.wc_input_price' ) || $( this ).is( '#refund_amount' ) ) { - checkDecimalNumbers = true; - regex = new RegExp( '[^\-0-9\%\\' + woocommerce_admin.mon_decimal_point + ']+', 'gi' ); - decimalRegex = new RegExp( '[^\\' + woocommerce_admin.mon_decimal_point + ']', 'gi' ); - error = 'i18n_mon_decimal_error'; - } else if ( $( this ).is( '.wc_input_country_iso' ) ) { - regex = new RegExp( '([^A-Z])+|(.){3,}', 'im' ); - error = 'i18n_country_iso_error'; - } else { - checkDecimalNumbers = true; - regex = new RegExp( '[^\-0-9\%\\' + woocommerce_admin.decimal_point + ']+', 'gi' ); - decimalRegex = new RegExp( '[^\\' + woocommerce_admin.decimal_point + ']', 'gi' ); - error = 'i18n_decimal_error'; - } - - var value = $( this ).val(); - var newvalue = value.replace( regex, '' ); - - // Check if newvalue have more than one decimal point. - if ( checkDecimalNumbers && 1 < newvalue.replace( decimalRegex, '' ).length ) { - newvalue = newvalue.replace( decimalRegex, '' ); - } - - if ( value !== newvalue ) { - $( document.body ).triggerHandler( 'wc_add_error_tip', [ $( this ), error ] ); - } else { - $( document.body ).triggerHandler( 'wc_remove_error_tip', [ $( this ), error ] ); - } - }) + ) .on( 'change', '#_sale_price.wc_input_price[type=text], .wc_input_price[name^=variable_sale_price]', function() { var sale_price_field = $( this ), regular_price_field; if ( sale_price_field.attr( 'name' ).indexOf( 'variable' ) !== -1 ) { - regular_price_field = sale_price_field.parents( '.variable_pricing' ).find( '.wc_input_price[name^=variable_regular_price]' ); + regular_price_field = sale_price_field + .parents( '.variable_pricing' ) + .find( '.wc_input_price[name^=variable_regular_price]' ); } else { regular_price_field = $( '#_regular_price' ); } - var sale_price = parseFloat( window.accounting.unformat( sale_price_field.val(), woocommerce_admin.mon_decimal_point ) ); - var regular_price = parseFloat( window.accounting.unformat( regular_price_field.val(), woocommerce_admin.mon_decimal_point ) ); + var sale_price = parseFloat( + window.accounting.unformat( sale_price_field.val(), woocommerce_admin.mon_decimal_point ) + ); + var regular_price = parseFloat( + window.accounting.unformat( regular_price_field.val(), woocommerce_admin.mon_decimal_point ) + ); if ( sale_price >= regular_price ) { $( this ).val( '' ); @@ -134,13 +161,19 @@ var sale_price_field = $( this ), regular_price_field; if ( sale_price_field.attr( 'name' ).indexOf( 'variable' ) !== -1 ) { - regular_price_field = sale_price_field.parents( '.variable_pricing' ).find( '.wc_input_price[name^=variable_regular_price]' ); + regular_price_field = sale_price_field + .parents( '.variable_pricing' ) + .find( '.wc_input_price[name^=variable_regular_price]' ); } else { regular_price_field = $( '#_regular_price' ); } - var sale_price = parseFloat( window.accounting.unformat( sale_price_field.val(), woocommerce_admin.mon_decimal_point ) ); - var regular_price = parseFloat( window.accounting.unformat( regular_price_field.val(), woocommerce_admin.mon_decimal_point ) ); + var sale_price = parseFloat( + window.accounting.unformat( sale_price_field.val(), woocommerce_admin.mon_decimal_point ) + ); + var regular_price = parseFloat( + window.accounting.unformat( regular_price_field.val(), woocommerce_admin.mon_decimal_point ) + ); if ( sale_price >= regular_price ) { $( document.body ).triggerHandler( 'wc_add_error_tip', [ $(this), 'i18n_sale_less_than_regular_error' ] ); @@ -236,9 +269,13 @@ if ( $( 'tr.last_selected', $this_table ).length > 0 ) { if ( $this_row.index() > $( 'tr.last_selected', $this_table ).index() ) { - $( 'tr', $this_table ).slice( $( 'tr.last_selected', $this_table ).index(), $this_row.index() ).addClass( 'current' ); + $( 'tr', $this_table ) + .slice( $( 'tr.last_selected', $this_table ).index(), $this_row.index() ) + .addClass( 'current' ); } else { - $( 'tr', $this_table ).slice( $this_row.index(), $( 'tr.last_selected', $this_table ).index() + 1 ).addClass( 'current' ); + $( 'tr', $this_table ) + .slice( $this_row.index(), $( 'tr.last_selected', $this_table ).index() + 1 ) + .addClass( 'current' ); } } @@ -260,7 +297,8 @@ }); // Additional cost and Attribute term tables - $( '.woocommerce_page_wc-settings .shippingrows tbody tr:even, table.attributes-table tbody tr:nth-child(odd)' ).addClass( 'alternate' ); + $( '.woocommerce_page_wc-settings .shippingrows tbody tr:even, table.attributes-table tbody tr:nth-child(odd)' ) + .addClass( 'alternate' ); // Show order items on orders page $( document.body ).on( 'click', '.show_order_items', function() { @@ -281,9 +319,15 @@ $( '.hide_options_if_checked' ).each( function() { $( this ).find( 'input:eq(0)' ).change( function() { if ( $( this ).is( ':checked' ) ) { - $( this ).closest( 'fieldset, tr' ).nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' ).hide(); + $( this ) + .closest( 'fieldset, tr' ) + .nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' ) + .hide(); } else { - $( this ).closest( 'fieldset, tr' ).nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' ).show(); + $( this ) + .closest( 'fieldset, tr' ) + .nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' ) + .show(); } }).change(); }); @@ -291,9 +335,15 @@ $( '.show_options_if_checked' ).each( function() { $( this ).find( 'input:eq(0)' ).change( function() { if ( $( this ).is( ':checked' ) ) { - $( this ).closest( 'fieldset, tr' ).nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' ).show(); + $( this ) + .closest( 'fieldset, tr' ) + .nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' ) + .show(); } else { - $( this ).closest( 'fieldset, tr' ).nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' ).hide(); + $( this ) + .closest( 'fieldset, tr' ) + .nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' ) + .hide(); } }).change(); }); diff --git a/assets/js/frontend/add-to-cart-variation.js b/assets/js/frontend/add-to-cart-variation.js index ffc851b544f..c7c603725ee 100644 --- a/assets/js/frontend/add-to-cart-variation.js +++ b/assets/js/frontend/add-to-cart-variation.js @@ -43,7 +43,7 @@ // Init after gallery. setTimeout( function() { $form.trigger( 'check_variations' ); - $form.trigger( 'wc_variation_form' ); + $form.trigger( 'wc_variation_form', self ); self.loading = false; }, 100 ); }; @@ -72,8 +72,14 @@ */ VariationForm.prototype.onHide = function( event ) { event.preventDefault(); - event.data.variationForm.$form.find( '.single_add_to_cart_button' ).removeClass( 'wc-variation-is-unavailable' ).addClass( 'disabled wc-variation-selection-needed' ); - event.data.variationForm.$form.find( '.woocommerce-variation-add-to-cart' ).removeClass( 'woocommerce-variation-add-to-cart-enabled' ).addClass( 'woocommerce-variation-add-to-cart-disabled' ); + event.data.variationForm.$form + .find( '.single_add_to_cart_button' ) + .removeClass( 'wc-variation-is-unavailable' ) + .addClass( 'disabled wc-variation-selection-needed' ); + event.data.variationForm.$form + .find( '.woocommerce-variation-add-to-cart' ) + .removeClass( 'woocommerce-variation-add-to-cart-enabled' ) + .addClass( 'woocommerce-variation-add-to-cart-disabled' ); }; /** @@ -82,11 +88,22 @@ VariationForm.prototype.onShow = function( event, variation, purchasable ) { event.preventDefault(); if ( purchasable ) { - event.data.variationForm.$form.find( '.single_add_to_cart_button' ).removeClass( 'disabled wc-variation-selection-needed wc-variation-is-unavailable' ); - event.data.variationForm.$form.find( '.woocommerce-variation-add-to-cart' ).removeClass( 'woocommerce-variation-add-to-cart-disabled' ).addClass( 'woocommerce-variation-add-to-cart-enabled' ); + event.data.variationForm.$form + .find( '.single_add_to_cart_button' ) + .removeClass( 'disabled wc-variation-selection-needed wc-variation-is-unavailable' ); + event.data.variationForm.$form + .find( '.woocommerce-variation-add-to-cart' ) + .removeClass( 'woocommerce-variation-add-to-cart-disabled' ) + .addClass( 'woocommerce-variation-add-to-cart-enabled' ); } else { - event.data.variationForm.$form.find( '.single_add_to_cart_button' ).removeClass( 'wc-variation-selection-needed' ).addClass( 'disabled wc-variation-is-unavailable' ); - event.data.variationForm.$form.find( '.woocommerce-variation-add-to-cart' ).removeClass( 'woocommerce-variation-add-to-cart-enabled' ).addClass( 'woocommerce-variation-add-to-cart-disabled' ); + event.data.variationForm.$form + .find( '.single_add_to_cart_button' ) + .removeClass( 'wc-variation-selection-needed' ) + .addClass( 'disabled wc-variation-is-unavailable' ); + event.data.variationForm.$form + .find( '.woocommerce-variation-add-to-cart' ) + .removeClass( 'woocommerce-variation-add-to-cart-enabled' ) + .addClass( 'woocommerce-variation-add-to-cart-disabled' ); } // If present, the media element library needs initialized on the variation description. @@ -123,8 +140,12 @@ VariationForm.prototype.onResetDisplayedVariation = function( event ) { var form = event.data.variationForm; form.$product.find( '.product_meta' ).find( '.sku' ).wc_reset_content(); - form.$product.find( '.product_weight, .woocommerce-product-attributes-item--weight .woocommerce-product-attributes-item__value' ).wc_reset_content(); - form.$product.find( '.product_dimensions, .woocommerce-product-attributes-item--dimensions .woocommerce-product-attributes-item__value' ).wc_reset_content(); + form.$product + .find( '.product_weight, .woocommerce-product-attributes-item--weight .woocommerce-product-attributes-item__value' ) + .wc_reset_content(); + form.$product + .find( '.product_dimensions, .woocommerce-product-attributes-item--dimensions .woocommerce-product-attributes-item__value' ) + .wc_reset_content(); form.$form.trigger( 'reset_image' ); form.$singleVariation.slideUp( 200 ).trigger( 'hide_variation' ); }; @@ -139,12 +160,12 @@ /** * Looks for matching variations for current selected attributes. */ - VariationForm.prototype.onFindVariation = function( event ) { + VariationForm.prototype.onFindVariation = function( event, chosenAttributes ) { var form = event.data.variationForm, - attributes = form.getChosenAttributes(), + attributes = 'undefined' !== typeof chosenAttributes ? chosenAttributes : form.getChosenAttributes(), currentAttributes = attributes.data; - if ( attributes.count === attributes.chosenCount ) { + if ( attributes.count && attributes.count === attributes.chosenCount ) { if ( form.useAjax ) { if ( form.xhr ) { form.xhr.abort(); @@ -164,7 +185,13 @@ attributes.chosenCount = 0; if ( ! form.loading ) { - form.$form.find( '.single_variation' ).after( '

    ' + wc_add_to_cart_variation_params.i18n_no_matching_variations_text + '

    ' ); + form.$form + .find( '.single_variation' ) + .after( + '

    ' + + wc_add_to_cart_variation_params.i18n_no_matching_variations_text + + '

    ' + ); form.$form.find( '.wc-no-matching-variations' ).slideDown( 200 ); } } @@ -186,7 +213,13 @@ attributes.chosenCount = 0; if ( ! form.loading ) { - form.$form.find( '.single_variation' ).after( '

    ' + wc_add_to_cart_variation_params.i18n_no_matching_variations_text + '

    ' ); + form.$form + .find( '.single_variation' ) + .after( + '

    ' + + wc_add_to_cart_variation_params.i18n_no_matching_variations_text + + '

    ' + ); form.$form.find( '.wc-no-matching-variations' ).slideDown( 200 ); } } @@ -206,8 +239,12 @@ VariationForm.prototype.onFoundVariation = function( event, variation ) { var form = event.data.variationForm, $sku = form.$product.find( '.product_meta' ).find( '.sku' ), - $weight = form.$product.find( '.product_weight, .woocommerce-product-attributes-item--weight .woocommerce-product-attributes-item__value' ), - $dimensions = form.$product.find( '.product_dimensions, .woocommerce-product-attributes-item--dimensions .woocommerce-product-attributes-item__value' ), + $weight = form.$product.find( + '.product_weight, .woocommerce-product-attributes-item--weight .woocommerce-product-attributes-item__value' + ), + $dimensions = form.$product.find( + '.product_dimensions, .woocommerce-product-attributes-item--dimensions .woocommerce-product-attributes-item__value' + ), $qty = form.$singleVariationWrap.find( '.quantity' ), purchasable = true, variation_id = '', @@ -333,7 +370,11 @@ refSelect.find( 'option' ).removeAttr( 'disabled attached' ).removeAttr( 'selected' ); - current_attr_select.data( 'attribute_options', refSelect.find( 'option' + option_gt_filter ).get() ); // Legacy data attribute. + // Legacy data attribute. + current_attr_select.data( + 'attribute_options', + refSelect.find( 'option' + option_gt_filter ).get() + ); current_attr_select.data( 'attribute_html', refSelect.html() ); } @@ -597,7 +638,9 @@ $product_gallery = $product.find( '.images' ), $gallery_nav = $product.find( '.flex-control-nav' ), $gallery_img = $gallery_nav.find( 'li:eq(0) img' ), - $product_img_wrap = $product_gallery.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 ), + $product_img_wrap = $product_gallery + .find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ) + .eq( 0 ), $product_img = $product_img_wrap.find( '.wp-post-image' ), $product_link = $product_img_wrap.find( 'a' ).eq( 0 ); @@ -658,7 +701,9 @@ $product_gallery = $product.find( '.images' ), $gallery_nav = $product.find( '.flex-control-nav' ), $gallery_img = $gallery_nav.find( 'li:eq(0) img' ), - $product_img_wrap = $product_gallery.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 ), + $product_img_wrap = $product_gallery + .find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ) + .eq( 0 ), $product_img = $product_img_wrap.find( '.wp-post-image' ), $product_link = $product_img_wrap.find( 'a' ).eq( 0 ); diff --git a/assets/js/frontend/add-to-cart.js b/assets/js/frontend/add-to-cart.js index 8d6666c96de..6fcee7b5a74 100644 --- a/assets/js/frontend/add-to-cart.js +++ b/assets/js/frontend/add-to-cart.js @@ -17,6 +17,7 @@ jQuery( function( $ ) { .on( 'click', '.add_to_cart_button', { addToCartHandler: this }, this.onAddToCart ) .on( 'click', '.remove_from_cart_button', { addToCartHandler: this }, this.onRemoveFromCart ) .on( 'added_to_cart', this.updateButton ) + .on( 'ajax_request_not_sent.adding_to_cart', this.updateButton ) .on( 'added_to_cart removed_from_cart', { addToCartHandler: this }, this.updateFragments ); }; @@ -69,6 +70,12 @@ jQuery( function( $ ) { $thisbutton.removeClass( 'added' ); $thisbutton.addClass( 'loading' ); + // Allow 3rd parties to validate and quit early. + if ( false === $( document.body ).triggerHandler( 'should_send_ajax_request.adding_to_cart', [ $thisbutton ] ) ) { + $( document.body ).trigger( 'ajax_request_not_sent.adding_to_cart', [ false, false, $thisbutton ] ); + return true; + } + var data = {}; // Fetch changes that are directly added by calling $thisbutton.data( key, value ) @@ -159,10 +166,13 @@ jQuery( function( $ ) { if ( $button ) { $button.removeClass( 'loading' ); - $button.addClass( 'added' ); + + if ( fragments ) { + $button.addClass( 'added' ); + } // View cart text. - if ( ! wc_add_to_cart_params.is_cart && $button.parent().find( '.added_to_cart' ).length === 0 ) { + if ( fragments && ! wc_add_to_cart_params.is_cart && $button.parent().find( '.added_to_cart' ).length === 0 ) { $button.after( ' ' + wc_add_to_cart_params.i18n_view_cart + '' ); } diff --git a/assets/js/frontend/cart.js b/assets/js/frontend/cart.js index 816863ed454..622c8eb1437 100644 --- a/assets/js/frontend/cart.js +++ b/assets/js/frontend/cart.js @@ -105,7 +105,7 @@ jQuery( function( $ ) { } $( '.woocommerce-cart-form' ).replaceWith( $new_form ); - $( '.woocommerce-cart-form' ).find( ':input[name="update_cart"]' ).prop( 'disabled', true ); + $( '.woocommerce-cart-form' ).find( ':input[name="update_cart"]' ).prop( 'disabled', true ).attr( 'aria-disabled', true ); if ( $notices.length > 0 ) { show_notice( $notices ); @@ -134,7 +134,9 @@ jQuery( function( $ ) { */ var show_notice = function( html_element, $target ) { if ( ! $target ) { - $target = $( '.woocommerce-notices-wrapper:first' ) || $( '.cart-empty' ).closest( '.woocommerce' ) || $( '.woocommerce-cart-form' ); + $target = $( '.woocommerce-notices-wrapper:first' ) || + $( '.cart-empty' ).closest( '.woocommerce' ) || + $( '.woocommerce-cart-form' ); } $target.prepend( html_element ); }; @@ -188,6 +190,7 @@ jQuery( function( $ ) { shipping_method_selected: function() { var shipping_methods = {}; + // eslint-disable-next-line max-len $( 'select.shipping_method, :input[name^=shipping_method][type=radio]:checked, :input[name^=shipping_method][type=hidden]' ).each( function() { shipping_methods[ $( this ).data( 'index' ) ] = $( this ).val(); } ); @@ -301,14 +304,14 @@ jQuery( function( $ ) { '.woocommerce-cart-form .cart_item :input', this.input_changed ); - $( '.woocommerce-cart-form :input[name="update_cart"]' ).prop( 'disabled', true ); + $( '.woocommerce-cart-form :input[name="update_cart"]' ).prop( 'disabled', true ).attr( 'aria-disabled', true ); }, /** * After an input is changed, enable the update cart button. */ input_changed: function() { - $( '.woocommerce-cart-form :input[name="update_cart"]' ).prop( 'disabled', false ); + $( '.woocommerce-cart-form :input[name="update_cart"]' ).prop( 'disabled', false ).attr( 'aria-disabled', false ); }, /** diff --git a/assets/js/frontend/country-select.js b/assets/js/frontend/country-select.js index d0cbe57ba92..77b9655d214 100644 --- a/assets/js/frontend/country-select.js +++ b/assets/js/frontend/country-select.js @@ -93,7 +93,7 @@ jQuery( function( $ ) { var country = $( this ).val(), $statebox = $wrapper.find( '#billing_state, #shipping_state, #calc_shipping_state' ), - $parent = $statebox.closest( 'p.form-row' ), + $parent = $statebox.closest( '.form-row' ), input_name = $statebox.attr( 'name' ), input_id = $statebox.attr('id'), input_classes = $statebox.attr('data-input-classes'), diff --git a/assets/js/frontend/single-product.js b/assets/js/frontend/single-product.js index 30b3d6fd991..618791c6a47 100644 --- a/assets/js/frontend/single-product.js +++ b/assets/js/frontend/single-product.js @@ -9,7 +9,7 @@ jQuery( function( $ ) { $( 'body' ) // Tabs .on( 'init', '.wc-tabs-wrapper, .woocommerce-tabs', function() { - $( '.wc-tab, .woocommerce-tabs .panel:not(.panel .panel)' ).hide(); + $( this ).find( '.wc-tab, .woocommerce-tabs .panel:not(.panel .panel)' ).hide(); var hash = window.location.hash; var url = window.location.href; diff --git a/assets/js/frontend/tokenization-form.js b/assets/js/frontend/tokenization-form.js index 15e9054b7c4..3a5a8bffbad 100644 --- a/assets/js/frontend/tokenization-form.js +++ b/assets/js/frontend/tokenization-form.js @@ -22,7 +22,12 @@ jQuery( function( $ ) { this.hideSaveNewCheckbox = this.hideSaveNewCheckbox.bind( this ); // When a radio button is changed, make sure to show/hide our new CC info area. - this.$target.on( 'click change', ':input.woocommerce-SavedPaymentMethods-tokenInput', { tokenizationForm: this }, this.onTokenChange ); + this.$target.on( + 'click change', + ':input.woocommerce-SavedPaymentMethods-tokenInput', + { tokenizationForm: this }, + this.onTokenChange + ); // OR if create account is checked. $( 'input#createaccount' ).change( { tokenizationForm: this }, this.onCreateAccountChange ); diff --git a/assets/js/frontend/woocommerce.js b/assets/js/frontend/woocommerce.js index 6c6047558cd..8c0414fff1b 100644 --- a/assets/js/frontend/woocommerce.js +++ b/assets/js/frontend/woocommerce.js @@ -81,15 +81,17 @@ jQuery( function( $ ) { // Show password visiblity hover icon on woocommerce forms $( '.woocommerce form .woocommerce-Input[type="password"]' ).wrap( '' ); + // Add 'password-input' class to the password wrapper in checkout page. + $( '.woocommerce form input' ).filter(':password').parent('span').addClass('password-input'); $( '.password-input' ).append( '' ); $( '.show-password-input' ).click( function() { $( this ).toggleClass( 'display-password' ); if ( $( this ).hasClass( 'display-password' ) ) { - $( this ).siblings( ['input[name^="password"]', 'input[type="password"]'] ).prop( 'type', 'text' ); + $( this ).siblings( ['input[type="password"]'] ).prop( 'type', 'text' ); } else { - $( this ).siblings( 'input[name^="password"]' ).prop( 'type', 'password' ); + $( this ).siblings( 'input[type="text"]' ).prop( 'type', 'password' ); } } ); diff --git a/assets/js/selectWoo/selectWoo.full.js b/assets/js/selectWoo/selectWoo.full.js index 613204ba441..23548fce727 100644 --- a/assets/js/selectWoo/selectWoo.full.js +++ b/assets/js/selectWoo/selectWoo.full.js @@ -755,6 +755,12 @@ S2.define('select2/utils',[ }); }; + Utils.entityDecode = function(html) { + var txt = document.createElement("textarea"); + txt.innerHTML = html; + return txt.value; + } + // Append an array of jQuery nodes to a given element. Utils.appendMany = function ($element, $nodes) { // jQuery 1.7.x does not support $.fn.append() with an array @@ -1611,9 +1617,9 @@ S2.define('select2/selection/single',[ var selection = data[0]; var $rendered = this.$selection.find('.select2-selection__rendered'); - var formatted = this.display(selection, $rendered); + var formatted = Utils.entityDecode(this.display(selection, $rendered)); - $rendered.empty().append(formatted); + $rendered.empty().text(formatted); $rendered.prop('title', selection.title || selection.text); }; @@ -1742,12 +1748,14 @@ S2.define('select2/selection/multiple',[ var selection = data[d]; var $selection = this.selectionContainer(); + var removeItemTag = $selection.html(); var formatted = this.display(selection, $selection); if ('string' === typeof formatted) { - formatted = formatted.trim(); + formatted = Utils.entityDecode(formatted.trim()); } - $selection.append(formatted); + $selection.text(formatted); + $selection.prepend(removeItemTag); $selection.prop('title', selection.title || selection.text); $selection.data('data', selection); @@ -1786,7 +1794,7 @@ S2.define('select2/selection/placeholder',[ Placeholder.prototype.createPlaceholder = function (decorated, placeholder) { var $placeholder = this.selectionContainer(); - $placeholder.html(this.display(placeholder)); + $placeholder.text(Utils.entityDecode(this.display(placeholder))); $placeholder.addClass('select2-selection__placeholder') .removeClass('select2-selection__choice'); diff --git a/assets/js/selectWoo/selectWoo.full.min.js b/assets/js/selectWoo/selectWoo.full.min.js index 4654399e175..11e22517352 100644 --- a/assets/js/selectWoo/selectWoo.full.min.js +++ b/assets/js/selectWoo/selectWoo.full.min.js @@ -5,7 +5,7 @@ * Released under the MIT license * https://github.com/woocommerce/selectWoo/blob/master/LICENSE.md */ -!function(n){"function"==typeof define&&define.amd?define(["jquery"],n):"object"==typeof module&&module.exports?module.exports=function(e,t){return t===undefined&&(t="undefined"!=typeof window?require("jquery"):require("jquery")(e)),n(t),t}:n(jQuery)}(function(i){var e=function(){if(i&&i.fn&&i.fn.select2&&i.fn.select2.amd)var e=i.fn.select2.amd;var t,o,c,n;return e&&e.requirejs||(e?o=e:e={},function(h){var s,r,f,g,m={},v={},y={},w={},n=Object.prototype.hasOwnProperty,i=[].slice,_=/\.js$/;function $(e,t){return n.call(e,t)}function a(e,t){var n,i,o,s,r,a,l,c,u,d,p,h=t&&t.split("/"),f=y.map,g=f&&f["*"]||{};if(e){for(r=(e=e.split("/")).length-1,y.nodeIdCompat&&_.test(e[r])&&(e[r]=e[r].replace(_,"")),"."===e[0].charAt(0)&&h&&(e=h.slice(0,h.length-1).concat(e)),u=0;u":">",'"':""","'":"'","/":"/"};return"string"!=typeof e?e:String(e).replace(/[&<>"'\/\\]/g,function(e){return t[e]})},e.appendMany=function(e,t){if("1.7"===s.fn.jquery.substr(0,3)){var n=s();s.map(t,function(e){n=n.add(e)}),t=n}e.append(t)},e.isTouchscreen=function(){return"undefined"==typeof e._isTouchscreenCache&&(e._isTouchscreenCache="ontouchstart"in document.documentElement),e._isTouchscreenCache},e}),e.define("select2/results",["jquery","./utils"],function(h,e){function i(e,t,n){this.$element=e,this.data=n,this.options=t,i.__super__.constructor.call(this)}return e.Extend(i,e.Observable),i.prototype.render=function(){var e=h('');return this.options.get("multiple")&&e.attr("aria-multiselectable","true"),this.$results=e},i.prototype.clear=function(){this.$results.empty()},i.prototype.displayMessage=function(e){var t=this.options.get("escapeMarkup");this.clear(),this.hideLoading();var n=h(''),i=this.options.get("translations").get(e.message);n.append(t(i(e.args))),n[0].className+=" select2-results__message",this.$results.append(n)},i.prototype.hideMessages=function(){this.$results.find(".select2-results__message").remove()},i.prototype.append=function(e){this.hideLoading();var t=[];if(null!=e.results&&0!==e.results.length){e.results=this.sort(e.results);for(var n=0;n",{"class":"select2-results__options select2-results__options--nested",role:"listbox"});p.append(l),s.attr("role","list"),s.append(r),s.append(p)}else this.template(e,t);return h.data(t,"data",e),t},i.prototype.bind=function(t,e){var l=this,n=t.id+"-results";this.$results.attr("id",n),t.on("results:all",function(e){l.clear(),l.append(e.data),t.isOpen()&&(l.setClasses(),l.highlightFirstItem())}),t.on("results:append",function(e){l.append(e.data),t.isOpen()&&l.setClasses()}),t.on("query",function(e){l.hideMessages(),l.showLoading(e)}),t.on("select",function(){t.isOpen()&&(l.setClasses(),l.highlightFirstItem())}),t.on("unselect",function(){t.isOpen()&&(l.setClasses(),l.highlightFirstItem())}),t.on("open",function(){l.$results.attr("aria-expanded","true"),l.$results.attr("aria-hidden","false"),l.setClasses(),l.ensureHighlightVisible()}),t.on("close",function(){l.$results.attr("aria-expanded","false"),l.$results.attr("aria-hidden","true"),l.$results.removeAttr("aria-activedescendant")}),t.on("results:toggle",function(){var e=l.getHighlightedResults();0!==e.length&&e.trigger("mouseup")}),t.on("results:select",function(){var e=l.getHighlightedResults();if(0!==e.length){var t=e.data("data");"true"==e.attr("data-selected")?l.trigger("close",{}):l.trigger("select",{data:t})}}),t.on("results:previous",function(){var e=l.getHighlightedResults(),t=l.$results.find("[data-selected]"),n=t.index(e);if(0!==n){var i=n-1;0===e.length&&(i=0);var o=t.eq(i);o.trigger("mouseenter");var s=l.$results.offset().top,r=o.offset().top,a=l.$results.scrollTop()+(r-s);0===i?l.$results.scrollTop(0):r-s<0&&l.$results.scrollTop(a)}}),t.on("results:next",function(){var e=l.getHighlightedResults(),t=l.$results.find("[data-selected]"),n=t.index(e)+1;if(!(n>=t.length)){var i=t.eq(n);i.trigger("mouseenter");var o=l.$results.offset().top+l.$results.outerHeight(!1),s=i.offset().top+i.outerHeight(!1),r=l.$results.scrollTop()+s-o;0===n?l.$results.scrollTop(0):othis.$results.outerHeight()||s<0)&&this.$results.scrollTop(o)}},i.prototype.template=function(e,t){var n=this.options.get("templateResult"),i=this.options.get("escapeMarkup"),o=n(e,t);null==o?t.style.display="none":"string"==typeof o?t.innerHTML=i(o):h(t).append(o)},i}),e.define("select2/keys",[],function(){return{BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46}}),e.define("select2/selection/base",["jquery","../utils","../keys"],function(i,e,o){function n(e,t){this.$element=e,this.options=t,n.__super__.constructor.call(this)}return e.Extend(n,e.Observable),n.prototype.render=function(){var e=i('');return this._tabindex=0,null!=this.$element.data("old-tabindex")?this._tabindex=this.$element.data("old-tabindex"):null!=this.$element.attr("tabindex")&&(this._tabindex=this.$element.attr("tabindex")),e.attr("title",this.$element.attr("title")),e.attr("tabindex",this._tabindex),this.$selection=e},n.prototype.bind=function(e,t){var n=this,i=(e.id,e.id+"-results");this.options.get("minimumResultsForSearch"),Infinity;this.container=e,this.$selection.on("focus",function(e){n.trigger("focus",e)}),this.$selection.on("blur",function(e){n._handleBlur(e)}),this.$selection.on("keydown",function(e){n.trigger("keypress",e),e.which===o.SPACE&&e.preventDefault()}),e.on("results:focus",function(e){n.$selection.attr("aria-activedescendant",e.data._resultId)}),e.on("selection:update",function(e){n.update(e.data)}),e.on("open",function(){n.$selection.attr("aria-expanded","true"),n.$selection.attr("aria-owns",i),n._attachCloseHandler(e)}),e.on("close",function(){n.$selection.attr("aria-expanded","false"),n.$selection.removeAttr("aria-activedescendant"),n.$selection.removeAttr("aria-owns"),window.setTimeout(function(){n.$selection.focus()},1),n._detachCloseHandler(e)}),e.on("enable",function(){n.$selection.attr("tabindex",n._tabindex)}),e.on("disable",function(){n.$selection.attr("tabindex","-1")})},n.prototype._handleBlur=function(e){var t=this;window.setTimeout(function(){document.activeElement==t.$selection[0]||i.contains(t.$selection[0],document.activeElement)||t.trigger("blur",e)},1)},n.prototype._attachCloseHandler=function(e){i(document.body).on("mousedown.select2."+e.id,function(e){var t=i(e.target),n=t.closest(".select2");i(".select2.select2-container--open").each(function(){var e=i(this);this!=n[0]&&(e.data("element").select2("close"),setTimeout(function(){e.find("*:focus").blur(),t.focus()},1))})})},n.prototype._detachCloseHandler=function(e){i(document.body).off("mousedown.select2."+e.id)},n.prototype.position=function(e,t){t.find(".selection").append(e)},n.prototype.destroy=function(){this._detachCloseHandler(this.container)},n.prototype.update=function(e){throw new Error("The `update` method must be defined in child classes.")},n}),e.define("select2/selection/single",["jquery","./base","../utils","../keys"],function(e,t,n,i){function o(){o.__super__.constructor.apply(this,arguments)}return n.Extend(o,t),o.prototype.render=function(){var e=o.__super__.render.call(this);return e.addClass("select2-selection--single"),e.html(''),e},o.prototype.bind=function(t,e){var n=this;o.__super__.bind.apply(this,arguments);var i=t.id+"-container";this.$selection.find(".select2-selection__rendered").attr("id",i).attr("role","textbox").attr("aria-readonly","true"),this.$selection.attr("aria-labelledby",i),this.$selection.attr("role","combobox"),this.$selection.on("mousedown",function(e){1===e.which&&n.trigger("toggle",{originalEvent:e})}),this.$selection.on("focus",function(e){}),this.$selection.on("keydown",function(e){!t.isOpen()&&48<=e.which&&e.which<=90&&t.open()}),this.$selection.on("blur",function(e){}),t.on("focus",function(e){t.isOpen()||n.$selection.focus()}),t.on("selection:update",function(e){n.update(e.data)})},o.prototype.clear=function(){this.$selection.find(".select2-selection__rendered").empty()},o.prototype.display=function(e,t){var n=this.options.get("templateSelection");return this.options.get("escapeMarkup")(n(e,t))},o.prototype.selectionContainer=function(){return e("")},o.prototype.update=function(e){if(0!==e.length){var t=e[0],n=this.$selection.find(".select2-selection__rendered"),i=this.display(t,n);n.empty().append(i),n.prop("title",t.title||t.text)}else this.clear()},o}),e.define("select2/selection/multiple",["jquery","./base","../utils"],function(i,e,a){function o(e,t){o.__super__.constructor.apply(this,arguments)}return a.Extend(o,e),o.prototype.render=function(){var e=o.__super__.render.call(this);return e.addClass("select2-selection--multiple"),e.html('
      '),e},o.prototype.bind=function(t,e){var n=this;o.__super__.bind.apply(this,arguments),this.$selection.on("click",function(e){n.trigger("toggle",{originalEvent:e})}),this.$selection.on("click",".select2-selection__choice__remove",function(e){if(!n.options.get("disabled")){var t=i(this).parent().data("data");n.trigger("unselect",{originalEvent:e,data:t})}}),this.$selection.on("keydown",function(e){!t.isOpen()&&48<=e.which&&e.which<=90&&t.open()}),t.on("focus",function(){n.focusOnSearch()})},o.prototype.clear=function(){this.$selection.find(".select2-selection__rendered").empty()},o.prototype.display=function(e,t){var n=this.options.get("templateSelection");return this.options.get("escapeMarkup")(n(e,t))},o.prototype.selectionContainer=function(){return i('
    • ')},o.prototype.focusOnSearch=function(){var e=this;"undefined"!=typeof e.$search&&setTimeout(function(){e._keyUpPrevented=!0,e.$search.focus()},1)},o.prototype.update=function(e){if(this.clear(),0!==e.length){for(var t=[],n=0;n×');n.data("data",t),this.$selection.find(".select2-selection__rendered").prepend(n)}},e}),e.define("select2/selection/search",["jquery","../utils","../keys"],function(i,e,a){function t(e,t,n){e.call(this,t,n)}return t.prototype.render=function(e){var t=i('');this.$searchContainer=t,this.$search=t.find("input");var n=e.call(this);return this._transferTabIndex(),n},t.prototype.bind=function(e,i,t){var o=this,n=i.id+"-results";e.call(this,i,t),i.on("open",function(){o.$search.attr("aria-owns",n),o.$search.trigger("focus")}),i.on("close",function(){o.$search.val(""),o.$search.removeAttr("aria-activedescendant"),o.$search.removeAttr("aria-owns"),o.$search.trigger("focus")}),i.on("enable",function(){o.$search.prop("disabled",!1),o._transferTabIndex()}),i.on("disable",function(){o.$search.prop("disabled",!0)}),i.on("focus",function(e){o.$search.trigger("focus")}),i.on("results:focus",function(e){o.$search.attr("aria-activedescendant",e.data._resultId)}),this.$selection.on("focusin",".select2-search--inline",function(e){o.trigger("focus",e)}),this.$selection.on("focusout",".select2-search--inline",function(e){o._handleBlur(e)}),this.$selection.on("keydown",".select2-search--inline",function(e){if(e.stopPropagation(),o.trigger("keypress",e),o._keyUpPrevented=e.isDefaultPrevented(),e.which===a.BACKSPACE&&""===o.$search.val()){var t=o.$searchContainer.prev(".select2-selection__choice");if(0this.maximumInputLength?this.trigger("results:message",{message:"inputTooLong",args:{maximum:this.maximumInputLength,input:t.term,params:t}}):e.call(this,t,n)},e}),e.define("select2/data/maximumSelectionLength",[],function(){function e(e,t,n){this.maximumSelectionLength=n.get("maximumSelectionLength"),e.call(this,t,n)}return e.prototype.query=function(n,i,o){var s=this;this.current(function(e){var t=null!=e?e.length:0;0=s.maximumSelectionLength?s.trigger("results:message",{message:"maximumSelected",args:{maximum:s.maximumSelectionLength}}):n.call(s,i,o)})},e}),e.define("select2/dropdown",["jquery","./utils"],function(t,e){function n(e,t){this.$element=e,this.options=t,n.__super__.constructor.call(this)}return e.Extend(n,e.Observable),n.prototype.render=function(){var e=t('');return e.attr("dir",this.options.get("dir")),this.$dropdown=e},n.prototype.bind=function(){},n.prototype.position=function(e,t){},n.prototype.destroy=function(){this.$dropdown.remove()},n}),e.define("select2/dropdown/search",["jquery","../utils"],function(s,e){function t(){}return t.prototype.render=function(e){var t=e.call(this),n=s('');return this.$searchContainer=n,this.$search=n.find("input"),t.prepend(n),t},t.prototype.bind=function(e,t,n){var i=this,o=t.id+"-results";e.call(this,t,n),this.$search.on("keydown",function(e){i.trigger("keypress",e),i._keyUpPrevented=e.isDefaultPrevented()}),this.$search.on("input",function(e){s(this).off("keyup")}),this.$search.on("keyup input",function(e){i.handleSearch(e)}),t.on("open",function(){i.$search.attr("tabindex",0),i.$search.attr("aria-owns",o),i.$search.focus(),window.setTimeout(function(){i.$search.focus()},0)}),t.on("close",function(){i.$search.attr("tabindex",-1),i.$search.removeAttr("aria-activedescendant"),i.$search.removeAttr("aria-owns"),i.$search.val("")}),t.on("focus",function(){t.isOpen()||i.$search.focus()}),t.on("results:all",function(e){null!=e.query.term&&""!==e.query.term||(i.showSearch(e)?i.$searchContainer.removeClass("select2-search--hide"):i.$searchContainer.addClass("select2-search--hide"))}),t.on("results:focus",function(e){i.$search.attr("aria-activedescendant",e.data._resultId)})},t.prototype.handleSearch=function(e){if(!this._keyUpPrevented){var t=this.$search.val();this.trigger("query",{term:t})}this._keyUpPrevented=!1},t.prototype.showSearch=function(e,t){return!0},t}),e.define("select2/dropdown/hidePlaceholder",[],function(){function e(e,t,n,i){this.placeholder=this.normalizePlaceholder(n.get("placeholder")),e.call(this,t,n,i)}return e.prototype.append=function(e,t){t.results=this.removePlaceholder(t.results),e.call(this,t)},e.prototype.normalizePlaceholder=function(e,t){return"string"==typeof t&&(t={id:"",text:t}),t},e.prototype.removePlaceholder=function(e,t){for(var n=t.slice(0),i=t.length-1;0<=i;i--){var o=t[i];this.placeholder.id===o.id&&n.splice(i,1)}return n},e}),e.define("select2/dropdown/infiniteScroll",["jquery"],function(o){function e(e,t,n,i){this.lastParams={},e.call(this,t,n,i),this.$loadingMore=this.createLoadingMore(),this.loading=!1}return e.prototype.append=function(e,t){this.$loadingMore.remove(),this.loading=!1,e.call(this,t),this.showLoadingMore(t)&&this.$results.append(this.$loadingMore)},e.prototype.bind=function(e,t,n){var i=this;e.call(this,t,n),t.on("query",function(e){i.lastParams=e,i.loading=!0}),t.on("query:append",function(e){i.lastParams=e,i.loading=!0}),this.$results.on("scroll",function(){var e=o.contains(document.documentElement,i.$loadingMore[0]);if(!i.loading&&e){var t=i.$results.offset().top+i.$results.outerHeight(!1);i.$loadingMore.offset().top+i.$loadingMore.outerHeight(!1)<=t+50&&i.loadMore()}})},e.prototype.loadMore=function(){this.loading=!0;var e=o.extend({},{page:1},this.lastParams);e.page++,this.trigger("query:append",e)},e.prototype.showLoadingMore=function(e,t){return t.pagination&&t.pagination.more},e.prototype.createLoadingMore=function(){var e=o('
    • '),t=this.options.get("translations").get("loadingMore");return e.html(t(this.lastParams)),e},e}),e.define("select2/dropdown/attachBody",["jquery","../utils"],function(f,a){function e(e,t,n){this.$dropdownParent=n.get("dropdownParent")||f(document.body),e.call(this,t,n)}return e.prototype.bind=function(e,t,n){var i=this,o=!1;e.call(this,t,n),t.on("open",function(){i._showDropdown(),i._attachPositioningHandler(t),o||(o=!0,t.on("results:all",function(){i._positionDropdown(),i._resizeDropdown()}),t.on("results:append",function(){i._positionDropdown(),i._resizeDropdown()}))}),t.on("close",function(){i._hideDropdown(),i._detachPositioningHandler(t)}),this.$dropdownContainer.on("mousedown",function(e){e.stopPropagation()})},e.prototype.destroy=function(e){e.call(this),this.$dropdownContainer.remove()},e.prototype.position=function(e,t,n){t.attr("class",n.attr("class")),t.removeClass("select2"),t.addClass("select2-container--open"),t.css({position:"absolute",top:-999999}),this.$container=n},e.prototype.render=function(e){var t=f(""),n=e.call(this);return t.append(n),this.$dropdownContainer=t},e.prototype._hideDropdown=function(e){this.$dropdownContainer.detach()},e.prototype._attachPositioningHandler=function(e,t){var n=this,i="scroll.select2."+t.id,o="resize.select2."+t.id,s="orientationchange.select2."+t.id,r=this.$container.parents().filter(a.hasScroll);r.each(function(){f(this).data("select2-scroll-position",{x:f(this).scrollLeft(),y:f(this).scrollTop()})}),r.on(i,function(e){var t=f(this).data("select2-scroll-position");f(this).scrollTop(t.y)}),f(window).on(i+" "+o+" "+s,function(e){n._positionDropdown(),n._resizeDropdown()})},e.prototype._detachPositioningHandler=function(e,t){var n="scroll.select2."+t.id,i="resize.select2."+t.id,o="orientationchange.select2."+t.id;this.$container.parents().filter(a.hasScroll).off(n),f(window).off(n+" "+i+" "+o)},e.prototype._positionDropdown=function(){var e=f(window),t=this.$dropdown.hasClass("select2-dropdown--above"),n=this.$dropdown.hasClass("select2-dropdown--below"),i=null,o=this.$container.offset();o.bottom=o.top+this.$container.outerHeight(!1);var s={height:this.$container.outerHeight(!1)};s.top=o.top,s.bottom=o.top+s.height;var r=this.$dropdown.outerHeight(!1),a=e.scrollTop(),l=e.scrollTop()+e.height(),c=ao.bottom+r,d={left:o.left,top:s.bottom},p=this.$dropdownParent;"static"===p.css("position")&&(p=p.offsetParent());var h=p.offset();d.top-=h.top,d.left-=h.left,t||n||(i="below"),u||!c||t?!c&&u&&t&&(i="below"):i="above",("above"==i||t&&"below"!==i)&&(d.top=s.top-h.top-r),null!=i&&(this.$dropdown.removeClass("select2-dropdown--below select2-dropdown--above").addClass("select2-dropdown--"+i),this.$container.removeClass("select2-container--below select2-container--above").addClass("select2-container--"+i)),this.$dropdownContainer.css(d)},e.prototype._resizeDropdown=function(){var e={width:this.$container.outerWidth(!1)+"px"};this.options.get("dropdownAutoWidth")&&(e.minWidth=e.width,e.position="relative",e.width="auto"),this.$dropdown.css(e)},e.prototype._showDropdown=function(e){this.$dropdownContainer.appendTo(this.$dropdownParent),this._positionDropdown(),this._resizeDropdown()},e}),e.define("select2/dropdown/minimumResultsForSearch",[],function(){function e(e,t,n,i){this.minimumResultsForSearch=n.get("minimumResultsForSearch"),this.minimumResultsForSearch<0&&(this.minimumResultsForSearch=Infinity),e.call(this,t,n,i)}return e.prototype.showSearch=function(e,t){return!(function o(e){for(var t=0,n=0;n');return e.attr("dir",this.options.get("dir")),this.$container=e,this.$container.addClass("select2-container--"+this.options.get("theme")),e.data("element",this.$element),e},u}),e.define("select2/compat/utils",["jquery"],function(r){return{syncCssClasses:function a(e,t,n){var i,o,s=[];(i=r.trim(e.attr("class")))&&r((i=""+i).split(/\s+/)).each(function(){0===this.indexOf("select2-")&&s.push(this)}),(i=r.trim(t.attr("class")))&&r((i=""+i).split(/\s+/)).each(function(){0!==this.indexOf("select2-")&&null!=(o=n(this))&&s.push(o)}),e.attr("class",s.join(" "))}}}),e.define("select2/compat/containerCss",["jquery","./utils"],function(r,a){function l(e){return null}function e(){}return e.prototype.render=function(e){var t=e.call(this),n=this.options.get("containerCssClass")||"";r.isFunction(n)&&(n=n(this.$element));var i=this.options.get("adaptContainerCssClass");if(i=i||l,-1!==n.indexOf(":all:")){n=n.replace(":all:","");var o=i;i=function(e){var t=o(e);return null!=t?t+" "+e:e}}var s=this.options.get("containerCss")||{};return r.isFunction(s)&&(s=s(this.$element)),a.syncCssClasses(t,this.$element,i),t.css(s),t.addClass(n),t},e}),e.define("select2/compat/dropdownCss",["jquery","./utils"],function(r,a){function l(e){return null}function e(){}return e.prototype.render=function(e){var t=e.call(this),n=this.options.get("dropdownCssClass")||"";r.isFunction(n)&&(n=n(this.$element));var i=this.options.get("adaptDropdownCssClass");if(i=i||l,-1!==n.indexOf(":all:")){n=n.replace(":all:","");var o=i;i=function(e){var t=o(e);return null!=t?t+" "+e:e}}var s=this.options.get("dropdownCss")||{};return r.isFunction(s)&&(s=s(this.$element)),a.syncCssClasses(t,this.$element,i),t.css(s),t.addClass(n),t},e}),e.define("select2/compat/initSelection",["jquery"],function(i){function e(e,t,n){n.get("debug")&&window.console&&console.warn&&console.warn("Select2: The `initSelection` option has been deprecated in favor of a custom data adapter that overrides the `current` method. This method is now called multiple times instead of a single time when the instance is initialized. Support will be removed for the `initSelection` option in future versions of Select2"),this.initSelection=n.get("initSelection"),this._isInitialized=!1,e.call(this,t,n)}return e.prototype.current=function(e,t){var n=this;this._isInitialized?e.call(this,t):this.initSelection.call(null,this.$element,function(e){n._isInitialized=!0,i.isArray(e)||(e=[e]),t(e)})},e}),e.define("select2/compat/inputData",["jquery"],function(r){function e(e,t,n){this._currentData=[],this._valueSeparator=n.get("valueSeparator")||",","hidden"===t.prop("type")&&n.get("debug")&&console&&console.warn&&console.warn("Select2: Using a hidden input with Select2 is no longer supported and may stop working in the future. It is recommended to use a `');this.$searchContainer=t,this.$search=t.find("input");var n=e.call(this);return this._transferTabIndex(),n},t.prototype.bind=function(e,i,t){var o=this,n=i.id+"-results";e.call(this,i,t),i.on("open",function(){o.$search.attr("aria-owns",n),o.$search.trigger("focus")}),i.on("close",function(){o.$search.val(""),o.$search.removeAttr("aria-activedescendant"),o.$search.removeAttr("aria-owns"),o.$search.trigger("focus")}),i.on("enable",function(){o.$search.prop("disabled",!1),o._transferTabIndex()}),i.on("disable",function(){o.$search.prop("disabled",!0)}),i.on("focus",function(e){o.$search.trigger("focus")}),i.on("results:focus",function(e){o.$search.attr("aria-activedescendant",e.data._resultId)}),this.$selection.on("focusin",".select2-search--inline",function(e){o.trigger("focus",e)}),this.$selection.on("focusout",".select2-search--inline",function(e){o._handleBlur(e)}),this.$selection.on("keydown",".select2-search--inline",function(e){if(e.stopPropagation(),o.trigger("keypress",e),o._keyUpPrevented=e.isDefaultPrevented(),e.which===a.BACKSPACE&&""===o.$search.val()){var t=o.$searchContainer.prev(".select2-selection__choice");if(0this.maximumInputLength?this.trigger("results:message",{message:"inputTooLong",args:{maximum:this.maximumInputLength,input:t.term,params:t}}):e.call(this,t,n)},e}),e.define("select2/data/maximumSelectionLength",[],function(){function e(e,t,n){this.maximumSelectionLength=n.get("maximumSelectionLength"),e.call(this,t,n)}return e.prototype.query=function(n,i,o){var s=this;this.current(function(e){var t=null!=e?e.length:0;0=s.maximumSelectionLength?s.trigger("results:message",{message:"maximumSelected",args:{maximum:s.maximumSelectionLength}}):n.call(s,i,o)})},e}),e.define("select2/dropdown",["jquery","./utils"],function(t,e){function n(e,t){this.$element=e,this.options=t,n.__super__.constructor.call(this)}return e.Extend(n,e.Observable),n.prototype.render=function(){var e=t('');return e.attr("dir",this.options.get("dir")),this.$dropdown=e},n.prototype.bind=function(){},n.prototype.position=function(e,t){},n.prototype.destroy=function(){this.$dropdown.remove()},n}),e.define("select2/dropdown/search",["jquery","../utils"],function(s,e){function t(){}return t.prototype.render=function(e){var t=e.call(this),n=s('');return this.$searchContainer=n,this.$search=n.find("input"),t.prepend(n),t},t.prototype.bind=function(e,t,n){var i=this,o=t.id+"-results";e.call(this,t,n),this.$search.on("keydown",function(e){i.trigger("keypress",e),i._keyUpPrevented=e.isDefaultPrevented()}),this.$search.on("input",function(e){s(this).off("keyup")}),this.$search.on("keyup input",function(e){i.handleSearch(e)}),t.on("open",function(){i.$search.attr("tabindex",0),i.$search.attr("aria-owns",o),i.$search.focus(),window.setTimeout(function(){i.$search.focus()},0)}),t.on("close",function(){i.$search.attr("tabindex",-1),i.$search.removeAttr("aria-activedescendant"),i.$search.removeAttr("aria-owns"),i.$search.val("")}),t.on("focus",function(){t.isOpen()||i.$search.focus()}),t.on("results:all",function(e){null!=e.query.term&&""!==e.query.term||(i.showSearch(e)?i.$searchContainer.removeClass("select2-search--hide"):i.$searchContainer.addClass("select2-search--hide"))}),t.on("results:focus",function(e){i.$search.attr("aria-activedescendant",e.data._resultId)})},t.prototype.handleSearch=function(e){if(!this._keyUpPrevented){var t=this.$search.val();this.trigger("query",{term:t})}this._keyUpPrevented=!1},t.prototype.showSearch=function(e,t){return!0},t}),e.define("select2/dropdown/hidePlaceholder",[],function(){function e(e,t,n,i){this.placeholder=this.normalizePlaceholder(n.get("placeholder")),e.call(this,t,n,i)}return e.prototype.append=function(e,t){t.results=this.removePlaceholder(t.results),e.call(this,t)},e.prototype.normalizePlaceholder=function(e,t){return"string"==typeof t&&(t={id:"",text:t}),t},e.prototype.removePlaceholder=function(e,t){for(var n=t.slice(0),i=t.length-1;0<=i;i--){var o=t[i];this.placeholder.id===o.id&&n.splice(i,1)}return n},e}),e.define("select2/dropdown/infiniteScroll",["jquery"],function(o){function e(e,t,n,i){this.lastParams={},e.call(this,t,n,i),this.$loadingMore=this.createLoadingMore(),this.loading=!1}return e.prototype.append=function(e,t){this.$loadingMore.remove(),this.loading=!1,e.call(this,t),this.showLoadingMore(t)&&this.$results.append(this.$loadingMore)},e.prototype.bind=function(e,t,n){var i=this;e.call(this,t,n),t.on("query",function(e){i.lastParams=e,i.loading=!0}),t.on("query:append",function(e){i.lastParams=e,i.loading=!0}),this.$results.on("scroll",function(){var e=o.contains(document.documentElement,i.$loadingMore[0]);if(!i.loading&&e){var t=i.$results.offset().top+i.$results.outerHeight(!1);i.$loadingMore.offset().top+i.$loadingMore.outerHeight(!1)<=t+50&&i.loadMore()}})},e.prototype.loadMore=function(){this.loading=!0;var e=o.extend({},{page:1},this.lastParams);e.page++,this.trigger("query:append",e)},e.prototype.showLoadingMore=function(e,t){return t.pagination&&t.pagination.more},e.prototype.createLoadingMore=function(){var e=o('
    • '),t=this.options.get("translations").get("loadingMore");return e.html(t(this.lastParams)),e},e}),e.define("select2/dropdown/attachBody",["jquery","../utils"],function(f,a){function e(e,t,n){this.$dropdownParent=n.get("dropdownParent")||f(document.body),e.call(this,t,n)}return e.prototype.bind=function(e,t,n){var i=this,o=!1;e.call(this,t,n),t.on("open",function(){i._showDropdown(),i._attachPositioningHandler(t),o||(o=!0,t.on("results:all",function(){i._positionDropdown(),i._resizeDropdown()}),t.on("results:append",function(){i._positionDropdown(),i._resizeDropdown()}))}),t.on("close",function(){i._hideDropdown(),i._detachPositioningHandler(t)}),this.$dropdownContainer.on("mousedown",function(e){e.stopPropagation()})},e.prototype.destroy=function(e){e.call(this),this.$dropdownContainer.remove()},e.prototype.position=function(e,t,n){t.attr("class",n.attr("class")),t.removeClass("select2"),t.addClass("select2-container--open"),t.css({position:"absolute",top:-999999}),this.$container=n},e.prototype.render=function(e){var t=f(""),n=e.call(this);return t.append(n),this.$dropdownContainer=t},e.prototype._hideDropdown=function(e){this.$dropdownContainer.detach()},e.prototype._attachPositioningHandler=function(e,t){var n=this,i="scroll.select2."+t.id,o="resize.select2."+t.id,s="orientationchange.select2."+t.id,r=this.$container.parents().filter(a.hasScroll);r.each(function(){f(this).data("select2-scroll-position",{x:f(this).scrollLeft(),y:f(this).scrollTop()})}),r.on(i,function(e){var t=f(this).data("select2-scroll-position");f(this).scrollTop(t.y)}),f(window).on(i+" "+o+" "+s,function(e){n._positionDropdown(),n._resizeDropdown()})},e.prototype._detachPositioningHandler=function(e,t){var n="scroll.select2."+t.id,i="resize.select2."+t.id,o="orientationchange.select2."+t.id;this.$container.parents().filter(a.hasScroll).off(n),f(window).off(n+" "+i+" "+o)},e.prototype._positionDropdown=function(){var e=f(window),t=this.$dropdown.hasClass("select2-dropdown--above"),n=this.$dropdown.hasClass("select2-dropdown--below"),i=null,o=this.$container.offset();o.bottom=o.top+this.$container.outerHeight(!1);var s={height:this.$container.outerHeight(!1)};s.top=o.top,s.bottom=o.top+s.height;var r=this.$dropdown.outerHeight(!1),a=e.scrollTop(),l=e.scrollTop()+e.height(),c=ao.bottom+r,d={left:o.left,top:s.bottom},p=this.$dropdownParent;"static"===p.css("position")&&(p=p.offsetParent());var h=p.offset();d.top-=h.top,d.left-=h.left,t||n||(i="below"),u||!c||t?!c&&u&&t&&(i="below"):i="above",("above"==i||t&&"below"!==i)&&(d.top=s.top-h.top-r),null!=i&&(this.$dropdown.removeClass("select2-dropdown--below select2-dropdown--above").addClass("select2-dropdown--"+i),this.$container.removeClass("select2-container--below select2-container--above").addClass("select2-container--"+i)),this.$dropdownContainer.css(d)},e.prototype._resizeDropdown=function(){var e={width:this.$container.outerWidth(!1)+"px"};this.options.get("dropdownAutoWidth")&&(e.minWidth=e.width,e.position="relative",e.width="auto"),this.$dropdown.css(e)},e.prototype._showDropdown=function(e){this.$dropdownContainer.appendTo(this.$dropdownParent),this._positionDropdown(),this._resizeDropdown()},e}),e.define("select2/dropdown/minimumResultsForSearch",[],function(){function e(e,t,n,i){this.minimumResultsForSearch=n.get("minimumResultsForSearch"),this.minimumResultsForSearch<0&&(this.minimumResultsForSearch=Infinity),e.call(this,t,n,i)}return e.prototype.showSearch=function(e,t){return!(function o(e){for(var t=0,n=0;n');return e.attr("dir",this.options.get("dir")),this.$container=e,this.$container.addClass("select2-container--"+this.options.get("theme")),e.data("element",this.$element),e},u}),e.define("select2/compat/utils",["jquery"],function(r){return{syncCssClasses:function a(e,t,n){var i,o,s=[];(i=r.trim(e.attr("class")))&&r((i=""+i).split(/\s+/)).each(function(){0===this.indexOf("select2-")&&s.push(this)}),(i=r.trim(t.attr("class")))&&r((i=""+i).split(/\s+/)).each(function(){0!==this.indexOf("select2-")&&null!=(o=n(this))&&s.push(o)}),e.attr("class",s.join(" "))}}}),e.define("select2/compat/containerCss",["jquery","./utils"],function(r,a){function l(e){return null}function e(){}return e.prototype.render=function(e){var t=e.call(this),n=this.options.get("containerCssClass")||"";r.isFunction(n)&&(n=n(this.$element));var i=this.options.get("adaptContainerCssClass");if(i=i||l,-1!==n.indexOf(":all:")){n=n.replace(":all:","");var o=i;i=function(e){var t=o(e);return null!=t?t+" "+e:e}}var s=this.options.get("containerCss")||{};return r.isFunction(s)&&(s=s(this.$element)),a.syncCssClasses(t,this.$element,i),t.css(s),t.addClass(n),t},e}),e.define("select2/compat/dropdownCss",["jquery","./utils"],function(r,a){function l(e){return null}function e(){}return e.prototype.render=function(e){var t=e.call(this),n=this.options.get("dropdownCssClass")||"";r.isFunction(n)&&(n=n(this.$element));var i=this.options.get("adaptDropdownCssClass");if(i=i||l,-1!==n.indexOf(":all:")){n=n.replace(":all:","");var o=i;i=function(e){var t=o(e);return null!=t?t+" "+e:e}}var s=this.options.get("dropdownCss")||{};return r.isFunction(s)&&(s=s(this.$element)),a.syncCssClasses(t,this.$element,i),t.css(s),t.addClass(n),t},e}),e.define("select2/compat/initSelection",["jquery"],function(i){function e(e,t,n){n.get("debug")&&window.console&&console.warn&&console.warn("Select2: The `initSelection` option has been deprecated in favor of a custom data adapter that overrides the `current` method. This method is now called multiple times instead of a single time when the instance is initialized. Support will be removed for the `initSelection` option in future versions of Select2"),this.initSelection=n.get("initSelection"),this._isInitialized=!1,e.call(this,t,n)}return e.prototype.current=function(e,t){var n=this;this._isInitialized?e.call(this,t):this.initSelection.call(null,this.$element,function(e){n._isInitialized=!0,i.isArray(e)||(e=[e]),t(e)})},e}),e.define("select2/compat/inputData",["jquery"],function(r){function e(e,t,n){this._currentData=[],this._valueSeparator=n.get("valueSeparator")||",","hidden"===t.prop("type")&&n.get("debug")&&console&&console.warn&&console.warn("Select2: Using a hidden input with Select2 is no longer supported and may stop working in the future. It is recommended to use a `');this.$searchContainer=t,this.$search=t.find("input");var n=e.call(this);return this._transferTabIndex(),n},t.prototype.bind=function(e,i,t){var r=this,n=i.id+"-results";e.call(this,i,t),i.on("open",function(){r.$search.attr("aria-owns",n),r.$search.trigger("focus")}),i.on("close",function(){r.$search.val(""),r.$search.removeAttr("aria-activedescendant"),r.$search.removeAttr("aria-owns"),r.$search.trigger("focus")}),i.on("enable",function(){r.$search.prop("disabled",!1),r._transferTabIndex()}),i.on("disable",function(){r.$search.prop("disabled",!0)}),i.on("focus",function(e){r.$search.trigger("focus")}),i.on("results:focus",function(e){r.$search.attr("aria-activedescendant",e.data._resultId)}),this.$selection.on("focusin",".select2-search--inline",function(e){r.trigger("focus",e)}),this.$selection.on("focusout",".select2-search--inline",function(e){r._handleBlur(e)}),this.$selection.on("keydown",".select2-search--inline",function(e){if(e.stopPropagation(),r.trigger("keypress",e),r._keyUpPrevented=e.isDefaultPrevented(),e.which===a.BACKSPACE&&""===r.$search.val()){var t=r.$searchContainer.prev(".select2-selection__choice");if(0this.maximumInputLength?this.trigger("results:message",{message:"inputTooLong",args:{maximum:this.maximumInputLength,input:t.term,params:t}}):e.call(this,t,n)},e}),e.define("select2/data/maximumSelectionLength",[],function(){function e(e,t,n){this.maximumSelectionLength=n.get("maximumSelectionLength"),e.call(this,t,n)}return e.prototype.query=function(n,i,r){var o=this;this.current(function(e){var t=null!=e?e.length:0;0=o.maximumSelectionLength?o.trigger("results:message",{message:"maximumSelected",args:{maximum:o.maximumSelectionLength}}):n.call(o,i,r)})},e}),e.define("select2/dropdown",["jquery","./utils"],function(t,e){function n(e,t){this.$element=e,this.options=t,n.__super__.constructor.call(this)}return e.Extend(n,e.Observable),n.prototype.render=function(){var e=t('');return e.attr("dir",this.options.get("dir")),this.$dropdown=e},n.prototype.bind=function(){},n.prototype.position=function(e,t){},n.prototype.destroy=function(){this.$dropdown.remove()},n}),e.define("select2/dropdown/search",["jquery","../utils"],function(o,e){function t(){}return t.prototype.render=function(e){var t=e.call(this),n=o('');return this.$searchContainer=n,this.$search=n.find("input"),t.prepend(n),t},t.prototype.bind=function(e,t,n){var i=this,r=t.id+"-results";e.call(this,t,n),this.$search.on("keydown",function(e){i.trigger("keypress",e),i._keyUpPrevented=e.isDefaultPrevented()}),this.$search.on("input",function(e){o(this).off("keyup")}),this.$search.on("keyup input",function(e){i.handleSearch(e)}),t.on("open",function(){i.$search.attr("tabindex",0),i.$search.attr("aria-owns",r),i.$search.focus(),window.setTimeout(function(){i.$search.focus()},0)}),t.on("close",function(){i.$search.attr("tabindex",-1),i.$search.removeAttr("aria-activedescendant"),i.$search.removeAttr("aria-owns"),i.$search.val("")}),t.on("focus",function(){t.isOpen()||i.$search.focus()}),t.on("results:all",function(e){null!=e.query.term&&""!==e.query.term||(i.showSearch(e)?i.$searchContainer.removeClass("select2-search--hide"):i.$searchContainer.addClass("select2-search--hide"))}),t.on("results:focus",function(e){i.$search.attr("aria-activedescendant",e.data._resultId)})},t.prototype.handleSearch=function(e){if(!this._keyUpPrevented){var t=this.$search.val();this.trigger("query",{term:t})}this._keyUpPrevented=!1},t.prototype.showSearch=function(e,t){return!0},t}),e.define("select2/dropdown/hidePlaceholder",[],function(){function e(e,t,n,i){this.placeholder=this.normalizePlaceholder(n.get("placeholder")),e.call(this,t,n,i)}return e.prototype.append=function(e,t){t.results=this.removePlaceholder(t.results),e.call(this,t)},e.prototype.normalizePlaceholder=function(e,t){return"string"==typeof t&&(t={id:"",text:t}),t},e.prototype.removePlaceholder=function(e,t){for(var n=t.slice(0),i=t.length-1;0<=i;i--){var r=t[i];this.placeholder.id===r.id&&n.splice(i,1)}return n},e}),e.define("select2/dropdown/infiniteScroll",["jquery"],function(r){function e(e,t,n,i){this.lastParams={},e.call(this,t,n,i),this.$loadingMore=this.createLoadingMore(),this.loading=!1}return e.prototype.append=function(e,t){this.$loadingMore.remove(),this.loading=!1,e.call(this,t),this.showLoadingMore(t)&&this.$results.append(this.$loadingMore)},e.prototype.bind=function(e,t,n){var i=this;e.call(this,t,n),t.on("query",function(e){i.lastParams=e,i.loading=!0}),t.on("query:append",function(e){i.lastParams=e,i.loading=!0}),this.$results.on("scroll",function(){var e=r.contains(document.documentElement,i.$loadingMore[0]);if(!i.loading&&e){var t=i.$results.offset().top+i.$results.outerHeight(!1);i.$loadingMore.offset().top+i.$loadingMore.outerHeight(!1)<=t+50&&i.loadMore()}})},e.prototype.loadMore=function(){this.loading=!0;var e=r.extend({},{page:1},this.lastParams);e.page++,this.trigger("query:append",e)},e.prototype.showLoadingMore=function(e,t){return t.pagination&&t.pagination.more},e.prototype.createLoadingMore=function(){var e=r('
    • '),t=this.options.get("translations").get("loadingMore");return e.html(t(this.lastParams)),e},e}),e.define("select2/dropdown/attachBody",["jquery","../utils"],function(f,a){function e(e,t,n){this.$dropdownParent=n.get("dropdownParent")||f(document.body),e.call(this,t,n)}return e.prototype.bind=function(e,t,n){var i=this,r=!1;e.call(this,t,n),t.on("open",function(){i._showDropdown(),i._attachPositioningHandler(t),r||(r=!0,t.on("results:all",function(){i._positionDropdown(),i._resizeDropdown()}),t.on("results:append",function(){i._positionDropdown(),i._resizeDropdown()}))}),t.on("close",function(){i._hideDropdown(),i._detachPositioningHandler(t)}),this.$dropdownContainer.on("mousedown",function(e){e.stopPropagation()})},e.prototype.destroy=function(e){e.call(this),this.$dropdownContainer.remove()},e.prototype.position=function(e,t,n){t.attr("class",n.attr("class")),t.removeClass("select2"),t.addClass("select2-container--open"),t.css({position:"absolute",top:-999999}),this.$container=n},e.prototype.render=function(e){var t=f(""),n=e.call(this);return t.append(n),this.$dropdownContainer=t},e.prototype._hideDropdown=function(e){this.$dropdownContainer.detach()},e.prototype._attachPositioningHandler=function(e,t){var n=this,i="scroll.select2."+t.id,r="resize.select2."+t.id,o="orientationchange.select2."+t.id,s=this.$container.parents().filter(a.hasScroll);s.each(function(){f(this).data("select2-scroll-position",{x:f(this).scrollLeft(),y:f(this).scrollTop()})}),s.on(i,function(e){var t=f(this).data("select2-scroll-position");f(this).scrollTop(t.y)}),f(window).on(i+" "+r+" "+o,function(e){n._positionDropdown(),n._resizeDropdown()})},e.prototype._detachPositioningHandler=function(e,t){var n="scroll.select2."+t.id,i="resize.select2."+t.id,r="orientationchange.select2."+t.id;this.$container.parents().filter(a.hasScroll).off(n),f(window).off(n+" "+i+" "+r)},e.prototype._positionDropdown=function(){var e=f(window),t=this.$dropdown.hasClass("select2-dropdown--above"),n=this.$dropdown.hasClass("select2-dropdown--below"),i=null,r=this.$container.offset();r.bottom=r.top+this.$container.outerHeight(!1);var o={height:this.$container.outerHeight(!1)};o.top=r.top,o.bottom=r.top+o.height;var s=this.$dropdown.outerHeight(!1),a=e.scrollTop(),l=e.scrollTop()+e.height(),c=ar.bottom+s,d={left:r.left,top:o.bottom},p=this.$dropdownParent;"static"===p.css("position")&&(p=p.offsetParent());var h=p.offset();d.top-=h.top,d.left-=h.left,t||n||(i="below"),u||!c||t?!c&&u&&t&&(i="below"):i="above",("above"==i||t&&"below"!==i)&&(d.top=o.top-h.top-s),null!=i&&(this.$dropdown.removeClass("select2-dropdown--below select2-dropdown--above").addClass("select2-dropdown--"+i),this.$container.removeClass("select2-container--below select2-container--above").addClass("select2-container--"+i)),this.$dropdownContainer.css(d)},e.prototype._resizeDropdown=function(){var e={width:this.$container.outerWidth(!1)+"px"};this.options.get("dropdownAutoWidth")&&(e.minWidth=e.width,e.position="relative",e.width="auto"),this.$dropdown.css(e)},e.prototype._showDropdown=function(e){this.$dropdownContainer.appendTo(this.$dropdownParent),this._positionDropdown(),this._resizeDropdown()},e}),e.define("select2/dropdown/minimumResultsForSearch",[],function(){function e(e,t,n,i){this.minimumResultsForSearch=n.get("minimumResultsForSearch"),this.minimumResultsForSearch<0&&(this.minimumResultsForSearch=Infinity),e.call(this,t,n,i)}return e.prototype.showSearch=function(e,t){return!(function r(e){for(var t=0,n=0;n');return e.attr("dir",this.options.get("dir")),this.$container=e,this.$container.addClass("select2-container--"+this.options.get("theme")),e.data("element",this.$element),e},u}),e.define("jquery-mousewheel",["jquery"],function(e){return e}),e.define("jquery.select2",["jquery","jquery-mousewheel","./select2/core","./select2/defaults"],function(r,e,o,t){if(null==r.fn.selectWoo){var s=["open","close","destroy"];r.fn.selectWoo=function(t){if("object"==typeof(t=t||{}))return this.each(function(){var e=r.extend(!0,{},t);new o(r(this),e)}),this;if("string"!=typeof t)throw new Error("Invalid arguments for Select2: "+t);var n,i=Array.prototype.slice.call(arguments,1);return this.each(function(){var e=r(this).data("select2");null==e&&window.console&&console.error&&console.error("The select2('"+t+"') method was called on an element that is not using Select2."),n=e[t].apply(e,i)}),-1":">",'"':""","'":"'","/":"/"};return"string"!=typeof e?e:String(e).replace(/[&<>"'\/\\]/g,function(e){return t[e]})},e.entityDecode=function(e){var t=document.createElement("textarea");return t.innerHTML=e,t.value},e.appendMany=function(e,t){if("1.7"===o.fn.jquery.substr(0,3)){var n=o();o.map(t,function(e){n=n.add(e)}),t=n}e.append(t)},e.isTouchscreen=function(){return"undefined"==typeof e._isTouchscreenCache&&(e._isTouchscreenCache="ontouchstart"in document.documentElement),e._isTouchscreenCache},e}),e.define("select2/results",["jquery","./utils"],function(h,e){function i(e,t,n){this.$element=e,this.data=n,this.options=t,i.__super__.constructor.call(this)}return e.Extend(i,e.Observable),i.prototype.render=function(){var e=h('
        ');return this.options.get("multiple")&&e.attr("aria-multiselectable","true"),this.$results=e},i.prototype.clear=function(){this.$results.empty()},i.prototype.displayMessage=function(e){var t=this.options.get("escapeMarkup");this.clear(),this.hideLoading();var n=h(''),i=this.options.get("translations").get(e.message);n.append(t(i(e.args))),n[0].className+=" select2-results__message",this.$results.append(n)},i.prototype.hideMessages=function(){this.$results.find(".select2-results__message").remove()},i.prototype.append=function(e){this.hideLoading();var t=[];if(null!=e.results&&0!==e.results.length){e.results=this.sort(e.results);for(var n=0;n",{"class":"select2-results__options select2-results__options--nested",role:"listbox"});p.append(l),o.attr("role","list"),o.append(s),o.append(p)}else this.template(e,t);return h.data(t,"data",e),t},i.prototype.bind=function(t,e){var l=this,n=t.id+"-results";this.$results.attr("id",n),t.on("results:all",function(e){l.clear(),l.append(e.data),t.isOpen()&&(l.setClasses(),l.highlightFirstItem())}),t.on("results:append",function(e){l.append(e.data),t.isOpen()&&l.setClasses()}),t.on("query",function(e){l.hideMessages(),l.showLoading(e)}),t.on("select",function(){t.isOpen()&&(l.setClasses(),l.highlightFirstItem())}),t.on("unselect",function(){t.isOpen()&&(l.setClasses(),l.highlightFirstItem())}),t.on("open",function(){l.$results.attr("aria-expanded","true"),l.$results.attr("aria-hidden","false"),l.setClasses(),l.ensureHighlightVisible()}),t.on("close",function(){l.$results.attr("aria-expanded","false"),l.$results.attr("aria-hidden","true"),l.$results.removeAttr("aria-activedescendant")}),t.on("results:toggle",function(){var e=l.getHighlightedResults();0!==e.length&&e.trigger("mouseup")}),t.on("results:select",function(){var e=l.getHighlightedResults();if(0!==e.length){var t=e.data("data");"true"==e.attr("data-selected")?l.trigger("close",{}):l.trigger("select",{data:t})}}),t.on("results:previous",function(){var e=l.getHighlightedResults(),t=l.$results.find("[data-selected]"),n=t.index(e);if(0!==n){var i=n-1;0===e.length&&(i=0);var r=t.eq(i);r.trigger("mouseenter");var o=l.$results.offset().top,s=r.offset().top,a=l.$results.scrollTop()+(s-o);0===i?l.$results.scrollTop(0):s-o<0&&l.$results.scrollTop(a)}}),t.on("results:next",function(){var e=l.getHighlightedResults(),t=l.$results.find("[data-selected]"),n=t.index(e)+1;if(!(n>=t.length)){var i=t.eq(n);i.trigger("mouseenter");var r=l.$results.offset().top+l.$results.outerHeight(!1),o=i.offset().top+i.outerHeight(!1),s=l.$results.scrollTop()+o-r;0===n?l.$results.scrollTop(0):rthis.$results.outerHeight()||o<0)&&this.$results.scrollTop(r)}},i.prototype.template=function(e,t){var n=this.options.get("templateResult"),i=this.options.get("escapeMarkup"),r=n(e,t);null==r?t.style.display="none":"string"==typeof r?t.innerHTML=i(r):h(t).append(r)},i}),e.define("select2/keys",[],function(){return{BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46}}),e.define("select2/selection/base",["jquery","../utils","../keys"],function(i,e,r){function n(e,t){this.$element=e,this.options=t,n.__super__.constructor.call(this)}return e.Extend(n,e.Observable),n.prototype.render=function(){var e=i('');return this._tabindex=0,null!=this.$element.data("old-tabindex")?this._tabindex=this.$element.data("old-tabindex"):null!=this.$element.attr("tabindex")&&(this._tabindex=this.$element.attr("tabindex")),e.attr("title",this.$element.attr("title")),e.attr("tabindex",this._tabindex),this.$selection=e},n.prototype.bind=function(e,t){var n=this,i=(e.id,e.id+"-results");this.options.get("minimumResultsForSearch"),Infinity;this.container=e,this.$selection.on("focus",function(e){n.trigger("focus",e)}),this.$selection.on("blur",function(e){n._handleBlur(e)}),this.$selection.on("keydown",function(e){n.trigger("keypress",e),e.which===r.SPACE&&e.preventDefault()}),e.on("results:focus",function(e){n.$selection.attr("aria-activedescendant",e.data._resultId)}),e.on("selection:update",function(e){n.update(e.data)}),e.on("open",function(){n.$selection.attr("aria-expanded","true"),n.$selection.attr("aria-owns",i),n._attachCloseHandler(e)}),e.on("close",function(){n.$selection.attr("aria-expanded","false"),n.$selection.removeAttr("aria-activedescendant"),n.$selection.removeAttr("aria-owns"),window.setTimeout(function(){n.$selection.focus()},1),n._detachCloseHandler(e)}),e.on("enable",function(){n.$selection.attr("tabindex",n._tabindex)}),e.on("disable",function(){n.$selection.attr("tabindex","-1")})},n.prototype._handleBlur=function(e){var t=this;window.setTimeout(function(){document.activeElement==t.$selection[0]||i.contains(t.$selection[0],document.activeElement)||t.trigger("blur",e)},1)},n.prototype._attachCloseHandler=function(e){i(document.body).on("mousedown.select2."+e.id,function(e){var t=i(e.target),n=t.closest(".select2");i(".select2.select2-container--open").each(function(){var e=i(this);this!=n[0]&&(e.data("element").select2("close"),setTimeout(function(){e.find("*:focus").blur(),t.focus()},1))})})},n.prototype._detachCloseHandler=function(e){i(document.body).off("mousedown.select2."+e.id)},n.prototype.position=function(e,t){t.find(".selection").append(e)},n.prototype.destroy=function(){this._detachCloseHandler(this.container)},n.prototype.update=function(e){throw new Error("The `update` method must be defined in child classes.")},n}),e.define("select2/selection/single",["jquery","./base","../utils","../keys"],function(e,t,r,n){function o(){o.__super__.constructor.apply(this,arguments)}return r.Extend(o,t),o.prototype.render=function(){var e=o.__super__.render.call(this);return e.addClass("select2-selection--single"),e.html(''),e},o.prototype.bind=function(t,e){var n=this;o.__super__.bind.apply(this,arguments);var i=t.id+"-container";this.$selection.find(".select2-selection__rendered").attr("id",i).attr("role","textbox").attr("aria-readonly","true"),this.$selection.attr("aria-labelledby",i),this.$selection.attr("role","combobox"),this.$selection.on("mousedown",function(e){1===e.which&&n.trigger("toggle",{originalEvent:e})}),this.$selection.on("focus",function(e){}),this.$selection.on("keydown",function(e){!t.isOpen()&&48<=e.which&&e.which<=90&&t.open()}),this.$selection.on("blur",function(e){}),t.on("focus",function(e){t.isOpen()||n.$selection.focus()}),t.on("selection:update",function(e){n.update(e.data)})},o.prototype.clear=function(){this.$selection.find(".select2-selection__rendered").empty()},o.prototype.display=function(e,t){var n=this.options.get("templateSelection");return this.options.get("escapeMarkup")(n(e,t))},o.prototype.selectionContainer=function(){return e("")},o.prototype.update=function(e){if(0!==e.length){var t=e[0],n=this.$selection.find(".select2-selection__rendered"),i=r.entityDecode(this.display(t,n));n.empty().text(i),n.prop("title",t.title||t.text)}else this.clear()},o}),e.define("select2/selection/multiple",["jquery","./base","../utils"],function(i,e,l){function r(e,t){r.__super__.constructor.apply(this,arguments)}return l.Extend(r,e),r.prototype.render=function(){var e=r.__super__.render.call(this);return e.addClass("select2-selection--multiple"),e.html('
          '),e},r.prototype.bind=function(t,e){var n=this;r.__super__.bind.apply(this,arguments),this.$selection.on("click",function(e){n.trigger("toggle",{originalEvent:e})}),this.$selection.on("click",".select2-selection__choice__remove",function(e){if(!n.options.get("disabled")){var t=i(this).parent().data("data");n.trigger("unselect",{originalEvent:e,data:t})}}),this.$selection.on("keydown",function(e){!t.isOpen()&&48<=e.which&&e.which<=90&&t.open()}),t.on("focus",function(){n.focusOnSearch()})},r.prototype.clear=function(){this.$selection.find(".select2-selection__rendered").empty()},r.prototype.display=function(e,t){var n=this.options.get("templateSelection");return this.options.get("escapeMarkup")(n(e,t))},r.prototype.selectionContainer=function(){return i('
        • ')},r.prototype.focusOnSearch=function(){var e=this;"undefined"!=typeof e.$search&&setTimeout(function(){e._keyUpPrevented=!0,e.$search.focus()},1)},r.prototype.update=function(e){if(this.clear(),0!==e.length){for(var t=[],n=0;n×');n.data("data",t),this.$selection.find(".select2-selection__rendered").prepend(n)}},e}),e.define("select2/selection/search",["jquery","../utils","../keys"],function(i,e,a){function t(e,t,n){e.call(this,t,n)}return t.prototype.render=function(e){var t=i('');this.$searchContainer=t,this.$search=t.find("input");var n=e.call(this);return this._transferTabIndex(),n},t.prototype.bind=function(e,i,t){var r=this,n=i.id+"-results";e.call(this,i,t),i.on("open",function(){r.$search.attr("aria-owns",n),r.$search.trigger("focus")}),i.on("close",function(){r.$search.val(""),r.$search.removeAttr("aria-activedescendant"),r.$search.removeAttr("aria-owns"),r.$search.trigger("focus")}),i.on("enable",function(){r.$search.prop("disabled",!1),r._transferTabIndex()}),i.on("disable",function(){r.$search.prop("disabled",!0)}),i.on("focus",function(e){r.$search.trigger("focus")}),i.on("results:focus",function(e){r.$search.attr("aria-activedescendant",e.data._resultId)}),this.$selection.on("focusin",".select2-search--inline",function(e){r.trigger("focus",e)}),this.$selection.on("focusout",".select2-search--inline",function(e){r._handleBlur(e)}),this.$selection.on("keydown",".select2-search--inline",function(e){if(e.stopPropagation(),r.trigger("keypress",e),r._keyUpPrevented=e.isDefaultPrevented(),e.which===a.BACKSPACE&&""===r.$search.val()){var t=r.$searchContainer.prev(".select2-selection__choice");if(0this.maximumInputLength?this.trigger("results:message",{message:"inputTooLong",args:{maximum:this.maximumInputLength,input:t.term,params:t}}):e.call(this,t,n)},e}),e.define("select2/data/maximumSelectionLength",[],function(){function e(e,t,n){this.maximumSelectionLength=n.get("maximumSelectionLength"),e.call(this,t,n)}return e.prototype.query=function(n,i,r){var o=this;this.current(function(e){var t=null!=e?e.length:0;0=o.maximumSelectionLength?o.trigger("results:message",{message:"maximumSelected",args:{maximum:o.maximumSelectionLength}}):n.call(o,i,r)})},e}),e.define("select2/dropdown",["jquery","./utils"],function(t,e){function n(e,t){this.$element=e,this.options=t,n.__super__.constructor.call(this)}return e.Extend(n,e.Observable),n.prototype.render=function(){var e=t('');return e.attr("dir",this.options.get("dir")),this.$dropdown=e},n.prototype.bind=function(){},n.prototype.position=function(e,t){},n.prototype.destroy=function(){this.$dropdown.remove()},n}),e.define("select2/dropdown/search",["jquery","../utils"],function(o,e){function t(){}return t.prototype.render=function(e){var t=e.call(this),n=o('');return this.$searchContainer=n,this.$search=n.find("input"),t.prepend(n),t},t.prototype.bind=function(e,t,n){var i=this,r=t.id+"-results";e.call(this,t,n),this.$search.on("keydown",function(e){i.trigger("keypress",e),i._keyUpPrevented=e.isDefaultPrevented()}),this.$search.on("input",function(e){o(this).off("keyup")}),this.$search.on("keyup input",function(e){i.handleSearch(e)}),t.on("open",function(){i.$search.attr("tabindex",0),i.$search.attr("aria-owns",r),i.$search.focus(),window.setTimeout(function(){i.$search.focus()},0)}),t.on("close",function(){i.$search.attr("tabindex",-1),i.$search.removeAttr("aria-activedescendant"),i.$search.removeAttr("aria-owns"),i.$search.val("")}),t.on("focus",function(){t.isOpen()||i.$search.focus()}),t.on("results:all",function(e){null!=e.query.term&&""!==e.query.term||(i.showSearch(e)?i.$searchContainer.removeClass("select2-search--hide"):i.$searchContainer.addClass("select2-search--hide"))}),t.on("results:focus",function(e){i.$search.attr("aria-activedescendant",e.data._resultId)})},t.prototype.handleSearch=function(e){if(!this._keyUpPrevented){var t=this.$search.val();this.trigger("query",{term:t})}this._keyUpPrevented=!1},t.prototype.showSearch=function(e,t){return!0},t}),e.define("select2/dropdown/hidePlaceholder",[],function(){function e(e,t,n,i){this.placeholder=this.normalizePlaceholder(n.get("placeholder")),e.call(this,t,n,i)}return e.prototype.append=function(e,t){t.results=this.removePlaceholder(t.results),e.call(this,t)},e.prototype.normalizePlaceholder=function(e,t){return"string"==typeof t&&(t={id:"",text:t}),t},e.prototype.removePlaceholder=function(e,t){for(var n=t.slice(0),i=t.length-1;0<=i;i--){var r=t[i];this.placeholder.id===r.id&&n.splice(i,1)}return n},e}),e.define("select2/dropdown/infiniteScroll",["jquery"],function(r){function e(e,t,n,i){this.lastParams={},e.call(this,t,n,i),this.$loadingMore=this.createLoadingMore(),this.loading=!1}return e.prototype.append=function(e,t){this.$loadingMore.remove(),this.loading=!1,e.call(this,t),this.showLoadingMore(t)&&this.$results.append(this.$loadingMore)},e.prototype.bind=function(e,t,n){var i=this;e.call(this,t,n),t.on("query",function(e){i.lastParams=e,i.loading=!0}),t.on("query:append",function(e){i.lastParams=e,i.loading=!0}),this.$results.on("scroll",function(){var e=r.contains(document.documentElement,i.$loadingMore[0]);if(!i.loading&&e){var t=i.$results.offset().top+i.$results.outerHeight(!1);i.$loadingMore.offset().top+i.$loadingMore.outerHeight(!1)<=t+50&&i.loadMore()}})},e.prototype.loadMore=function(){this.loading=!0;var e=r.extend({},{page:1},this.lastParams);e.page++,this.trigger("query:append",e)},e.prototype.showLoadingMore=function(e,t){return t.pagination&&t.pagination.more},e.prototype.createLoadingMore=function(){var e=r('
        • '),t=this.options.get("translations").get("loadingMore");return e.html(t(this.lastParams)),e},e}),e.define("select2/dropdown/attachBody",["jquery","../utils"],function(f,a){function e(e,t,n){this.$dropdownParent=n.get("dropdownParent")||f(document.body),e.call(this,t,n)}return e.prototype.bind=function(e,t,n){var i=this,r=!1;e.call(this,t,n),t.on("open",function(){i._showDropdown(),i._attachPositioningHandler(t),r||(r=!0,t.on("results:all",function(){i._positionDropdown(),i._resizeDropdown()}),t.on("results:append",function(){i._positionDropdown(),i._resizeDropdown()}))}),t.on("close",function(){i._hideDropdown(),i._detachPositioningHandler(t)}),this.$dropdownContainer.on("mousedown",function(e){e.stopPropagation()})},e.prototype.destroy=function(e){e.call(this),this.$dropdownContainer.remove()},e.prototype.position=function(e,t,n){t.attr("class",n.attr("class")),t.removeClass("select2"),t.addClass("select2-container--open"),t.css({position:"absolute",top:-999999}),this.$container=n},e.prototype.render=function(e){var t=f(""),n=e.call(this);return t.append(n),this.$dropdownContainer=t},e.prototype._hideDropdown=function(e){this.$dropdownContainer.detach()},e.prototype._attachPositioningHandler=function(e,t){var n=this,i="scroll.select2."+t.id,r="resize.select2."+t.id,o="orientationchange.select2."+t.id,s=this.$container.parents().filter(a.hasScroll);s.each(function(){f(this).data("select2-scroll-position",{x:f(this).scrollLeft(),y:f(this).scrollTop()})}),s.on(i,function(e){var t=f(this).data("select2-scroll-position");f(this).scrollTop(t.y)}),f(window).on(i+" "+r+" "+o,function(e){n._positionDropdown(),n._resizeDropdown()})},e.prototype._detachPositioningHandler=function(e,t){var n="scroll.select2."+t.id,i="resize.select2."+t.id,r="orientationchange.select2."+t.id;this.$container.parents().filter(a.hasScroll).off(n),f(window).off(n+" "+i+" "+r)},e.prototype._positionDropdown=function(){var e=f(window),t=this.$dropdown.hasClass("select2-dropdown--above"),n=this.$dropdown.hasClass("select2-dropdown--below"),i=null,r=this.$container.offset();r.bottom=r.top+this.$container.outerHeight(!1);var o={height:this.$container.outerHeight(!1)};o.top=r.top,o.bottom=r.top+o.height;var s=this.$dropdown.outerHeight(!1),a=e.scrollTop(),l=e.scrollTop()+e.height(),c=ar.bottom+s,d={left:r.left,top:o.bottom},p=this.$dropdownParent;"static"===p.css("position")&&(p=p.offsetParent());var h=p.offset();d.top-=h.top,d.left-=h.left,t||n||(i="below"),u||!c||t?!c&&u&&t&&(i="below"):i="above",("above"==i||t&&"below"!==i)&&(d.top=o.top-h.top-s),null!=i&&(this.$dropdown.removeClass("select2-dropdown--below select2-dropdown--above").addClass("select2-dropdown--"+i),this.$container.removeClass("select2-container--below select2-container--above").addClass("select2-container--"+i)),this.$dropdownContainer.css(d)},e.prototype._resizeDropdown=function(){var e={width:this.$container.outerWidth(!1)+"px"};this.options.get("dropdownAutoWidth")&&(e.minWidth=e.width,e.position="relative",e.width="auto"),this.$dropdown.css(e)},e.prototype._showDropdown=function(e){this.$dropdownContainer.appendTo(this.$dropdownParent),this._positionDropdown(),this._resizeDropdown()},e}),e.define("select2/dropdown/minimumResultsForSearch",[],function(){function e(e,t,n,i){this.minimumResultsForSearch=n.get("minimumResultsForSearch"),this.minimumResultsForSearch<0&&(this.minimumResultsForSearch=Infinity),e.call(this,t,n,i)}return e.prototype.showSearch=function(e,t){return!(function r(e){for(var t=0,n=0;n');return e.attr("dir",this.options.get("dir")),this.$container=e,this.$container.addClass("select2-container--"+this.options.get("theme")),e.data("element",this.$element),e},u}),e.define("jquery-mousewheel",["jquery"],function(e){return e}),e.define("jquery.select2",["jquery","jquery-mousewheel","./select2/core","./select2/defaults"],function(r,e,o,t){if(null==r.fn.selectWoo){var s=["open","close","destroy"];r.fn.selectWoo=function(t){if("object"==typeof(t=t||{}))return this.each(function(){var e=r.extend(!0,{},t);new o(r(this),e)}),this;if("string"!=typeof t)throw new Error("Invalid arguments for Select2: "+t);var n,i=Array.prototype.slice.call(arguments,1);return this.each(function(){var e=r(this).data("select2");null==e&&window.console&&console.error&&console.error("The select2('"+t+"') method was called on an element that is not using Select2."),n=e[t].apply(e,i)}),-1WooCommerce core" > $output_file +echo "Generating contributor list for WC core since $from_date" +./node_modules/.bin/githubcontrib --repo woocommerce $common_arguments >> $output_file + +echo "

          WooCommerce Admin

          " >> $output_file +echo "Generating contributor list for WC Admin since $from_date" +./node_modules/.bin/githubcontrib --repo woocommerce-admin $common_arguments >> $output_file + +echo "

          WooCommerce Blocks

          " >> $output_file +echo "Generating contributor list for WC Blocks since $from_date" +./node_modules/.bin/githubcontrib --repo woocommerce-gutenberg-products-block $common_arguments >> $output_file + +echo "

          Action Scheduler

          " >> $output_file +echo "Generating contributor list for Action Scheduler since $from_date" +./node_modules/.bin/githubcontrib --repo action-scheduler $common_arguments >> $output_file + +echo "

          REST API

          " >> $output_file +echo "Generating contributor list for REST API since $from_date" +./node_modules/.bin/githubcontrib --repo woocommerce-rest-api $common_arguments >> $output_file + +echo "Output generated to $output_file." diff --git a/bin/package-update.sh b/bin/package-update.sh index 0a3cc1b6a95..f3bb1137f81 100755 --- a/bin/package-update.sh +++ b/bin/package-update.sh @@ -34,7 +34,8 @@ output 2 "Done!" output 3 "Updating package JS textdomains..." find ./packages/woocommerce-blocks -iname '*.js' -exec sed -i.bak -e "s/'woo-gutenberg-products-block'/'woocommerce'/g" -e "s/\"woo-gutenberg-products-block\"/'woocommerce'/g" {} \; -find ./packages/woocommerce-admin -iname '*.js' -exec sed -i.bak -e "s/, 'woocommerce-admin'/, 'woocommerce'/g" {} \; +find ./packages/woocommerce-blocks -iname '*.js' -exec sed -i.bak -e "s/'woocommerce-admin'/'woocommerce'/g" -e "s/\"woocommerce-admin\"/'woocommerce'/g" {} \; +find ./packages/woocommerce-admin -iname '*.js' -exec sed -i.bak -e "s/'woocommerce-admin'/'woocommerce'/g" -e "s/\"woocommerce-admin\"/'woocommerce'/g" {} \; # Cleanup backup files find ./packages -name "*.bak" -type f -delete diff --git a/bin/pre-push.sh b/bin/pre-push.sh new file mode 100755 index 00000000000..4f4afd34923 --- /dev/null +++ b/bin/pre-push.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +PROTECTED_BRANCH="master" +REMOTE_REF=$(echo "$HUSKY_GIT_STDIN" | cut -d " " -f 3) + +if [ -n "$REMOTE_REF" ]; then + if [ -z "${REMOTE_REF##*$PROTECTED_BRANCH*}" ]; then + printf "%sYou're about to push to master, is that what you intended? [y/N]: %s" "$(tput setaf 3)" "$(tput sgr0)" + read -r PROCEED < /dev/tty + echo + + if [ "$(echo "${PROCEED:-n}" | tr "[:upper:]" "[:lower:]")" = "y" ]; then + echo "$(tput setaf 2)Brace yourself! Pushing to the master branch...$(tput sgr0)" + echo + exit 0 + fi + + echo "$(tput setaf 2)Push to master cancelled!$(tput sgr0)" + echo + exit 1 + fi +fi diff --git a/composer.json b/composer.json index b204fe4c990..e2c31e99b5a 100644 --- a/composer.json +++ b/composer.json @@ -8,15 +8,15 @@ "minimum-stability": "dev", "require": { "php": ">=7.0", - "automattic/jetpack-autoloader": "^1.6.0", + "automattic/jetpack-autoloader": "^1.7.0", "automattic/jetpack-constants": "^1.1", "composer/installers": "1.7.0", "maxmind-db/reader": "1.6.0", "pelago/emogrifier": "^3.1", - "woocommerce/action-scheduler": "3.1.5", - "woocommerce/woocommerce-blocks": "2.5.16", - "woocommerce/woocommerce-rest-api": "1.0.7", - "woocommerce/woocommerce-admin": "1.1.1" + "woocommerce/action-scheduler": "3.1.6", + "woocommerce/woocommerce-admin": "1.3.0-rc.1", + "woocommerce/woocommerce-blocks": "2.7.1", + "woocommerce/woocommerce-rest-api": "1.0.10" }, "require-dev": { "phpunit/phpunit": "7.5.20", @@ -43,6 +43,12 @@ "Automattic\\WooCommerce\\": "src/" } }, + "autoload-dev": { + "psr-4": { + "Automattic\\WooCommerce\\Tests\\": "tests/php/src", + "Automattic\\WooCommerce\\Testing\\Tools\\": "tests/Tools" + } + }, "scripts": { "post-install-cmd": [ "sh ./bin/package-update.sh" @@ -63,7 +69,7 @@ "phpcbf -p" ], "makepot-audit": [ - "wp i18n make-pot . --exclude=\".github,.wordpress-org,bin,sample-data,node_modules,tests\" --slug=woocommerce" + "wp --allow-root i18n make-pot . --exclude=\".github,.wordpress-org,bin,sample-data,node_modules,tests\" --slug=woocommerce" ], "makepot": [ "@makepot-audit --skip-audit" @@ -80,8 +86,8 @@ "test": "Run unit tests", "phpcs": "Analyze code against the WordPress coding standards with PHP_CodeSniffer", "phpcbf": "Fix coding standards warnings/errors automatically with PHP Code Beautifier", - "makepot-audit": "Generate i18n/langauges/woocommerce.pot file and run audit", - "makepot": "Generate i18n/langauges/woocommerce.pot file" + "makepot-audit": "Generate i18n/languages/woocommerce.pot file and run audit", + "makepot": "Generate i18n/languages/woocommerce.pot file" } } } diff --git a/composer.lock b/composer.lock index 8d09e371394..dec7ac99caf 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4f587bb7d4020e7b4987cd1dde300e48", + "content-hash": "c35209de8f965f88aa5121e3ba76fc65", "packages": [ { "name": "automattic/jetpack-autoloader", - "version": "v1.6.0", + "version": "v1.7.0", "source": { "type": "git", "url": "https://github.com/Automattic/jetpack-autoloader.git", - "reference": "3bcbe1ae19febd6beeb181cf11af0bf0b7abe7e7" + "reference": "7c6736eeee0f9fc49fa691fe3e958725efb27ca0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Automattic/jetpack-autoloader/zipball/3bcbe1ae19febd6beeb181cf11af0bf0b7abe7e7", - "reference": "3bcbe1ae19febd6beeb181cf11af0bf0b7abe7e7", + "url": "https://api.github.com/repos/Automattic/jetpack-autoloader/zipball/7c6736eeee0f9fc49fa691fe3e958725efb27ca0", + "reference": "7c6736eeee0f9fc49fa691fe3e958725efb27ca0", "shasum": "" }, "require": { @@ -40,23 +40,24 @@ "GPL-2.0-or-later" ], "description": "Creates a custom autoloader for a plugin or theme.", - "time": "2020-03-26T07:57:53+00:00" + "time": "2020-04-23T02:28:37+00:00" }, { "name": "automattic/jetpack-constants", - "version": "v1.1.3", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/Automattic/jetpack-constants.git", - "reference": "5fdd94dec1151e7defd684a97e0b64fe6ff1bd3a" + "reference": "881618defb04134ddba120e7835af1a474a11edc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Automattic/jetpack-constants/zipball/5fdd94dec1151e7defd684a97e0b64fe6ff1bd3a", - "reference": "5fdd94dec1151e7defd684a97e0b64fe6ff1bd3a", + "url": "https://api.github.com/repos/Automattic/jetpack-constants/zipball/881618defb04134ddba120e7835af1a474a11edc", + "reference": "881618defb04134ddba120e7835af1a474a11edc", "shasum": "" }, "require-dev": { + "php-mock/php-mock": "^2.1", "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5" }, "type": "library", @@ -70,7 +71,7 @@ "GPL-2.0-or-later" ], "description": "A wrapper for defining constants in a more testable way.", - "time": "2019-11-08T21:16:05+00:00" + "time": "2020-04-15T18:58:53+00:00" }, { "name": "composer/installers", @@ -330,7 +331,7 @@ }, { "name": "symfony/css-selector", - "version": "v3.4.39", + "version": "v3.4.42", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", @@ -379,34 +380,20 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], "time": "2020-03-16T08:31:04+00:00" }, { "name": "woocommerce/action-scheduler", - "version": "3.1.5", + "version": "3.1.6", "source": { "type": "git", "url": "https://github.com/woocommerce/action-scheduler.git", - "reference": "84e8ecba7d4f542f85fae7663e90eede1858b41b" + "reference": "275d0ba54b1c263dfc62688de2fa9a25a373edf8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/woocommerce/action-scheduler/zipball/84e8ecba7d4f542f85fae7663e90eede1858b41b", - "reference": "84e8ecba7d4f542f85fae7663e90eede1858b41b", + "url": "https://api.github.com/repos/woocommerce/action-scheduler/zipball/275d0ba54b1c263dfc62688de2fa9a25a373edf8", + "reference": "275d0ba54b1c263dfc62688de2fa9a25a373edf8", "shasum": "" }, "require-dev": { @@ -428,20 +415,20 @@ ], "description": "Action Scheduler for WordPress and WooCommerce", "homepage": "https://actionscheduler.org/", - "time": "2020-04-29T16:19:22+00:00" + "time": "2020-05-12T16:22:33+00:00" }, { "name": "woocommerce/woocommerce-admin", - "version": "v1.1.1", + "version": "v1.3.0-rc.1", "source": { "type": "git", "url": "https://github.com/woocommerce/woocommerce-admin.git", - "reference": "79e78bb8b71fa0c0b0a77efee5474b46d62c1a76" + "reference": "12bc8bf522298a099bb725990cd50bae944e667f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/79e78bb8b71fa0c0b0a77efee5474b46d62c1a76", - "reference": "79e78bb8b71fa0c0b0a77efee5474b46d62c1a76", + "url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/12bc8bf522298a099bb725990cd50bae944e667f", + "reference": "12bc8bf522298a099bb725990cd50bae944e667f", "shasum": "" }, "require": { @@ -475,20 +462,20 @@ ], "description": "A modern, javascript-driven WooCommerce Admin experience.", "homepage": "https://github.com/woocommerce/woocommerce-admin", - "time": "2020-04-28T22:16:15+00:00" + "time": "2020-06-23T02:57:05+00:00" }, { "name": "woocommerce/woocommerce-blocks", - "version": "v2.5.16", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/woocommerce/woocommerce-gutenberg-products-block.git", - "reference": "3bd91b669247000fd3f5277954701d0b148d3f1a" + "reference": "0025c5cda83892c6f566fffd05197006f230d16c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/3bd91b669247000fd3f5277954701d0b148d3f1a", - "reference": "3bd91b669247000fd3f5277954701d0b148d3f1a", + "url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/0025c5cda83892c6f566fffd05197006f230d16c", + "reference": "0025c5cda83892c6f566fffd05197006f230d16c", "shasum": "" }, "require": { @@ -522,20 +509,20 @@ "gutenberg", "woocommerce" ], - "time": "2020-04-07T11:47:19+00:00" + "time": "2020-06-16T13:34:29+00:00" }, { "name": "woocommerce/woocommerce-rest-api", - "version": "1.0.7", + "version": "1.0.10", "source": { "type": "git", "url": "https://github.com/woocommerce/woocommerce-rest-api.git", - "reference": "49162ec26a25bd0c6efc0f3452b113cdfff0a823" + "reference": "fdcb116b4f5b699b942c01b46fd863c7da8b4b7c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/woocommerce/woocommerce-rest-api/zipball/49162ec26a25bd0c6efc0f3452b113cdfff0a823", - "reference": "49162ec26a25bd0c6efc0f3452b113cdfff0a823", + "url": "https://api.github.com/repos/woocommerce/woocommerce-rest-api/zipball/fdcb116b4f5b699b942c01b46fd863c7da8b4b7c", + "reference": "fdcb116b4f5b699b942c01b46fd863c7da8b4b7c", "shasum": "" }, "require": { @@ -562,7 +549,7 @@ ], "description": "The WooCommerce core REST API.", "homepage": "https://github.com/woocommerce/woocommerce-rest-api", - "time": "2020-01-28T21:04:51+00:00" + "time": "2020-06-16T09:51:51+00:00" } ], "packages-dev": [ @@ -634,20 +621,20 @@ }, { "name": "doctrine/instantiator", - "version": "1.3.0", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" + "reference": "f350df0268e904597e3bd9c4685c53e0e333feea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", - "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f350df0268e904597e3bd9c4685c53e0e333feea", + "reference": "f350df0268e904597e3bd9c4685c53e0e333feea", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.1 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^6.0", @@ -686,7 +673,7 @@ "constructor", "instantiate" ], - "time": "2019-10-21T16:45:58+00:00" + "time": "2020-05-29T17:27:14+00:00" }, { "name": "gettext/gettext", @@ -813,16 +800,16 @@ }, { "name": "mck89/peast", - "version": "v1.10.3", + "version": "v1.10.4", "source": { "type": "git", "url": "https://github.com/mck89/peast.git", - "reference": "6d1100f39f684c9e004f808b27f6c824b083d8d8" + "reference": "e11664ef53ba2a4ca1d16d8bc73fcc317cd65d3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mck89/peast/zipball/6d1100f39f684c9e004f808b27f6c824b083d8d8", - "reference": "6d1100f39f684c9e004f808b27f6c824b083d8d8", + "url": "https://api.github.com/repos/mck89/peast/zipball/e11664ef53ba2a4ca1d16d8bc73fcc317cd65d3d", + "reference": "e11664ef53ba2a4ca1d16d8bc73fcc317cd65d3d", "shasum": "" }, "require": { @@ -834,7 +821,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.10.3-dev" + "dev-master": "1.10.4-dev" } }, "autoload": { @@ -854,7 +841,7 @@ } ], "description": "Peast is PHP library that generates AST for JavaScript code", - "time": "2020-04-03T09:06:20+00:00" + "time": "2020-06-21T17:16:08+00:00" }, { "name": "mustache/mustache", @@ -1214,24 +1201,21 @@ }, { "name": "phpdocumentor/reflection-common", - "version": "2.0.0", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" + "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", - "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b", + "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b", "shasum": "" }, "require": { "php": ">=7.1" }, - "require-dev": { - "phpunit/phpunit": "~6" - }, "type": "library", "extra": { "branch-alias": { @@ -1262,7 +1246,7 @@ "reflection", "static analysis" ], - "time": "2018-08-07T13:53:10+00:00" + "time": "2020-04-27T09:25:28+00:00" }, { "name": "phpdocumentor/reflection-docblock", @@ -2430,7 +2414,7 @@ }, { "name": "symfony/finder", - "version": "v3.4.39", + "version": "v3.4.42", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", @@ -2475,34 +2459,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], "time": "2020-02-14T07:34:21+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.15.0", + "version": "v1.17.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14" + "reference": "2edd75b8b35d62fd3eeabba73b26b8f1f60ce13d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/4719fa9c18b0464d399f1a63bf624b42b6fa8d14", - "reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/2edd75b8b35d62fd3eeabba73b26b8f1f60ce13d", + "reference": "2edd75b8b35d62fd3eeabba73b26b8f1f60ce13d", "shasum": "" }, "require": { @@ -2514,7 +2484,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-master": "1.17-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { @@ -2547,21 +2521,7 @@ "polyfill", "portable" ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-02-27T09:26:54+00:00" + "time": "2020-06-06T08:46:27+00:00" }, { "name": "theseer/tokenizer", @@ -2605,16 +2565,16 @@ }, { "name": "webmozart/assert", - "version": "1.8.0", + "version": "1.9.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6" + "reference": "9dc4f203e36f2b486149058bade43c851dd97451" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/ab2cb0b3b559010b75981b1bdce728da3ee90ad6", - "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6", + "url": "https://api.github.com/repos/webmozart/assert/zipball/9dc4f203e36f2b486149058bade43c851dd97451", + "reference": "9dc4f203e36f2b486149058bade43c851dd97451", "shasum": "" }, "require": { @@ -2622,6 +2582,7 @@ "symfony/polyfill-ctype": "^1.8" }, "conflict": { + "phpstan/phpstan": "<0.12.20", "vimeo/psalm": "<3.9.1" }, "require-dev": { @@ -2649,7 +2610,7 @@ "check", "validate" ], - "time": "2020-04-18T12:12:48+00:00" + "time": "2020-06-16T10:16:42+00:00" }, { "name": "woocommerce/woocommerce-sniffs", @@ -2693,16 +2654,16 @@ }, { "name": "wp-cli/i18n-command", - "version": "v2.2.2", + "version": "v2.2.3", "source": { "type": "git", "url": "https://github.com/wp-cli/i18n-command.git", - "reference": "2804c5246d9338da59951737b03c54d257be8e47" + "reference": "7a5d483d872dfec1b89d88d348666ecd59454d52" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/i18n-command/zipball/2804c5246d9338da59951737b03c54d257be8e47", - "reference": "2804c5246d9338da59951737b03c54d257be8e47", + "url": "https://api.github.com/repos/wp-cli/i18n-command/zipball/7a5d483d872dfec1b89d88d348666ecd59454d52", + "reference": "7a5d483d872dfec1b89d88d348666ecd59454d52", "shasum": "" }, "require": { @@ -2746,7 +2707,7 @@ ], "description": "Provides internationalization tools for WordPress projects.", "homepage": "https://github.com/wp-cli/i18n-command", - "time": "2019-12-13T09:00:43+00:00" + "time": "2020-06-04T07:07:10+00:00" }, { "name": "wp-cli/mustangostang-spyc", @@ -2965,6 +2926,5 @@ "platform-dev": [], "platform-overrides": { "php": "7.1" - }, - "plugin-api-version": "1.1.0" + } } diff --git a/docker-compose.yaml b/docker-compose.yaml index 8d127416ccd..d0efa56e609 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,57 +1,14 @@ -version: '3.7' +version: '3.3' services: - db: - image: mariadb:10.5 - restart: on-failure - environment: - MYSQL_DATABASE: testdb - MYSQL_USER: wordpress - MYSQL_PASSWORD: wordpress - MYSQL_RANDOM_ROOT_PASSWORD: 'yes' + wordpress-www: volumes: - - db:/var/lib/mysql - - wordpress-woocommerce-dev: - depends_on: - - db - build: - context: . - dockerfile: Dockerfile - ports: - - 8084:80 - restart: on-failure - environment: - WORDPRESS_DB_HOST: db - WORDPRESS_DB_NAME: testdb - WORDPRESS_DB_USER: wordpress - WORDPRESS_DB_PASSWORD: wordpress - WORDPRESS_TABLE_PREFIX: "wp_" - WORDPRESS_DEBUG: 1 - volumes: - - "./:/var/www/html/wp-content/plugins/woocommerce" - - wordpress:/var/www/html + # This path is relative to the first config file + # which is in tests/e2e/env or node_modules/@woocommerce/e2e-environment + - "../../../:/var/www/html/wp-content/plugins/woocommerce" wordpress-cli: - depends_on: - - db - - wordpress-woocommerce-dev - image: wordpress:cli - restart: on-failure - user: xfs - command: > - /bin/sh -c ' - wp core install --url=http://localhost:8084 --title="WooCommerce Core E2E Test Suite" --admin_user=admin --admin_password=password --admin_email=admin@woocommercecoree2etestsuite.com --path=/var/www/html --skip-email; - wp plugin activate woocommerce; - wp theme install twentynineteen --activate; - wp user create customer customer@woocommercecoree2etestsuite.com --user_pass=password --role=customer --path=/var/www/html; - wp post create --post_type=page --post_status=publish --post_title='Ready' --post_content='E2E-tests.'; - ' volumes: - - "./:/var/www/html/wp-content/plugins/woocommerce" - - wordpress:/var/www/html + - "../../../:/var/www/html/wp-content/plugins/woocommerce" -volumes: - db: - wordpress: diff --git a/i18n/states.php b/i18n/states.php index 49aa9b6603a..9c2a5ff6876 100644 --- a/i18n/states.php +++ b/i18n/states.php @@ -349,6 +349,25 @@ return array( ), 'FI' => array(), 'FR' => array(), + 'GH' => array( // Ghanaian Regions. + 'AF' => __( 'Ahafo', 'woocommerce' ), + 'AH' => __( 'Ashanti', 'woocommerce' ), + 'BA' => __( 'Brong-Ahafo', 'woocommerce' ), + 'BO' => __( 'Bono', 'woocommerce' ), + 'BE' => __( 'Bono East', 'woocommerce' ), + 'CP' => __( 'Central', 'woocommerce' ), + 'EP' => __( 'Eastern', 'woocommerce' ), + 'AA' => __( 'Greater Accra', 'woocommerce' ), + 'NE' => __( 'North East', 'woocommerce' ), + 'NP' => __( 'Northern', 'woocommerce' ), + 'OT' => __( 'Oti', 'woocommerce' ), + 'SV' => __( 'Savannah', 'woocommerce' ), + 'UE' => __( 'Upper East', 'woocommerce' ), + 'UW' => __( 'Upper West', 'woocommerce' ), + 'TV' => __( 'Volta', 'woocommerce' ), + 'WP' => __( 'Western', 'woocommerce' ), + 'WN' => __( 'Western North', 'woocommerce' ), + ), 'GP' => array(), 'GR' => array( // Greek Regions. 'I' => __( 'Αττική', 'woocommerce' ), @@ -696,6 +715,55 @@ return array( 'JP46' => __( 'Kagoshima', 'woocommerce' ), 'JP47' => __( 'Okinawa', 'woocommerce' ), ), + 'KE' => array( // Kenya counties. + 'KE01' => __( 'Baringo', 'woocommerce' ), + 'KE02' => __( 'Bomet', 'woocommerce' ), + 'KE03' => __( 'Bungoma', 'woocommerce' ), + 'KE04' => __( 'Busia', 'woocommerce' ), + 'KE05' => __( 'Elgeyo-Marakwet', 'woocommerce' ), + 'KE06' => __( 'Embu', 'woocommerce' ), + 'KE07' => __( 'Garissa', 'woocommerce' ), + 'KE08' => __( 'Homa Bay', 'woocommerce' ), + 'KE09' => __( 'Isiolo', 'woocommerce' ), + 'KE10' => __( 'Kajiado', 'woocommerce' ), + 'KE11' => __( 'Kakamega', 'woocommerce' ), + 'KE12' => __( 'Kericho', 'woocommerce' ), + 'KE13' => __( 'Kiambu', 'woocommerce' ), + 'KE14' => __( 'Kilifi', 'woocommerce' ), + 'KE15' => __( 'Kirinyaga', 'woocommerce' ), + 'KE16' => __( 'Kisii', 'woocommerce' ), + 'KE17' => __( 'Kisumu', 'woocommerce' ), + 'KE18' => __( 'Kitui', 'woocommerce' ), + 'KE19' => __( 'Kwale', 'woocommerce' ), + 'KE20' => __( 'Laikipia', 'woocommerce' ), + 'KE21' => __( 'Lamu', 'woocommerce' ), + 'KE22' => __( 'Machakos', 'woocommerce' ), + 'KE23' => __( 'Makueni', 'woocommerce' ), + 'KE24' => __( 'Mandera', 'woocommerce' ), + 'KE25' => __( 'Marsabit', 'woocommerce' ), + 'KE26' => __( 'Meru', 'woocommerce' ), + 'KE27' => __( 'Migori', 'woocommerce' ), + 'KE28' => __( 'Mombasa', 'woocommerce' ), + 'KE29' => __( 'Murang’a', 'woocommerce' ), + 'KE30' => __( 'Nairobi County', 'woocommerce' ), + 'KE31' => __( 'Nakuru', 'woocommerce' ), + 'KE32' => __( 'Nandi', 'woocommerce' ), + 'KE33' => __( 'Narok', 'woocommerce' ), + 'KE34' => __( 'Nyamira', 'woocommerce' ), + 'KE35' => __( 'Nyandarua', 'woocommerce' ), + 'KE36' => __( 'Nyeri', 'woocommerce' ), + 'KE37' => __( 'Samburu', 'woocommerce' ), + 'KE38' => __( 'Siaya', 'woocommerce' ), + 'KE39' => __( 'Taita-Taveta', 'woocommerce' ), + 'KE40' => __( 'Tana River', 'woocommerce' ), + 'KE41' => __( 'Tharaka-Nithi', 'woocommerce' ), + 'KE42' => __( 'Trans Nzoia', 'woocommerce' ), + 'KE43' => __( 'Turkana', 'woocommerce' ), + 'KE44' => __( 'Uasin Gishu', 'woocommerce' ), + 'KE45' => __( 'Vihiga', 'woocommerce' ), + 'KE46' => __( 'Wajir', 'woocommerce' ), + 'KE47' => __( 'West Pokot', 'woocommerce' ), + ), 'KR' => array(), 'KW' => array(), 'LA' => array( @@ -828,6 +896,19 @@ return array( 'PJY' => __( 'Putrajaya', 'woocommerce' ), 'KUL' => __( 'Kuala Lumpur', 'woocommerce' ), ), + 'MZ' => array( // Mozambique provinces. + 'MZP' => __( 'Cabo Delgado', 'woocommerce' ), + 'MZG' => __( 'Gaza', 'woocommerce' ), + 'MZI' => __( 'Inhambane', 'woocommerce' ), + 'MZB' => __( 'Manica', 'woocommerce' ), + 'MZL' => __( 'Maputo Province', 'woocommerce' ), + 'MZMPM' => __( 'Maputo', 'woocommerce' ), + 'MZN' => __( 'Nampula', 'woocommerce' ), + 'MZA' => __( 'Niassa', 'woocommerce' ), + 'MZS' => __( 'Sofala', 'woocommerce' ), + 'MZT' => __( 'Tete', 'woocommerce' ), + 'MZQ' => __( 'Zambézia', 'woocommerce' ), + ), 'NG' => array( // Nigerian provinces. 'AB' => __( 'Abia', 'woocommerce' ), 'FC' => __( 'Abuja', 'woocommerce' ), diff --git a/includes/abstracts/abstract-wc-order.php b/includes/abstracts/abstract-wc-order.php index 5e5f38f6d9f..9c0f2618f7e 100644 --- a/includes/abstracts/abstract-wc-order.php +++ b/includes/abstracts/abstract-wc-order.php @@ -437,12 +437,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order { * @return float */ public function get_subtotal() { - $subtotal = 0; - - foreach ( $this->get_items() as $item ) { - $subtotal += wc_remove_number_precision( self::round_item_subtotal( wc_add_number_precision( $item->get_subtotal() ) ) ); - } - + $subtotal = round( $this->get_cart_subtotal_for_order(), wc_get_price_decimals() ); return apply_filters( 'woocommerce_order_get_subtotal', (float) $subtotal, $this ); } @@ -1672,18 +1667,13 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order { public function calculate_totals( $and_taxes = true ) { do_action( 'woocommerce_order_before_calculate_totals', $and_taxes, $this ); - $cart_subtotal = 0; - $cart_total = 0; $fees_total = 0; $shipping_total = 0; $cart_subtotal_tax = 0; $cart_total_tax = 0; - // Sum line item costs without rounding. - foreach ( $this->get_items() as $item ) { - $cart_subtotal += $item->get_subtotal(); - $cart_total += $item->get_total(); - } + $cart_subtotal = $this->get_cart_subtotal_for_order(); + $cart_total = $this->get_cart_total_for_order(); // Sum shipping costs. foreach ( $this->get_shipping_methods() as $shipping ) { diff --git a/includes/abstracts/abstract-wc-settings-api.php b/includes/abstracts/abstract-wc-settings-api.php index 6e844fb4939..4fd19ca7041 100644 --- a/includes/abstracts/abstract-wc-settings-api.php +++ b/includes/abstracts/abstract-wc-settings-api.php @@ -708,7 +708,7 @@ abstract class WC_Settings_API { get_description_html( $data ); // WPCS: XSS ok. ?> @@ -761,11 +761,11 @@ abstract class WC_Settings_API { $option_value_inner ) : ?> - + - + diff --git a/includes/admin/class-wc-admin-addons.php b/includes/admin/class-wc-admin-addons.php index 31e9adac3a3..42faab0fb19 100644 --- a/includes/admin/class-wc-admin-addons.php +++ b/includes/admin/class-wc-admin-addons.php @@ -51,13 +51,13 @@ class WC_Admin_Addons { */ public static function build_parameter_string( $category, $term, $country ) { - $paramters = array( + $parameters = array( 'category' => $category, 'term' => $term, 'country' => $country, ); - return '?' . http_build_query( $paramters ); + return '?' . http_build_query( $parameters ); } /** diff --git a/includes/admin/class-wc-admin-assets.php b/includes/admin/class-wc-admin-assets.php index 5bdd3e12685..df1b5de4f33 100644 --- a/includes/admin/class-wc-admin-assets.php +++ b/includes/admin/class-wc-admin-assets.php @@ -44,6 +44,7 @@ if ( ! class_exists( 'WC_Admin_Assets', false ) ) : wp_register_style( 'woocommerce_admin_dashboard_styles', WC()->plugin_url() . '/assets/css/dashboard.css', array(), $version ); wp_register_style( 'woocommerce_admin_print_reports_styles', WC()->plugin_url() . '/assets/css/reports-print.css', array(), $version, 'print' ); wp_register_style( 'woocommerce_admin_marketplace_styles', WC()->plugin_url() . '/assets/css/marketplace-suggestions.css', array(), $version ); + wp_register_style( 'woocommerce_admin_privacy_styles', WC()->plugin_url() . '/assets/css/privacy.css', array(), $version ); // Add RTL support for admin styles. wp_style_add_data( 'woocommerce_admin_menu_styles', 'rtl', 'replace' ); @@ -51,6 +52,7 @@ if ( ! class_exists( 'WC_Admin_Assets', false ) ) : wp_style_add_data( 'woocommerce_admin_dashboard_styles', 'rtl', 'replace' ); wp_style_add_data( 'woocommerce_admin_print_reports_styles', 'rtl', 'replace' ); wp_style_add_data( 'woocommerce_admin_marketplace_styles', 'rtl', 'replace' ); + wp_style_add_data( 'woocommerce_admin_privacy_styles', 'rtl', 'replace' ); // Sitewide menu CSS. wp_enqueue_style( 'woocommerce_admin_menu_styles' ); @@ -70,6 +72,11 @@ if ( ! class_exists( 'WC_Admin_Assets', false ) ) : wp_enqueue_style( 'woocommerce_admin_print_reports_styles' ); } + // Privacy Policy Guide css for back-compat. + if ( isset( $_GET['wp-privacy-policy-guide'] ) || in_array( $screen_id, array( 'privacy-policy-guide' ) ) ) { + wp_enqueue_style( 'woocommerce_admin_privacy_styles' ); + } + // @deprecated 2.3. if ( has_action( 'woocommerce_admin_css' ) ) { do_action( 'woocommerce_admin_css' ); diff --git a/includes/admin/class-wc-admin-dashboard.php b/includes/admin/class-wc-admin-dashboard.php index 9b5ef4941b3..28d1c6b0fe2 100644 --- a/includes/admin/class-wc-admin-dashboard.php +++ b/includes/admin/class-wc-admin-dashboard.php @@ -216,36 +216,61 @@ if ( ! class_exists( 'WC_Admin_Dashboard', false ) ) : $lowinstock_count = get_transient( $transient_name ); if ( false === $lowinstock_count ) { - $lowinstock_count = (int) $wpdb->get_var( - $wpdb->prepare( - "SELECT COUNT( product_id ) - FROM {$wpdb->wc_product_meta_lookup} AS lookup - INNER JOIN {$wpdb->posts} as posts ON lookup.product_id = posts.ID - WHERE stock_quantity <= %d - AND stock_quantity > %d - AND posts.post_status = 'publish'", - $stock, - $nostock - ) - ); - set_transient( $transient_name, $lowinstock_count, DAY_IN_SECONDS * 30 ); + /** + * Status widget low in stock count pre query. + * + * @since 4.3.0 + * @param null|string $low_in_stock_count Low in stock count, by default null. + * @param int $stock Low stock amount. + * @param int $nostock No stock amount + */ + $lowinstock_count = apply_filters( 'woocommerce_status_widget_low_in_stock_count_pre_query', null, $stock, $nostock ); + + if ( is_null( $lowinstock_count ) ) { + $lowinstock_count = $wpdb->get_var( + $wpdb->prepare( + "SELECT COUNT( product_id ) + FROM {$wpdb->wc_product_meta_lookup} AS lookup + INNER JOIN {$wpdb->posts} as posts ON lookup.product_id = posts.ID + WHERE stock_quantity <= %d + AND stock_quantity > %d + AND posts.post_status = 'publish'", + $stock, + $nostock + ) + ); + } + + set_transient( $transient_name, (int) $lowinstock_count, DAY_IN_SECONDS * 30 ); } $transient_name = 'wc_outofstock_count'; $outofstock_count = get_transient( $transient_name ); if ( false === $outofstock_count ) { - $outofstock_count = (int) $wpdb->get_var( - $wpdb->prepare( - "SELECT COUNT( product_id ) - FROM {$wpdb->wc_product_meta_lookup} AS lookup - INNER JOIN {$wpdb->posts} as posts ON lookup.product_id = posts.ID - WHERE stock_quantity <= %d - AND posts.post_status = 'publish'", - $nostock - ) - ); - set_transient( $transient_name, $outofstock_count, DAY_IN_SECONDS * 30 ); + /** + * Status widget out of stock count pre query. + * + * @since 4.3.0 + * @param null|string $outofstock_count Out of stock count, by default null. + * @param int $nostock No stock amount + */ + $outofstock_count = apply_filters( 'woocommerce_status_widget_out_of_stock_count_pre_query', null, $nostock ); + + if ( is_null( $outofstock_count ) ) { + $outofstock_count = (int) $wpdb->get_var( + $wpdb->prepare( + "SELECT COUNT( product_id ) + FROM {$wpdb->wc_product_meta_lookup} AS lookup + INNER JOIN {$wpdb->posts} as posts ON lookup.product_id = posts.ID + WHERE stock_quantity <= %d + AND posts.post_status = 'publish'", + $nostock + ) + ); + } + + set_transient( $transient_name, (int) $outofstock_count, DAY_IN_SECONDS * 30 ); } ?>
        • diff --git a/includes/admin/class-wc-admin-menus.php b/includes/admin/class-wc-admin-menus.php index 4443eba108a..3f1dd955b5e 100644 --- a/includes/admin/class-wc-admin-menus.php +++ b/includes/admin/class-wc-admin-menus.php @@ -184,7 +184,7 @@ class WC_Admin_Menus { // Add count if user has access. if ( apply_filters( 'woocommerce_include_processing_order_count_in_menu', true ) && current_user_can( 'edit_others_shop_orders' ) ) { - $order_count = wc_processing_order_count(); + $order_count = apply_filters( 'woocommerce_menu_order_count', wc_processing_order_count() ); if ( $order_count ) { foreach ( $submenu['woocommerce'] as $key => $menu_item ) { diff --git a/includes/admin/class-wc-admin-meta-boxes.php b/includes/admin/class-wc-admin-meta-boxes.php index dd50c90d3a5..32e03797591 100644 --- a/includes/admin/class-wc-admin-meta-boxes.php +++ b/includes/admin/class-wc-admin-meta-boxes.php @@ -49,9 +49,9 @@ class WC_Admin_Meta_Boxes { * Save order data - also updates status and sends out admin emails if needed. Last to show latest data. * Save actions - sends out other emails. Last to show latest data. */ - add_action( 'woocommerce_process_shop_order_meta', 'WC_Meta_Box_Order_Items::save', 10, 2 ); + add_action( 'woocommerce_process_shop_order_meta', 'WC_Meta_Box_Order_Items::save', 10 ); add_action( 'woocommerce_process_shop_order_meta', 'WC_Meta_Box_Order_Downloads::save', 30, 2 ); - add_action( 'woocommerce_process_shop_order_meta', 'WC_Meta_Box_Order_Data::save', 40, 2 ); + add_action( 'woocommerce_process_shop_order_meta', 'WC_Meta_Box_Order_Data::save', 40 ); add_action( 'woocommerce_process_shop_order_meta', 'WC_Meta_Box_Order_Actions::save', 50, 2 ); // Save Product Meta Boxes. diff --git a/includes/admin/class-wc-admin-notices.php b/includes/admin/class-wc-admin-notices.php index 59939424c8a..e6057d91c46 100644 --- a/includes/admin/class-wc-admin-notices.php +++ b/includes/admin/class-wc-admin-notices.php @@ -28,17 +28,19 @@ class WC_Admin_Notices { * @var array */ private static $core_notices = array( - 'install' => 'install_notice', - 'update' => 'update_notice', - 'template_files' => 'template_file_check_notice', - 'legacy_shipping' => 'legacy_shipping_notice', - 'no_shipping_methods' => 'no_shipping_methods_notice', - 'regenerating_thumbnails' => 'regenerating_thumbnails_notice', - 'regenerating_lookup_table' => 'regenerating_lookup_table_notice', - 'no_secure_connection' => 'secure_connection_notice', - WC_PHP_MIN_REQUIREMENTS_NOTICE => 'wp_php_min_requirements_notice', - 'maxmind_license_key' => 'maxmind_missing_license_key_notice', - 'redirect_download_method' => 'redirect_download_method_notice', + 'install' => 'install_notice', + 'update' => 'update_notice', + 'template_files' => 'template_file_check_notice', + 'legacy_shipping' => 'legacy_shipping_notice', + 'no_shipping_methods' => 'no_shipping_methods_notice', + 'regenerating_thumbnails' => 'regenerating_thumbnails_notice', + 'regenerating_lookup_table' => 'regenerating_lookup_table_notice', + 'no_secure_connection' => 'secure_connection_notice', + WC_PHP_MIN_REQUIREMENTS_NOTICE => 'wp_php_min_requirements_notice', + 'maxmind_license_key' => 'maxmind_missing_license_key_notice', + 'redirect_download_method' => 'redirect_download_method_notice', + 'uploads_directory_is_unprotected' => 'uploads_directory_is_unprotected_notice', + 'base_tables_missing' => 'base_tables_missing_notice', ); /** @@ -93,6 +95,9 @@ class WC_Admin_Notices { if ( ! self::is_ssl() ) { self::add_notice( 'no_secure_connection' ); } + if ( ! self::is_uploads_directory_protected() ) { + self::add_notice( 'uploads_directory_is_unprotected' ); + } self::add_notice( 'template_files' ); self::add_min_version_notice(); self::add_maxmind_missing_license_key_notice(); @@ -488,6 +493,35 @@ class WC_Admin_Notices { include dirname( __FILE__ ) . '/views/html-notice-redirect-only-download.php'; } + /** + * Notice about uploads directory begin unprotected. + * + * @since 4.2.0 + */ + public static function uploads_directory_is_unprotected_notice() { + if ( get_user_meta( get_current_user_id(), 'dismissed_uploads_directory_is_unprotected_notice', true ) || self::is_uploads_directory_protected() ) { + self::remove_notice( 'uploads_directory_is_unprotected' ); + return; + } + + include dirname( __FILE__ ) . '/views/html-notice-uploads-directory-is-unprotected.php'; + } + + /** + * Notice about base tables missing. + */ + public static function base_tables_missing_notice() { + $notice_dismissed = apply_filters( + 'woocommerce_hide_base_tables_missing_nag', + get_user_meta( get_current_user_id(), 'dismissed_base_tables_missing_notice', true ) + ); + if ( $notice_dismissed ) { + self::remove_notice( 'base_tables_missing' ); + } + + include dirname( __FILE__ ) . '/views/html-notice-base-table-missing.php'; + } + /** * Determine if the store is running SSL. * @@ -530,6 +564,42 @@ class WC_Admin_Notices { public static function theme_check_notice() { wc_deprecated_function( 'WC_Admin_Notices::theme_check_notice', '3.3.0' ); } + + /** + * Check if uploads directory is protected. + * + * @since 4.2.0 + * @return bool + */ + protected static function is_uploads_directory_protected() { + $cache_key = '_woocommerce_upload_directory_status'; + $status = get_transient( $cache_key ); + + // Check for cache. + if ( false !== $status ) { + return 'protected' === $status; + } + + // Get only data from the uploads directory. + $uploads = wp_get_upload_dir(); + + // Check for the "uploads/woocommerce_uploads" directory. + $response = wp_safe_remote_get( + esc_url_raw( $uploads['baseurl'] . '/woocommerce_uploads/' ), + array( + 'redirection' => 0, + ) + ); + $response_code = intval( wp_remote_retrieve_response_code( $response ) ); + $response_content = wp_remote_retrieve_body( $response ); + + // Check if returns 200 with empty content in case can open an index.html file, + // and check for non-200 codes in case the directory is protected. + $is_protected = ( 200 === $response_code && empty( $response_content ) ) || ( 200 !== $response_code ); + set_transient( $cache_key, $is_protected ? 'protected' : 'unprotected', 1 * DAY_IN_SECONDS ); + + return $is_protected; + } } WC_Admin_Notices::init(); diff --git a/includes/admin/class-wc-admin-settings.php b/includes/admin/class-wc-admin-settings.php index 837ffbc8230..1d1a49b8311 100644 --- a/includes/admin/class-wc-admin-settings.php +++ b/includes/admin/class-wc-admin-settings.php @@ -200,7 +200,7 @@ if ( ! class_exists( 'WC_Admin_Settings', false ) ) : /** * Output admin fields. * - * Loops though the woocommerce options array and outputs each field. + * Loops through the woocommerce options array and outputs each field. * * @param array[] $options Opens array to output. */ @@ -726,7 +726,7 @@ if ( ! class_exists( 'WC_Admin_Settings', false ) ) : /** * Save admin fields. * - * Loops though the woocommerce options array and outputs each field. + * Loops through the woocommerce options array and outputs each field. * * @param array $options Options array to output. * @param array $data Optional. Data to use for saving. Defaults to $_POST. @@ -869,25 +869,29 @@ if ( ! class_exists( 'WC_Admin_Settings', false ) ) : * If using force or x-sendfile, this ensures the .htaccess is in place. */ public static function check_download_folder_protection() { - $upload_dir = wp_upload_dir(); - $downloads_url = $upload_dir['basedir'] . '/woocommerce_uploads'; + $upload_dir = wp_get_upload_dir(); + $downloads_path = $upload_dir['basedir'] . '/woocommerce_uploads'; $download_method = get_option( 'woocommerce_file_download_method' ); + $file_path = $downloads_path . '/.htaccess'; + $file_content = 'redirect' === $download_method ? 'Options -Indexes' : 'deny from all'; + $create = false; - if ( 'redirect' === $download_method ) { - - // Redirect method - don't protect. - if ( file_exists( $downloads_url . '/.htaccess' ) ) { - unlink( $downloads_url . '/.htaccess' ); // @codingStandardsIgnoreLine - } + if ( wp_mkdir_p( $downloads_path ) && ! file_exists( $file_path ) ) { + $create = true; } else { + $current_content = @file_get_contents( $file_path ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents - // Force method - protect, add rules to the htaccess file. - if ( ! file_exists( $downloads_url . '/.htaccess' ) ) { - $file_handle = @fopen( $downloads_url . '/.htaccess', 'w' ); // @codingStandardsIgnoreLine - if ( $file_handle ) { - fwrite( $file_handle, 'deny from all' ); // @codingStandardsIgnoreLine - fclose( $file_handle ); // @codingStandardsIgnoreLine - } + if ( $current_content !== $file_content ) { + unlink( $file_path ); + $create = true; + } + } + + if ( $create ) { + $file_handle = @fopen( $file_path, 'wb' ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_read_fopen + if ( $file_handle ) { + fwrite( $file_handle, $file_content ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fwrite + fclose( $file_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fclose } } } diff --git a/includes/admin/class-wc-admin-status.php b/includes/admin/class-wc-admin-status.php index be40b97270a..23e670ec8d7 100644 --- a/includes/admin/class-wc-admin-status.php +++ b/includes/admin/class-wc-admin-status.php @@ -339,6 +339,33 @@ class WC_Admin_Status { } } + /** + * Prints table info if a base table is not present. + */ + private static function output_tables_info() { + $missing_tables = WC_Install::verify_base_tables( false ); + if ( 0 === count( $missing_tables ) ) { + return; + } + ?> + +
          + + + + + + 1 ? $version_parts[0] : $raw_version; + + // Add WP 5.3+ compatibility class. + if ( $raw_version && version_compare( $version, '5.3', '>=' ) ) { + $classes .= ' wc-wp-version-gte-53'; + } + + return $classes; + } } return new WC_Admin(); diff --git a/includes/admin/helper/class-wc-helper-api.php b/includes/admin/helper/class-wc-helper-api.php index d47b64395c9..e1baf489000 100644 --- a/includes/admin/helper/class-wc-helper-api.php +++ b/includes/admin/helper/class-wc-helper-api.php @@ -97,10 +97,11 @@ class WC_Helper_API { $args['headers'] = array(); } - $args['headers'] = array( + $headers = array( 'Authorization' => 'Bearer ' . $auth['access_token'], 'X-Woo-Signature' => $signature, ); + $args['headers'] = wp_parse_args( $headers, $args['headers'] ); $url = add_query_arg( array( @@ -139,6 +140,19 @@ class WC_Helper_API { return self::request( $endpoint, $args ); } + /** + * Wrapper for self::request(). + * + * @param string $endpoint The helper API endpoint to request. + * @param array $args Arguments passed to wp_remote_request(). + * + * @return array The response object from wp_safe_remote_request(). + */ + public static function put( $endpoint, $args = array() ) { + $args['method'] = 'PUT'; + return self::request( $endpoint, $args ); + } + /** * Using the API base, form a request URL from a given endpoint. * diff --git a/includes/admin/helper/class-wc-helper.php b/includes/admin/helper/class-wc-helper.php index e131b8e52e5..40beb7e9493 100644 --- a/includes/admin/helper/class-wc-helper.php +++ b/includes/admin/helper/class-wc-helper.php @@ -471,6 +471,7 @@ class WC_Helper { if ( $wc_screen_id . '_page_wc-addons' === $screen_id && isset( $_GET['section'] ) && 'helper' === $_GET['section'] ) { wp_enqueue_style( 'woocommerce-helper', WC()->plugin_url() . '/assets/css/helper.css', array(), Constants::get_constant( 'WC_VERSION' ) ); + wp_style_add_data( 'woocommerce-helper', 'rtl', 'replace' ); } } @@ -1149,9 +1150,18 @@ class WC_Helper { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } - // Reset plugin cache before retrieving plugin list. - wp_clean_plugins_cache(); - $plugins = get_plugins(); + $plugins = get_plugins(); + + /** + * Check if plugins have WC headers, if not then clear cache and fetch again. + * WC Headers will not be present if `wc_enable_wc_plugin_headers` hook was added after a `get_plugins` call -- for example when WC is activated/updated. + * Also, get_plugins call is expensive so we should clear this cache very conservatively. + */ + if ( ! empty( $plugins ) && ! array_key_exists( 'Woo', current( $plugins ) ) ) { + wp_clean_plugins_cache( false ); + $plugins = get_plugins(); + } + $woo_plugins = array(); // Backwards compatibility for woothemes_queue_update(). @@ -1469,8 +1479,6 @@ class WC_Helper { $screen = get_current_screen(); $screen_id = $screen ? $screen->id : ''; - self::_prompt_helper_connect( $screen_id ); - if ( 'update-core' !== $screen_id ) { return; } @@ -1487,56 +1495,6 @@ class WC_Helper { } } - /** - * Prompt a Helper connection if the user has WooCommerce.com extensions. - * - * @param string $screen_id Current screen ID. - */ - private static function _prompt_helper_connect( $screen_id ) { - if ( apply_filters( 'woocommerce_helper_suppress_connect_notice', false ) ) { - return; - } - - $screens = wc_get_screen_ids(); - $screens[] = 'plugins'; - - if ( ! in_array( $screen_id, $screens, true ) ) { - return; - } - - // Don't show the notice on the Helper screens. - $screen_addons = sanitize_title( __( 'WooCommerce', 'woocommerce' ) ) . '_page_wc-addons'; - - if ( $screen_addons === $screen_id && ! empty( $_REQUEST['section'] ) && 'helper' === $_REQUEST['section'] ) { - return; - } - - // We believe we have an active connection. - $auth = WC_Helper_Options::get( 'auth' ); - if ( ! empty( $auth['access_token'] ) ) { - return; - } - - $active_plugins = apply_filters( 'active_plugins', get_option( 'active_plugins' ) ); - if ( empty( $active_plugins ) ) { - return; - } - - $woo_plugins = self::get_local_woo_plugins(); - if ( empty( $woo_plugins ) ) { - return; - } - - $active_woo_plugins = array_intersect_key( $woo_plugins, array_flip( $active_plugins ) ); - - if ( count( $active_woo_plugins ) > 0 ) { - /* translators: %s: helper screen url */ - $notice = __( 'Connect your store to WooCommerce.com to receive extensions updates and support.', 'woocommerce' ); - $notice = sprintf( $notice, admin_url( 'admin.php?page=wc-addons§ion=helper' ) ); - echo '

          ' . wp_kses_post( $notice ) . '

          '; - } - } - /** * Get an update notice if one or more Woo extensions has an update available. * diff --git a/includes/admin/importers/class-wc-product-csv-importer-controller.php b/includes/admin/importers/class-wc-product-csv-importer-controller.php index 22b70555917..5a87ec9ae50 100644 --- a/includes/admin/importers/class-wc-product-csv-importer-controller.php +++ b/includes/admin/importers/class-wc-product-csv-importer-controller.php @@ -319,6 +319,7 @@ class WC_Product_CSV_Importer_Controller { return new WP_Error( 'woocommerce_product_csv_importer_upload_file_empty', __( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini or by post_max_size being defined as smaller than upload_max_filesize in php.ini.', 'woocommerce' ) ); } + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated if ( ! self::is_file_valid_csv( wc_clean( wp_unslash( $_FILES['import']['name'] ) ), false ) ) { return new WP_Error( 'woocommerce_product_csv_importer_upload_file_invalid', __( 'Invalid file type. The importer supports CSV and TXT file formats.', 'woocommerce' ) ); } @@ -327,7 +328,7 @@ class WC_Product_CSV_Importer_Controller { 'test_form' => false, 'mimes' => self::get_valid_csv_filetypes(), ); - $import = $_FILES['import']; // WPCS: sanitization ok, input var ok. + $import = $_FILES['import']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.ValidatedSanitizedInput.MissingUnslash $upload = wp_handle_upload( $import, $overrides ); if ( isset( $upload['error'] ) ) { @@ -577,14 +578,15 @@ class WC_Product_CSV_Importer_Controller { $headers = array(); foreach ( $raw_headers as $key => $field ) { - $field = strtolower( $field ); + $normalized_field = strtolower( $field ); $index = $num_indexes ? $key : $field; - $headers[ $index ] = $field; + $headers[ $index ] = $normalized_field; - if ( isset( $default_columns[ $field ] ) ) { - $headers[ $index ] = $default_columns[ $field ]; + if ( isset( $default_columns[ $normalized_field ] ) ) { + $headers[ $index ] = $default_columns[ $normalized_field ]; } else { foreach ( $special_columns as $regex => $special_key ) { + // Don't use the normalized field in the regex since meta might be case-sensitive. if ( preg_match( $regex, $field, $matches ) ) { $headers[ $index ] = $special_key . $matches[1]; break; @@ -619,7 +621,7 @@ class WC_Product_CSV_Importer_Controller { * @return string */ protected function sanitize_special_column_name_regex( $value ) { - return '/' . str_replace( array( '%d', '%s' ), '(.*)', trim( quotemeta( $value ) ) ) . '/'; + return '/' . str_replace( array( '%d', '%s' ), '(.*)', trim( quotemeta( $value ) ) ) . '/i'; } /** diff --git a/includes/admin/importers/views/html-product-csv-import-form.php b/includes/admin/importers/views/html-product-csv-import-form.php index 0d925979476..f7e44815c11 100644 --- a/includes/admin/importers/views/html-product-csv-import-form.php +++ b/includes/admin/importers/views/html-product-csv-import-form.php @@ -12,7 +12,7 @@ if ( ! defined( 'ABSPATH' ) ) {

          -

          +

          diff --git a/includes/admin/list-tables/class-wc-admin-list-table-products.php b/includes/admin/list-tables/class-wc-admin-list-table-products.php index f864efa4e4d..8ac403273d5 100644 --- a/includes/admin/list-tables/class-wc-admin-list-table-products.php +++ b/includes/admin/list-tables/class-wc-admin-list-table-products.php @@ -351,7 +351,7 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table { */ protected function render_products_type_filter() { $current_product_type = isset( $_REQUEST['product_type'] ) ? wc_clean( wp_unslash( $_REQUEST['product_type'] ) ) : false; // WPCS: input var ok, sanitization ok. - $output = ''; foreach ( wc_get_product_types() as $value => $label ) { $output .= ''; $output .= ''; } } diff --git a/includes/admin/meta-boxes/class-wc-meta-box-coupon-data.php b/includes/admin/meta-boxes/class-wc-meta-box-coupon-data.php index 243e6d1411c..c8b92d10e2a 100644 --- a/includes/admin/meta-boxes/class-wc-meta-box-coupon-data.php +++ b/includes/admin/meta-boxes/class-wc-meta-box-coupon-data.php @@ -194,7 +194,7 @@ class WC_Meta_Box_Coupon_Data { foreach ( $product_ids as $product_id ) { $product = wc_get_product( $product_id ); if ( is_object( $product ) ) { - echo ''; + echo ''; } } ?> @@ -212,7 +212,7 @@ class WC_Meta_Box_Coupon_Data { foreach ( $product_ids as $product_id ) { $product = wc_get_product( $product_id ); if ( is_object( $product ) ) { - echo ''; + echo ''; } } ?> diff --git a/includes/admin/meta-boxes/class-wc-meta-box-order-data.php b/includes/admin/meta-boxes/class-wc-meta-box-order-data.php index 62d929b2670..f5568ddb2d1 100644 --- a/includes/admin/meta-boxes/class-wc-meta-box-order-data.php +++ b/includes/admin/meta-boxes/class-wc-meta-box-order-data.php @@ -404,9 +404,9 @@ class WC_Meta_Box_Order_Data { } if ( ! $found_method && ! empty( $payment_method ) ) { - echo ''; + echo ''; } else { - echo ''; + echo ''; } ?> diff --git a/includes/admin/meta-boxes/class-wc-meta-box-product-data.php b/includes/admin/meta-boxes/class-wc-meta-box-product-data.php index a98b0f6c654..7bbbab50ab2 100644 --- a/includes/admin/meta-boxes/class-wc-meta-box-product-data.php +++ b/includes/admin/meta-boxes/class-wc-meta-box-product-data.php @@ -244,7 +244,7 @@ class WC_Meta_Box_Product_Data { continue; } $attribute_id = 0; - $attribute_name = wc_clean( $attribute_names[ $i ] ); + $attribute_name = wc_clean( esc_html( $attribute_names[ $i ] ) ); if ( 'pa_' === substr( $attribute_name, 0, 3 ) ) { $attribute_id = wc_attribute_taxonomy_id_by_name( $attribute_name ); @@ -257,7 +257,7 @@ class WC_Meta_Box_Product_Data { $options = wp_parse_id_list( $options ); } else { // Terms or text sent in textarea. - $options = 0 < $attribute_id ? wc_sanitize_textarea( wc_sanitize_term_text_based( $options ) ) : wc_sanitize_textarea( $options ); + $options = 0 < $attribute_id ? wc_sanitize_textarea( esc_html( wc_sanitize_term_text_based( $options ) ) ) : wc_sanitize_textarea( esc_html( $options ) ); $options = wc_get_text_attributes( $options ); } diff --git a/includes/admin/meta-boxes/views/html-product-attribute.php b/includes/admin/meta-boxes/views/html-product-attribute.php index d4a7910f2b1..2b987fce19d 100644 --- a/includes/admin/meta-boxes/views/html-product-attribute.php +++ b/includes/admin/meta-boxes/views/html-product-attribute.php @@ -49,7 +49,7 @@ if ( ! defined( 'ABSPATH' ) ) { foreach ( $all_terms as $term ) { $options = $attribute->get_options(); $options = ! empty( $options ) ? $options : array(); - echo ''; + echo ''; } } ?> diff --git a/includes/admin/meta-boxes/views/html-product-data-linked-products.php b/includes/admin/meta-boxes/views/html-product-data-linked-products.php index dfbdd2d17d2..2a7a0938db9 100644 --- a/includes/admin/meta-boxes/views/html-product-data-linked-products.php +++ b/includes/admin/meta-boxes/views/html-product-data-linked-products.php @@ -19,7 +19,7 @@ defined( 'ABSPATH' ) || exit; foreach ( $product_ids as $product_id ) { $product = wc_get_product( $product_id ); if ( is_object( $product ) ) { - echo ''; + echo ''; } } ?> @@ -37,7 +37,7 @@ defined( 'ABSPATH' ) || exit; foreach ( $product_ids as $product_id ) { $product = wc_get_product( $product_id ); if ( is_object( $product ) ) { - echo ''; + echo ''; } } ?> @@ -53,7 +53,7 @@ defined( 'ABSPATH' ) || exit; foreach ( $product_ids as $product_id ) { $product = wc_get_product( $product_id ); if ( is_object( $product ) ) { - echo ''; + echo ''; } } ?> diff --git a/includes/admin/notes/class-wc-notes-run-db-update.php b/includes/admin/notes/class-wc-notes-run-db-update.php index d3bb683559c..6611f62b6dd 100644 --- a/includes/admin/notes/class-wc-notes-run-db-update.php +++ b/includes/admin/notes/class-wc-notes-run-db-update.php @@ -48,12 +48,22 @@ class WC_Notes_Run_Db_Update { } catch ( Exception $e ) { return; } - $note_ids = $data_store->get_notes_with_name( self::NOTE_NAME ); + $note_ids = $data_store->get_notes_with_name( self::NOTE_NAME ); if ( empty( $note_ids ) ) { return; } + if ( count( $note_ids ) > 1 ) { + // Remove weird duplicates. Leave the first one. + $current_notice = array_shift( $note_ids ); + foreach ( $note_ids as $note_id ) { + $note = new WC_Admin_Note( $note_id ); + $data_store->delete( $note ); + } + return $current_notice; + } + return current( $note_ids ); } @@ -79,14 +89,15 @@ class WC_Notes_Run_Db_Update { * - actions are set up for the first 'Update database' notice, and * - URL for note's action is equal to the given URL (to check for potential nonce update). * - * @param WC_Admin_Note $note Note to check. - * @param string $update_url URL to check the note against. + * @param WC_Admin_Note $note Note to check. + * @param string $update_url URL to check the note against. + * @param array( string ) $current_actions List of actions to check for. * @return bool */ - private static function note_up_to_date( $note, $update_url ) { + private static function note_up_to_date( $note, $update_url, $current_actions ) { $actions = $note->get_actions(); - if ( 2 === count( array_intersect( wp_list_pluck( $actions, 'name' ), array( 'update-db_run', 'update-db_learn-more' ) ) ) - && in_array( $update_url, wp_list_pluck( $actions, 'query' ) ) ) { + if ( count( $current_actions ) === count( array_intersect( wp_list_pluck( $actions, 'name' ), $current_actions ) ) + && in_array( $update_url, wp_list_pluck( $actions, 'query' ), true ) ) { return true; } @@ -110,6 +121,23 @@ class WC_Notes_Run_Db_Update { ) ); + $note_actions = array( + array( + 'name' => 'update-db_run', + 'label' => __( 'Update WooCommerce Database', 'woocommerce' ), + 'url' => $update_url, + 'status' => 'unactioned', + 'primary' => true, + ), + array( + 'name' => 'update-db_learn-more', + 'label' => __( 'Learn more about updates', 'woocommerce' ), + 'url' => 'https://docs.woocommerce.com/document/how-to-update-woocommerce/', + 'status' => 'unactioned', + 'primary' => false, + ), + ); + if ( $note_id ) { $note = new WC_Admin_Note( $note_id ); } else { @@ -117,7 +145,7 @@ class WC_Notes_Run_Db_Update { } // Check if the note needs to be updated (e.g. expired nonce or different note type stored in the previous run). - if ( self::note_up_to_date( $note, $update_url ) ) { + if ( self::note_up_to_date( $note, $update_url, wp_list_pluck( $note_actions, 'name' ) ) ) { return $note_id; } @@ -128,7 +156,6 @@ class WC_Notes_Run_Db_Update { . sprintf( ' ' . esc_html__( 'The database update process runs in the background and may take a little while, so please be patient. Advanced users can alternatively update via %1$sWP CLI%2$s.', 'woocommerce' ), '', '' ) ); $note->set_type( WC_Admin_Note::E_WC_ADMIN_NOTE_UPDATE ); - $note->set_icon( 'info' ); $note->set_name( self::NOTE_NAME ); $note->set_content_data( (object) array() ); $note->set_source( 'woocommerce-core' ); @@ -138,20 +165,9 @@ class WC_Notes_Run_Db_Update { // Set new actions. $note->clear_actions(); - $note->add_action( - 'update-db_run', - __( 'Update WooCommerce Database', 'woocommerce' ), - $update_url, - 'unactioned', - true - ); - $note->add_action( - 'update-db_learn-more', - __( 'Learn more about updates', 'woocommerce' ), - 'https://docs.woocommerce.com/document/how-to-update-woocommerce/', - 'unactioned', - false - ); + foreach ( $note_actions as $note_action ) { + $note->add_action( ...array_values( $note_action ) ); + } return $note->save(); } @@ -164,7 +180,7 @@ class WC_Notes_Run_Db_Update { * @param int $note_id Note id to update. */ private static function update_in_progress_notice( $note_id ) { - // Same actions as in includes/admin/views/html-notice-updating.php. + // Same actions as in includes/admin/views/html-notice-updating.php. This just redirects, performs no action, so without nonce. $pending_actions_url = admin_url( 'admin.php?page=wc-status&tab=action-scheduler&s=woocommerce_run_update&status=pending' ); $cron_disabled = Constants::is_true( 'DISABLE_WP_CRON' ); $cron_cta = $cron_disabled ? __( 'You can manually run queued updates here.', 'woocommerce' ) : __( 'View progress →', 'woocommerce' ); @@ -205,89 +221,81 @@ class WC_Notes_Run_Db_Update { ) ); + $note_actions = array( + array( + 'name' => 'update-db_done', + 'label' => __( 'Thanks!', 'woocommerce' ), + 'url' => $hide_notices_url, + 'status' => 'actioned', + 'primary' => true, + ), + ); + $note = new WC_Admin_Note( $note_id ); + + // Check if the note needs to be updated (e.g. expired nonce or different note type stored in the previous run). + if ( self::note_up_to_date( $note, $hide_notices_url, wp_list_pluck( $note_actions, 'name' ) ) ) { + return $note_id; + } + $note->set_title( __( 'WooCommerce database update done', 'woocommerce' ) ); $note->set_content( __( 'WooCommerce database update complete. Thank you for updating to the latest version!', 'woocommerce' ) ); - $actions = $note->get_actions(); - if ( ! in_array( 'update-db_done', wp_list_pluck( $actions, 'name' ) ) ) { - $note->clear_actions(); - $note->add_action( - 'update-db_done', - __( 'Thanks!', 'woocommerce' ), - $hide_notices_url, - 'actioned', - true - ); - - $note->save(); - } - } - - /** - * Return true if db update notice should be shown, false otherwise. - * - * If the db needs an update, the notice should be always shown. - * If the db does not need an update, but the notice has *not* been actioned (i.e. after the db update, when - * store owner hasn't acknowledged the successful db update), still show the notice. - * If the db does not need an update, and the notice has been actioned, then notice should *not* be shown. - * The same is true if the db does not need an update and the notice does not exist. - * - * @return bool - */ - private static function should_show_notice() { - if ( ! \WC_Install::needs_db_update() ) { - try { - $data_store = \WC_Data_Store::load( 'admin-note' ); - } catch ( Exception $e ) { - // Bail out in case of incorrect use. - return false; - } - $note_ids = $data_store->get_notes_with_name( self::NOTE_NAME ); - - if ( ! empty( $note_ids ) ) { - // Db update not needed && note actioned -> don't show it. - $note = new WC_Admin_Note( $note_ids[0] ); - if ( $note::E_WC_ADMIN_NOTE_ACTIONED === $note->get_status() ) { - return false; - } - } else { - // Db update not needed && note does not exist -> don't show it. - return false; - } + $note->clear_actions(); + foreach ( $note_actions as $note_action ) { + $note->add_action( ...array_values( $note_action ) ); } - return true; + $note->save(); } /** * Prepare the correct content of the db update note to be displayed by WC Admin. * * This one gets called on each page load, so try to bail quickly. + * + * If the db needs an update, the notice should be always shown. + * If the db does not need an update, but the notice has *not* been actioned (i.e. after the db update, when + * store owner hasn't acknowledged the successful db update), still show the Thanks notice. + * If the db does not need an update, and the notice has been actioned, then notice should *not* be shown. + * The notice should also be hidden if the db does not need an update and the notice does not exist. */ public static function show_reminder() { - if ( ! self::should_show_notice() ) { - return; - } + $needs_db_update = \WC_Install::needs_db_update(); $note_id = self::get_current_notice(); + if ( ! $needs_db_update ) { + // Db update not needed && note does not exist -> don't show it. + if ( ! $note_id ) { + return; + } - if ( \WC_Install::needs_db_update() && empty( $note_id ) ) { - // Db needs update && no notice exists -> create one. - $note_id = self::update_needed_notice(); - } - - if ( \WC_Install::needs_db_update() ) { - $next_scheduled_date = WC()->queue()->get_next( 'woocommerce_run_update_callback', null, 'woocommerce-db-updates' ); - - if ( $next_scheduled_date || ! empty( $_GET['do_update_woocommerce'] ) ) { // WPCS: input var ok, CSRF ok. - self::update_in_progress_notice( $note_id ); + $note = new WC_Admin_Note( $note_id ); + if ( $note::E_WC_ADMIN_NOTE_ACTIONED === $note->get_status() ) { + // Db update not needed && note actioned -> don't show it. + return; } else { - self::update_needed_notice( $note_id ); + // Db update not needed && notice is unactioned -> Thank you note. + \WC_Install::update_db_version(); + self::update_done_notice( $note_id ); + return; } } else { - \WC_Install::update_db_version(); - self::update_done_notice( $note_id ); + // Db needs update &&. + if ( ! $note_id ) { + // Db needs update && no notice exists -> create one that shows Nudge to update. + $note_id = self::update_needed_notice(); + } + + $next_scheduled_date = WC()->queue()->get_next( 'woocommerce_run_update_callback', null, 'woocommerce-db-updates' ); + + if ( $next_scheduled_date || ! empty( $_GET['do_update_woocommerce'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended + // Db needs update && db update is scheduled -> update note to In progress. + self::update_in_progress_notice( $note_id ); + } else { + // Db needs update && db update is not scheduled -> Nudge to run the db update. + self::update_needed_notice( $note_id ); + } } } diff --git a/includes/admin/plugin-updates/class-wc-plugin-updates.php b/includes/admin/plugin-updates/class-wc-plugin-updates.php index fb838c726fa..fa64bcce0b4 100644 --- a/includes/admin/plugin-updates/class-wc-plugin-updates.php +++ b/includes/admin/plugin-updates/class-wc-plugin-updates.php @@ -45,13 +45,6 @@ class WC_Plugin_Updates { */ protected $major_untested_plugins = array(); - /** - * Array of plugins lacking testing with the minor version. - * - * @var array - */ - protected $minor_untested_plugins = array(); - /** * Common JS for initializing and managing thickbox-based modals. */ @@ -103,29 +96,6 @@ class WC_Plugin_Updates { | Methods for getting messages. */ - /** - * Get the inline warning notice for minor version updates. - * - * @return string - */ - protected function get_extensions_inline_warning_minor() { - $upgrade_type = 'minor'; - $plugins = ! empty( $this->major_untested_plugins ) ? array_diff_key( $this->minor_untested_plugins, $this->major_untested_plugins ) : $this->minor_untested_plugins; - $version_parts = explode( '.', $this->new_version ); - $new_version = $version_parts[0] . '.' . $version_parts[1]; - - if ( empty( $plugins ) ) { - return; - } - - /* translators: %s: version number */ - $message = sprintf( __( "Heads up! The versions of the following plugins you're running haven't been tested with the latest version of WooCommerce (%s).", 'woocommerce' ), $new_version ); - - ob_start(); - include 'views/html-notice-untested-extensions-inline.php'; - return ob_get_clean(); - } - /** * Get the inline warning notice for major version updates. * diff --git a/includes/admin/plugin-updates/class-wc-plugins-screen-updates.php b/includes/admin/plugin-updates/class-wc-plugins-screen-updates.php index f544f408582..a7a048db15a 100644 --- a/includes/admin/plugin-updates/class-wc-plugins-screen-updates.php +++ b/includes/admin/plugin-updates/class-wc-plugins-screen-updates.php @@ -45,7 +45,6 @@ class WC_Plugins_Screen_Updates extends WC_Plugin_Updates { $this->new_version = $response->new_version; $this->upgrade_notice = $this->get_upgrade_notice( $response->new_version ); $this->major_untested_plugins = $this->get_untested_plugins( $response->new_version, 'major' ); - $this->minor_untested_plugins = $this->get_untested_plugins( $response->new_version, 'minor' ); $current_version_parts = explode( '.', Constants::get_constant( 'WC_VERSION' ) ); $new_version_parts = explode( '.', $this->new_version ); @@ -59,10 +58,6 @@ class WC_Plugins_Screen_Updates extends WC_Plugin_Updates { $this->upgrade_notice .= $this->get_extensions_inline_warning_major(); } - if ( ! empty( $this->minor_untested_plugins ) ) { - $this->upgrade_notice .= $this->get_extensions_inline_warning_minor(); - } - if ( ! empty( $this->major_untested_plugins ) ) { $this->upgrade_notice .= $this->get_extensions_modal_warning(); add_action( 'admin_print_footer_scripts', array( $this, 'plugin_screen_modal_js' ) ); diff --git a/includes/admin/settings/class-wc-settings-advanced.php b/includes/admin/settings/class-wc-settings-advanced.php index 8fbcb5956b6..5056d4fdba8 100644 --- a/includes/admin/settings/class-wc-settings-advanced.php +++ b/includes/admin/settings/class-wc-settings-advanced.php @@ -42,6 +42,7 @@ class WC_Settings_Advanced extends WC_Settings_Page { 'webhooks' => __( 'Webhooks', 'woocommerce' ), 'legacy_api' => __( 'Legacy API', 'woocommerce' ), 'woocommerce_com' => __( 'WooCommerce.com', 'woocommerce' ), + 'features' => __( 'Features', 'woocommerce' ), ); return apply_filters( 'woocommerce_get_sections_' . $this->id, $sections ); @@ -397,6 +398,28 @@ class WC_Settings_Advanced extends WC_Settings_Page { ), ) ); + } elseif ( 'features' === $current_section ) { + $settings = apply_filters( + 'woocommerce_settings_features', + array( + array( + 'title' => __( 'Features', 'woocommerce' ), + 'type' => 'title', + 'desc' => __( 'Start using new features that are being progressively rolled out to improve the store management experience.', 'woocommerce' ), + 'id' => 'features_options', + ), + array( + 'title' => __( 'Home Screen', 'woocommerce' ), + 'desc' => __( 'Displays analytical insights, inbox notifications, and handy shortcuts in a single screen', 'woocommerce' ), + 'id' => 'woocommerce_homescreen_enabled', + 'type' => 'checkbox', + ), + array( + 'type' => 'sectionend', + 'id' => 'features_options', + ), + ) + ); } return apply_filters( 'woocommerce_get_settings_' . $this->id, $settings, $current_section ); diff --git a/includes/admin/settings/class-wc-settings-emails.php b/includes/admin/settings/class-wc-settings-emails.php index 5c5525bafd5..00df3150196 100644 --- a/includes/admin/settings/class-wc-settings-emails.php +++ b/includes/admin/settings/class-wc-settings-emails.php @@ -128,7 +128,7 @@ class WC_Settings_Emails extends WC_Settings_Page { array( 'title' => __( 'Footer text', 'woocommerce' ), /* translators: %s: Available placeholders for use */ - 'desc' => __( 'The text to appear in the footer of all WooCommerce emails.', 'woocommerce' ) . ' ' . sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '{site_title} {site_address}' ), + 'desc' => __( 'The text to appear in the footer of all WooCommerce emails.', 'woocommerce' ) . ' ' . sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '{site_title} {site_url}' ), 'id' => 'woocommerce_email_footer_text', 'css' => 'width:400px; height: 75px;', 'placeholder' => __( 'N/A', 'woocommerce' ), diff --git a/includes/admin/settings/class-wc-settings-shipping.php b/includes/admin/settings/class-wc-settings-shipping.php index f34eb287011..11e66d59a5d 100644 --- a/includes/admin/settings/class-wc-settings-shipping.php +++ b/includes/admin/settings/class-wc-settings-shipping.php @@ -286,7 +286,7 @@ class WC_Settings_Shipping extends WC_Settings_Page { * Show zones */ protected function zones_screen() { - $method_count = wc_get_shipping_method_count(); + $method_count = wc_get_shipping_method_count( false, true ); wp_localize_script( 'wc-shipping-zones', diff --git a/includes/admin/settings/views/html-admin-page-shipping-zone-methods.php b/includes/admin/settings/views/html-admin-page-shipping-zone-methods.php index 4512a0adb41..8bc70e58312 100644 --- a/includes/admin/settings/views/html-admin-page-shipping-zone-methods.php +++ b/includes/admin/settings/views/html-admin-page-shipping-zone-methods.php @@ -189,7 +189,7 @@ if ( ! defined( 'ABSPATH' ) ) { if ( ! $method->supports( 'shipping-zones' ) ) { continue; } - echo '
          - +
          - + @@ -792,7 +799,7 @@ if ( 0 < count( $dropins_mu_plugins['mu_plugins'] ) ) : - + diff --git a/includes/admin/views/html-bulk-edit-product.php b/includes/admin/views/html-bulk-edit-product.php index 125fe1c14f9..5e81412b5bd 100644 --- a/includes/admin/views/html-bulk-edit-product.php +++ b/includes/admin/views/html-bulk-edit-product.php @@ -29,7 +29,7 @@ if ( ! defined( 'ABSPATH' ) ) { '3' => __( 'Decrease existing price by (fixed amount or %):', 'woocommerce' ), ); foreach ( $options as $key => $value ) { - echo ''; + echo ''; } ?> @@ -54,7 +54,7 @@ if ( ! defined( 'ABSPATH' ) ) { '4' => __( 'Set to regular price decreased by (fixed amount or %):', 'woocommerce' ), ); foreach ( $options as $key => $value ) { - echo ''; + echo ''; } ?> @@ -78,7 +78,7 @@ if ( ! defined( 'ABSPATH' ) ) { 'none' => _x( 'None', 'Tax status', 'woocommerce' ), ); foreach ( $options as $key => $value ) { - echo ''; + echo ''; } ?> @@ -104,7 +104,7 @@ if ( ! defined( 'ABSPATH' ) ) { } foreach ( $options as $key => $value ) { - echo ''; + echo ''; } ?> @@ -124,7 +124,7 @@ if ( ! defined( 'ABSPATH' ) ) { '1' => __( 'Change to:', 'woocommerce' ), ); foreach ( $options as $key => $value ) { - echo ''; + echo ''; } ?> @@ -148,7 +148,7 @@ if ( ! defined( 'ABSPATH' ) ) { '1' => __( 'Change to:', 'woocommerce' ), ); foreach ( $options as $key => $value ) { - echo ''; + echo ''; } ?> @@ -170,7 +170,7 @@ if ( ! defined( 'ABSPATH' ) ) { $value ) { - echo ''; + echo ''; } ?> @@ -190,7 +190,7 @@ if ( ! defined( 'ABSPATH' ) ) { 'hidden' => __( 'Hidden', 'woocommerce' ), ); foreach ( $options as $key => $value ) { - echo ''; + echo ''; } ?> @@ -207,7 +207,7 @@ if ( ! defined( 'ABSPATH' ) ) { 'no' => __( 'No', 'woocommerce' ), ); foreach ( $options as $key => $value ) { - echo ''; + echo ''; } ?> @@ -222,7 +222,7 @@ if ( ! defined( 'ABSPATH' ) ) { echo ''; foreach ( wc_get_product_stock_status_options() as $key => $value ) { - echo ''; + echo ''; } ?> @@ -241,7 +241,7 @@ if ( ! defined( 'ABSPATH' ) ) { 'no' => __( 'No', 'woocommerce' ), ); foreach ( $options as $key => $value ) { - echo ''; + echo ''; } ?> @@ -261,7 +261,7 @@ if ( ! defined( 'ABSPATH' ) ) { '3' => __( 'Decrease existing stock by:', 'woocommerce' ), ); foreach ( $options as $key => $value ) { - echo ''; + echo ''; } ?> @@ -280,7 +280,7 @@ if ( ! defined( 'ABSPATH' ) ) { echo ''; foreach ( wc_get_product_backorder_options() as $key => $value ) { - echo ''; + echo ''; } ?> diff --git a/includes/admin/views/html-notice-base-table-missing.php b/includes/admin/views/html-notice-base-table-missing.php new file mode 100644 index 00000000000..1a8859b122c --- /dev/null +++ b/includes/admin/views/html-notice-base-table-missing.php @@ -0,0 +1,43 @@ + +
          + + + + +

          + +

          +

          + Check again.', 'woocommerce' ), + esc_html( implode( ', ', $missing_tables ) ), + wp_nonce_url( admin_url( 'admin.php?page=wc-status&tab=tools&action=verify_db_tables' ), 'debug_action' ) + ) + ); + } else { + echo wp_kses_post( + sprintf( + /* translators: %1%s: Missing tables (seperated by ",") */ + __( 'One or more tables required for WooCommerce to function are missing, some features may not work as expected. Missing tables: %1$s.', 'woocommerce' ), + esc_html( implode( ', ', $missing_tables ) ) + ) + ); + } + ?> +

          +
          diff --git a/includes/admin/views/html-notice-uploads-directory-is-unprotected.php b/includes/admin/views/html-notice-uploads-directory-is-unprotected.php new file mode 100644 index 00000000000..a4fd291f7ca --- /dev/null +++ b/includes/admin/views/html-notice-uploads-directory-is-unprotected.php @@ -0,0 +1,29 @@ + +
          + + +

          + browsable via the web. We strongly recommend configuring your web server to prevent directory indexing.', 'woocommerce' ), + esc_url( $uploads['baseurl'] . '/woocommerce_uploads' ), + 'https://docs.woocommerce.com/document/digital-downloadable-product-handling/#protecting-your-uploads-directory' + ) + ); + ?> +

          +
          diff --git a/includes/admin/wc-admin-functions.php b/includes/admin/wc-admin-functions.php index 288f34bec07..57b9b31cb6b 100644 --- a/includes/admin/wc-admin-functions.php +++ b/includes/admin/wc-admin-functions.php @@ -137,7 +137,7 @@ function wc_create_page( $slug, $option = '', $page_title = '', $page_content = /** * Output admin fields. * - * Loops though the woocommerce options array and outputs each field. + * Loops through the woocommerce options array and outputs each field. * * @param array $options Opens array to output. */ diff --git a/includes/class-wc-cart.php b/includes/class-wc-cart.php index 17378bfbf1b..4ca59ad0885 100644 --- a/includes/class-wc-cart.php +++ b/includes/class-wc-cart.php @@ -765,7 +765,6 @@ class WC_Cart extends WC_Legacy_Cart { public function check_cart_item_stock() { $error = new WP_Error(); $product_qty_in_cart = $this->get_cart_item_quantities(); - $hold_stock_minutes = (int) get_option( 'woocommerce_hold_stock_minutes', 0 ); $current_session_order_id = isset( WC()->session->order_awaiting_payment ) ? absint( WC()->session->order_awaiting_payment ) : 0; foreach ( $this->get_cart() as $cart_item_key => $values ) { @@ -784,7 +783,7 @@ class WC_Cart extends WC_Legacy_Cart { } // Check stock based on all items in the cart and consider any held stock within pending orders. - $held_stock = ( $hold_stock_minutes > 0 ) ? wc_get_held_stock_quantity( $product, $current_session_order_id ) : 0; + $held_stock = wc_get_held_stock_quantity( $product, $current_session_order_id ); $required_stock = $product_qty_in_cart[ $product->get_stock_managed_by_id() ]; if ( $product->get_stock_quantity() < ( $held_stock + $required_stock ) ) { diff --git a/includes/class-wc-checkout.php b/includes/class-wc-checkout.php index 3a05d107527..6645d1f06cf 100644 --- a/includes/class-wc-checkout.php +++ b/includes/class-wc-checkout.php @@ -388,12 +388,30 @@ class WC_Checkout { // Save the order. $order_id = $order->save(); + /** + * Action hook fired after an order is created used to add custom meta to the order. + * + * @since 3.0.0 + */ do_action( 'woocommerce_checkout_update_order_meta', $order_id, $data ); + /** + * Action hook fired after an order is created. + * + * @since 4.3.0 + */ + do_action( 'woocommerce_checkout_order_created', $order ); + return $order_id; } catch ( Exception $e ) { if ( $order && $order instanceof WC_Order ) { $order->get_data_store()->release_held_coupons( $order ); + /** + * Action hook fired when an order is discarded due to Exception. + * + * @since 4.3.0 + */ + do_action( 'woocommerce_checkout_order_exception', $order ); } return new WP_Error( 'checkout-error', $e->getMessage() ); } @@ -748,14 +766,14 @@ class WC_Checkout { /* translators: %s: field name */ $postcode_validation_notice = sprintf( __( '%s is not a valid postcode / ZIP.', 'woocommerce' ), '' . esc_html( $field_label ) . '' ); } - $errors->add( 'validation', apply_filters( 'woocommerce_checkout_postcode_validation_notice', $postcode_validation_notice, $country, $data[ $key ] ), array( 'id' => $key ) ); + $errors->add( $key . '_validation', apply_filters( 'woocommerce_checkout_postcode_validation_notice', $postcode_validation_notice, $country, $data[ $key ] ), array( 'id' => $key ) ); } } if ( in_array( 'phone', $format, true ) ) { if ( $validate_fieldset && '' !== $data[ $key ] && ! WC_Validation::is_phone( $data[ $key ] ) ) { /* translators: %s: phone number */ - $errors->add( 'validation', sprintf( __( '%s is not a valid phone number.', 'woocommerce' ), '' . esc_html( $field_label ) . '' ), array( 'id' => $key ) ); + $errors->add( $key . '_validation', sprintf( __( '%s is not a valid phone number.', 'woocommerce' ), '' . esc_html( $field_label ) . '' ), array( 'id' => $key ) ); } } @@ -765,7 +783,7 @@ class WC_Checkout { if ( $validate_fieldset && ! $email_is_valid ) { /* translators: %s: email address */ - $errors->add( 'validation', sprintf( __( '%s is not a valid email address.', 'woocommerce' ), '' . esc_html( $field_label ) . '' ), array( 'id' => $key ) ); + $errors->add( $key . '_validation', sprintf( __( '%s is not a valid email address.', 'woocommerce' ), '' . esc_html( $field_label ) . '' ), array( 'id' => $key ) ); continue; } } @@ -785,14 +803,14 @@ class WC_Checkout { if ( $validate_fieldset && ! in_array( $data[ $key ], $valid_state_values, true ) ) { /* translators: 1: state field 2: valid states */ - $errors->add( 'validation', sprintf( __( '%1$s is not valid. Please enter one of the following: %2$s', 'woocommerce' ), '' . esc_html( $field_label ) . '', implode( ', ', $valid_states ) ), array( 'id' => $key ) ); + $errors->add( $key . '_validation', sprintf( __( '%1$s is not valid. Please enter one of the following: %2$s', 'woocommerce' ), '' . esc_html( $field_label ) . '', implode( ', ', $valid_states ) ), array( 'id' => $key ) ); } } } if ( $validate_fieldset && $required && '' === $data[ $key ] ) { /* translators: %s: field name */ - $errors->add( 'required-field', apply_filters( 'woocommerce_checkout_required_field_notice', sprintf( __( '%s is a required field.', 'woocommerce' ), '' . esc_html( $field_label ) . '' ), $field_label ), array( 'id' => $key ) ); + $errors->add( $key . '_required', apply_filters( 'woocommerce_checkout_required_field_notice', sprintf( __( '%s is a required field.', 'woocommerce' ), '' . esc_html( $field_label ) . '' ), $field_label ), array( 'id' => $key ) ); } } } diff --git a/includes/class-wc-comments.php b/includes/class-wc-comments.php index d39bb7b0a85..ab4e6945f01 100644 --- a/includes/class-wc-comments.php +++ b/includes/class-wc-comments.php @@ -146,7 +146,7 @@ class WC_Comments { */ public static function check_comment_rating( $comment_data ) { // If posting a comment (not trackback etc) and not logged in. - if ( ! is_admin() && isset( $_POST['comment_post_ID'], $_POST['rating'], $comment_data['comment_type'] ) && 'product' === get_post_type( absint( $_POST['comment_post_ID'] ) ) && empty( $_POST['rating'] ) && '' === $comment_data['comment_type'] && wc_review_ratings_enabled() && wc_review_ratings_required() ) { // WPCS: input var ok, CSRF ok. + if ( ! is_admin() && isset( $_POST['comment_post_ID'], $_POST['rating'], $comment_data['comment_type'] ) && 'product' === get_post_type( absint( $_POST['comment_post_ID'] ) ) && empty( $_POST['rating'] ) && self::is_default_comment_type( $comment_data['comment_type'] ) && wc_review_ratings_enabled() && wc_review_ratings_required() ) { // WPCS: input var ok, CSRF ok. wp_die( esc_html__( 'Please rate the product.', 'woocommerce' ) ); exit; } @@ -406,12 +406,26 @@ class WC_Comments { * @return array */ public static function update_comment_type( $comment_data ) { - if ( ! is_admin() && isset( $_POST['comment_post_ID'], $comment_data['comment_type'] ) && '' === $comment_data['comment_type'] && 'product' === get_post_type( absint( $_POST['comment_post_ID'] ) ) ) { // WPCS: input var ok, CSRF ok. + if ( ! is_admin() && isset( $_POST['comment_post_ID'], $comment_data['comment_type'] ) && self::is_default_comment_type( $comment_data['comment_type'] ) && 'product' === get_post_type( absint( $_POST['comment_post_ID'] ) ) ) { // WPCS: input var ok, CSRF ok. $comment_data['comment_type'] = 'review'; } return $comment_data; } + + /** + * Determines if a comment is of the default type. + * + * Prior to WordPress 5.5, '' was the default comment type. + * As of 5.5, the default type is 'comment'. + * + * @since 4.3.0 + * @param string $comment_type Comment type. + * @return bool + */ + private static function is_default_comment_type( $comment_type ) { + return ( '' === $comment_type || 'comment' === $comment_type ); + } } WC_Comments::init(); diff --git a/includes/class-wc-countries.php b/includes/class-wc-countries.php index fb8e34c69ee..7c0bb934c7c 100644 --- a/includes/class-wc-countries.php +++ b/includes/class-wc-countries.php @@ -474,7 +474,7 @@ class WC_Countries { echo ' selected="selected"'; } - echo '>' . esc_html( $value ) . ' — ' . ( $escape ? esc_js( $state_value ) : $state_value ) . ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo '>' . esc_html( $value ) . ' — ' . ( $escape ? esc_html( $state_value ) : $state_value ) . ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } echo ''; @@ -483,7 +483,7 @@ class WC_Countries { if ( $selected_country === $key && '*' === $selected_state ) { echo ' selected="selected"'; } - echo ' value="' . esc_attr( $key ) . '">' . ( $escape ? esc_js( $value ) : $value ) . ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo ' value="' . esc_attr( $key ) . '">' . ( $escape ? esc_html( $value ) : $value ) . ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } } @@ -910,6 +910,7 @@ class WC_Countries { ), 'state' => array( 'required' => false, + 'hidden' => true, ), ), 'DK' => array( @@ -918,6 +919,7 @@ class WC_Countries { ), 'state' => array( 'required' => false, + 'hidden' => true, ), ), 'EE' => array( @@ -944,6 +946,14 @@ class WC_Countries { 'required' => false, ), ), + 'GH' => array( + 'postcode' => array( + 'required' => false, + ), + 'state' => array( + 'label' => __( 'Region', 'woocommerce' ), + ), + ), 'GP' => array( 'state' => array( 'required' => false, @@ -1229,6 +1239,7 @@ class WC_Countries { ), 'state' => array( 'required' => false, + 'hidden' => true, ), ), 'TR' => array( diff --git a/includes/class-wc-emails.php b/includes/class-wc-emails.php index 3edef5e03f3..2d2f4d24c8d 100644 --- a/includes/class-wc-emails.php +++ b/includes/class-wc-emails.php @@ -290,12 +290,14 @@ class WC_Emails { array( '{site_title}', '{site_address}', + '{site_url}', '{woocommerce}', '{WooCommerce}', ), array( $this->get_blogname(), $domain, + $domain, 'WooCommerce', 'WooCommerce', ), diff --git a/includes/class-wc-form-handler.php b/includes/class-wc-form-handler.php index 3565b642a6b..80a4336aba5 100644 --- a/includes/class-wc-form-handler.php +++ b/includes/class-wc-form-handler.php @@ -459,6 +459,10 @@ class WC_Form_Handler { return; } + if ( ! apply_filters( 'woocommerce_add_payment_method_form_is_valid', true ) ) { + return; + } + // Test rate limit. $current_user_id = get_current_user_id(); $rate_limit_id = 'add_payment_method_' . $current_user_id; @@ -466,12 +470,15 @@ class WC_Form_Handler { if ( WC_Rate_Limiter::retried_too_soon( $rate_limit_id ) ) { wc_add_notice( - /* translators: %d number of seconds */ - _n( - 'You cannot add a new payment method so soon after the previous one. Please wait for %d second.', - 'You cannot add a new payment method so soon after the previous one. Please wait for %d seconds.', - $delay, - 'woocommerce' + sprintf( + /* translators: %d number of seconds */ + _n( + 'You cannot add a new payment method so soon after the previous one. Please wait for %d second.', + 'You cannot add a new payment method so soon after the previous one. Please wait for %d seconds.', + $delay, + 'woocommerce' + ), + $delay ), 'error' ); @@ -862,11 +869,12 @@ class WC_Form_Handler { */ private static function add_to_cart_handler_variable( $product_id ) { try { - $variation_id = empty( $_REQUEST['variation_id'] ) ? '' : absint( wp_unslash( $_REQUEST['variation_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended - $quantity = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( wp_unslash( $_REQUEST['quantity'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended - $missing_attributes = array(); - $variations = array(); - $adding_to_cart = wc_get_product( $product_id ); + $variation_id = empty( $_REQUEST['variation_id'] ) ? '' : absint( wp_unslash( $_REQUEST['variation_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended + $quantity = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( wp_unslash( $_REQUEST['quantity'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended + $missing_attributes = array(); + $variations = array(); + $variation_attributes = array(); + $adding_to_cart = wc_get_product( $product_id ); if ( ! $adding_to_cart ) { return false; @@ -874,6 +882,9 @@ class WC_Form_Handler { // If the $product_id was in fact a variation ID, update the variables. if ( $adding_to_cart->is_type( 'variation' ) ) { + $variation_attributes = $adding_to_cart->get_variation_attributes(); + // Filter out 'any' variations, which are empty, as they need to be explicitly specified while adding to cart. + $variation_attributes = array_filter( $variation_attributes ); $variation_id = $product_id; $product_id = $adding_to_cart->get_parent_id(); $adding_to_cart = wc_get_product( $product_id ); @@ -904,6 +915,9 @@ class WC_Form_Handler { } } + // Merge variation attributes and posted attributes. + $posted_and_variation_attributes = array_merge( $variation_attributes, $posted_attributes ); + // If no variation ID is set, attempt to get a variation ID from posted attributes. if ( empty( $variation_id ) ) { $data_store = WC_Data_Store::load( 'product' ); @@ -932,8 +946,8 @@ class WC_Form_Handler { * * If no attribute was posted, only error if the variation has an 'any' attribute which requires a value. */ - if ( isset( $posted_attributes[ $attribute_key ] ) ) { - $value = $posted_attributes[ $attribute_key ]; + if ( isset( $posted_and_variation_attributes[ $attribute_key ] ) ) { + $value = $posted_and_variation_attributes[ $attribute_key ]; // Allow if valid or show error. if ( $valid_value === $value ) { diff --git a/includes/class-wc-install.php b/includes/class-wc-install.php index a219d7d8323..409a5567de4 100644 --- a/includes/class-wc-install.php +++ b/includes/class-wc-install.php @@ -287,6 +287,7 @@ class WC_Install { WC()->wpdb_table_fix(); self::remove_admin_notices(); self::create_tables(); + self::verify_base_tables(); self::create_options(); self::create_roles(); self::setup_environment(); @@ -296,6 +297,7 @@ class WC_Install { self::maybe_enable_setup_wizard(); self::update_wc_version(); self::maybe_update_db_version(); + self::maybe_enable_homescreen(); delete_transient( 'wc_installing' ); @@ -303,6 +305,54 @@ class WC_Install { do_action( 'woocommerce_installed' ); } + /** + * Check if all the base tables are present. + * + * @param bool $modify_notice Whether to modify notice based on if all tables are present. + * @param bool $execute Whether to execute get_schema queries as well. + * + * @return array List of querues. + */ + public static function verify_base_tables( $modify_notice = true, $execute = false ) { + require_once ABSPATH . 'wp-admin/includes/upgrade.php'; + + if ( $execute ) { + self::create_tables(); + } + $queries = dbDelta( self::get_schema(), false ); + $missing_tables = array(); + foreach ( $queries as $table_name => $result ) { + if ( "Created table $table_name" === $result ) { + $missing_tables[] = $table_name; + } + } + + if ( 0 < count( $missing_tables ) ) { + if ( $modify_notice ) { + WC_Admin_Notices::add_notice( 'base_tables_missing' ); + } + update_option( 'woocommerce_schema_missing_tables', $missing_tables ); + } else { + if ( $modify_notice ) { + WC_Admin_Notices::remove_notice( 'base_tables_missing' ); + } + update_option( 'woocommerce_schema_version', WC()->db_version ); + delete_option( 'woocommerce_schema_missing_tables' ); + } + return $missing_tables; + } + + /** + * Check if the homepage should be enabled and set the appropriate option if thats the case. + * + * @since 4.3.0 + */ + private static function maybe_enable_homescreen() { + if ( self::is_new_install() && ! get_option( 'woocommerce_homescreen_enabled' ) ) { + add_option( 'woocommerce_homescreen_enabled', 'yes' ); + } + } + /** * Reset any notices added to admin. * @@ -621,6 +671,11 @@ class WC_Install { /** * Set up the database tables which the plugin needs to function. + * WARNING: If you are modifying this method, make sure that its safe to call regardless of the state of database. + * + * This is called from `install` method and is executed in-sync when WC is installed or updated. This can also be called optionally from `verify_base_tables`. + * + * TODO: Add all crucial tables that we have created from workers in the past. * * Tables: * woocommerce_attribute_taxonomies - Table for storing attribute taxonomies - these are user defined @@ -946,6 +1001,14 @@ CREATE TABLE {$wpdb->prefix}wc_tax_rate_classes ( slug varchar(200) NOT NULL DEFAULT '', PRIMARY KEY (tax_rate_class_id), UNIQUE KEY slug (slug($max_index_length)) +) $collate; +CREATE TABLE {$wpdb->prefix}wc_reserved_stock ( + `order_id` bigint(20) NOT NULL, + `product_id` bigint(20) NOT NULL, + `stock_quantity` double NOT NULL DEFAULT 0, + `timestamp` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `expires` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`order_id`, `product_id`) ) $collate; "; @@ -980,6 +1043,7 @@ CREATE TABLE {$wpdb->prefix}wc_tax_rate_classes ( "{$wpdb->prefix}woocommerce_shipping_zones", "{$wpdb->prefix}woocommerce_tax_rate_locations", "{$wpdb->prefix}woocommerce_tax_rates", + "{$wpdb->prefix}wc_reserved_stock", ); /** @@ -1187,7 +1251,7 @@ CREATE TABLE {$wpdb->prefix}wc_tax_rate_classes ( } // Install files and folders for uploading files and prevent hotlinking. - $upload_dir = wp_upload_dir(); + $upload_dir = wp_get_upload_dir(); $download_method = get_option( 'woocommerce_file_download_method', 'force' ); $files = array( @@ -1206,19 +1270,16 @@ CREATE TABLE {$wpdb->prefix}wc_tax_rate_classes ( 'file' => 'index.html', 'content' => '', ), - ); - - if ( 'redirect' !== $download_method ) { - $files[] = array( + array( 'base' => $upload_dir['basedir'] . '/woocommerce_uploads', 'file' => '.htaccess', - 'content' => 'deny from all', - ); - } + 'content' => 'redirect' === $download_method ? 'Options -Indexes' : 'deny from all', + ), + ); foreach ( $files as $file ) { if ( wp_mkdir_p( $file['base'] ) && ! file_exists( trailingslashit( $file['base'] ) . $file['file'] ) ) { - $file_handle = @fopen( trailingslashit( $file['base'] ) . $file['file'], 'w' ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_read_fopen + $file_handle = @fopen( trailingslashit( $file['base'] ) . $file['file'], 'wb' ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_read_fopen if ( $file_handle ) { fwrite( $file_handle, $file['content'] ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fwrite fclose( $file_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fclose diff --git a/includes/class-wc-order.php b/includes/class-wc-order.php index b2ab190c506..a43455d2fcb 100644 --- a/includes/class-wc-order.php +++ b/includes/class-wc-order.php @@ -419,6 +419,19 @@ class WC_Order extends WC_Abstract_Order { | */ + /** + * Get basic order data in array format. + * + * @return array + */ + public function get_base_data() { + return array_merge( + array( 'id' => $this->get_id() ), + $this->data, + array( 'number' => $this->get_order_number() ) + ); + } + /** * Get all class data in array format. * @@ -427,12 +440,8 @@ class WC_Order extends WC_Abstract_Order { */ public function get_data() { return array_merge( + $this->get_base_data(), array( - 'id' => $this->get_id(), - ), - $this->data, - array( - 'number' => $this->get_order_number(), 'meta_data' => $this->get_meta_data(), 'line_items' => $this->get_items( 'line_item' ), 'tax_lines' => $this->get_items( 'tax' ), diff --git a/includes/class-wc-post-types.php b/includes/class-wc-post-types.php index 7de16656db5..ab9dcbc07d2 100644 --- a/includes/class-wc-post-types.php +++ b/includes/class-wc-post-types.php @@ -59,6 +59,7 @@ class WC_Post_Types { 'query_var' => is_admin(), 'rewrite' => false, 'public' => false, + 'label' => _x( 'Product type', 'Taxonomy name', 'woocommerce' ), ) ) ); @@ -75,6 +76,7 @@ class WC_Post_Types { 'query_var' => is_admin(), 'rewrite' => false, 'public' => false, + 'label' => _x( 'Product visibility', 'Taxonomy name', 'woocommerce' ), ) ) ); diff --git a/includes/class-wc-privacy-exporters.php b/includes/class-wc-privacy-exporters.php index 7d519c2f0a1..b248de85d83 100644 --- a/includes/class-wc-privacy-exporters.php +++ b/includes/class-wc-privacy-exporters.php @@ -27,10 +27,11 @@ class WC_Privacy_Exporters { $customer_personal_data = self::get_customer_personal_data( $user ); if ( ! empty( $customer_personal_data ) ) { $data_to_export[] = array( - 'group_id' => 'woocommerce_customer', - 'group_label' => __( 'Customer Data', 'woocommerce' ), - 'item_id' => 'user', - 'data' => $customer_personal_data, + 'group_id' => 'woocommerce_customer', + 'group_label' => __( 'Customer Data', 'woocommerce' ), + 'group_description' => __( 'User’s WooCommerce customer data.', 'woocommerce' ), + 'item_id' => 'user', + 'data' => $customer_personal_data, ); } } @@ -71,10 +72,11 @@ class WC_Privacy_Exporters { if ( 0 < count( $orders ) ) { foreach ( $orders as $order ) { $data_to_export[] = array( - 'group_id' => 'woocommerce_orders', - 'group_label' => __( 'Orders', 'woocommerce' ), - 'item_id' => 'order-' . $order->get_id(), - 'data' => self::get_order_personal_data( $order ), + 'group_id' => 'woocommerce_orders', + 'group_label' => __( 'Orders', 'woocommerce' ), + 'group_description' => __( 'User’s WooCommerce orders data.', 'woocommerce' ), + 'item_id' => 'order-' . $order->get_id(), + 'data' => self::get_order_personal_data( $order ), ); } $done = 10 > count( $orders ); @@ -118,22 +120,24 @@ class WC_Privacy_Exporters { if ( 0 < count( $downloads ) ) { foreach ( $downloads as $download ) { $data_to_export[] = array( - 'group_id' => 'woocommerce_downloads', + 'group_id' => 'woocommerce_downloads', /* translators: This is the headline for a list of downloads purchased from the store for a given user. */ - 'group_label' => __( 'Purchased Downloads', 'woocommerce' ), - 'item_id' => 'download-' . $download->get_id(), - 'data' => self::get_download_personal_data( $download ), + 'group_label' => __( 'Purchased Downloads', 'woocommerce' ), + 'group_description' => __( 'User’s WooCommerce purchased downloads data.', 'woocommerce' ), + 'item_id' => 'download-' . $download->get_id(), + 'data' => self::get_download_personal_data( $download ), ); $download_logs = $customer_download_log_data_store->get_download_logs_for_permission( $download->get_id() ); foreach ( $download_logs as $download_log ) { $data_to_export[] = array( - 'group_id' => 'woocommerce_download_logs', + 'group_id' => 'woocommerce_download_logs', /* translators: This is the headline for a list of access logs for downloads purchased from the store for a given user. */ - 'group_label' => __( 'Access to Purchased Downloads', 'woocommerce' ), - 'item_id' => 'download-log-' . $download_log->get_id(), - 'data' => array( + 'group_label' => __( 'Access to Purchased Downloads', 'woocommerce' ), + 'group_description' => __( 'User’s WooCommerce access to purchased downloads data.', 'woocommerce' ), + 'item_id' => 'download-log-' . $download_log->get_id(), + 'data' => array( array( 'name' => __( 'Download ID', 'woocommerce' ), 'value' => $download_log->get_permission_id(), @@ -413,10 +417,11 @@ class WC_Privacy_Exporters { if ( 0 < count( $tokens ) ) { foreach ( $tokens as $token ) { $data_to_export[] = array( - 'group_id' => 'woocommerce_tokens', - 'group_label' => __( 'Payment Tokens', 'woocommerce' ), - 'item_id' => 'token-' . $token->get_id(), - 'data' => array( + 'group_id' => 'woocommerce_tokens', + 'group_label' => __( 'Payment Tokens', 'woocommerce' ), + 'group_description' => __( 'User’s WooCommerce payment tokens data.', 'woocommerce' ), + 'item_id' => 'token-' . $token->get_id(), + 'data' => array( array( 'name' => __( 'Token', 'woocommerce' ), 'value' => $token->get_display_name(), diff --git a/includes/class-wc-privacy.php b/includes/class-wc-privacy.php index 516b24ff638..5ffed57c6f3 100644 --- a/includes/class-wc-privacy.php +++ b/includes/class-wc-privacy.php @@ -66,12 +66,10 @@ class WC_Privacy extends WC_Abstract_Privacy { * @since 3.4.0 */ public function get_privacy_message() { - $content = ' -
          ' . - '

          ' . - __( 'This sample language includes the basics around what personal data your store may be collecting, storing and sharing, as well as who may have access to that data. Depending on what settings are enabled and which additional plugins are used, the specific information shared by your store will vary. We recommend consulting with a lawyer when deciding what information to disclose on your privacy policy.', 'woocommerce' ) . - '

          ' . - '
          ' . + $content = '
          ' . + '

          ' . + __( 'This sample language includes the basics around what personal data your store may be collecting, storing and sharing, as well as who may have access to that data. Depending on what settings are enabled and which additional plugins are used, the specific information shared by your store will vary. We recommend consulting with a lawyer when deciding what information to disclose on your privacy policy.', 'woocommerce' ) . + '

          ' . '

          ' . __( 'We collect information about you during the checkout process on our store.', 'woocommerce' ) . '

          ' . '

          ' . __( 'What we collect and store', 'woocommerce' ) . '

          ' . '

          ' . __( 'While you visit our site, we’ll track:', 'woocommerce' ) . '

          ' . @@ -81,9 +79,9 @@ class WC_Privacy extends WC_Abstract_Privacy { '
        • ' . __( 'Shipping address: we’ll ask you to enter this so we can, for instance, estimate shipping before you place an order, and send you the order!', 'woocommerce' ) . '
        • ' . '' . '

          ' . __( 'We’ll also use cookies to keep track of cart contents while you’re browsing our site.', 'woocommerce' ) . '

          ' . - '
          ' . - '

          ' . __( 'Note: you may want to further detail your cookie policy, and link to that section from here.', 'woocommerce' ) . '

          ' . - '
          ' . + '

          ' . + __( 'Note: you may want to further detail your cookie policy, and link to that section from here.', 'woocommerce' ) . + '

          ' . '

          ' . __( 'When you purchase from us, we’ll ask you to provide information including your name, billing address, shipping address, email address, phone number, credit card/payment details and optional account information like username and password. We’ll use this information for purposes, such as, to:', 'woocommerce' ) . '

          ' . '
            ' . '
          • ' . __( 'Send you information about your account and order', 'woocommerce' ) . '
          • ' . @@ -105,16 +103,17 @@ class WC_Privacy extends WC_Abstract_Privacy { '
          ' . '

          ' . __( 'Our team members have access to this information to help fulfill orders, process refunds and support you.', 'woocommerce' ) . '

          ' . '

          ' . __( 'What we share with others', 'woocommerce' ) . '

          ' . - '
          ' . - '

          ' . __( 'In this section you should list who you’re sharing data with, and for what purpose. This could include, but may not be limited to, analytics, marketing, payment gateways, shipping providers, and third party embeds.', 'woocommerce' ) . '

          ' . - '
          ' . + '

          ' . + __( 'In this section you should list who you’re sharing data with, and for what purpose. This could include, but may not be limited to, analytics, marketing, payment gateways, shipping providers, and third party embeds.', 'woocommerce' ) . + '

          ' . '

          ' . __( 'We share information with third parties who help us provide our orders and store services to you; for example --', 'woocommerce' ) . '

          ' . '

          ' . __( 'Payments', 'woocommerce' ) . '

          ' . - '
          ' . - '

          ' . __( 'In this subsection you should list which third party payment processors you’re using to take payments on your store since these may handle customer data. We’ve included PayPal as an example, but you should remove this if you’re not using PayPal.', 'woocommerce' ) . '

          ' . - '
          ' . + '

          ' . + __( 'In this subsection you should list which third party payment processors you’re using to take payments on your store since these may handle customer data. We’ve included PayPal as an example, but you should remove this if you’re not using PayPal.', 'woocommerce' ) . + '

          ' . '

          ' . __( 'We accept payments through PayPal. When processing payments, some of your data will be passed to PayPal, including information required to process or support the payment, such as the purchase total and billing information.', 'woocommerce' ) . '

          ' . - '

          ' . __( 'Please see the PayPal Privacy Policy for more details.', 'woocommerce' ) . '

          '; + '

          ' . __( 'Please see the PayPal Privacy Policy for more details.', 'woocommerce' ) . '

          ' . + '
          '; return apply_filters( 'wc_privacy_policy_content', $content ); } diff --git a/includes/class-wc-shipping.php b/includes/class-wc-shipping.php index 8027b84a693..a803c400f2f 100644 --- a/includes/class-wc-shipping.php +++ b/includes/class-wc-shipping.php @@ -332,7 +332,26 @@ class WC_Shipping { if ( ! is_array( $stored_rates ) || $package_hash !== $stored_rates['package_hash'] || 'yes' === get_option( 'woocommerce_shipping_debug_mode', 'no' ) ) { foreach ( $this->load_shipping_methods( $package ) as $shipping_method ) { if ( ! $shipping_method->supports( 'shipping-zones' ) || $shipping_method->get_instance_id() ) { - $package['rates'] = $package['rates'] + $shipping_method->get_rates_for_package( $package ); // + instead of array_merge maintains numeric keys + /** + * Fires before getting shipping rates for a package. + * + * @since 4.3.0 + * @param array $package Package of cart items. + * @param WC_Shipping_Method $shipping_method Shipping method instance. + */ + do_action( 'woocommerce_before_get_rates_for_package', $package, $shipping_method ); + + // Use + instead of array_merge to maintain numeric keys. + $package['rates'] = $package['rates'] + $shipping_method->get_rates_for_package( $package ); + + /** + * Fires after getting shipping rates for a package. + * + * @since 4.3.0 + * @param array $package Package of cart items. + * @param WC_Shipping_Method $shipping_method Shipping method instance. + */ + do_action( 'woocommerce_after_get_rates_for_package', $package, $shipping_method ); } } diff --git a/includes/class-wc-tax.php b/includes/class-wc-tax.php index 53b9cabc18a..a7784c3e702 100644 --- a/includes/class-wc-tax.php +++ b/includes/class-wc-tax.php @@ -495,7 +495,7 @@ class WC_Tax { ); } - return apply_filters( 'woocommerce_matched_rates', $matched_tax_rates, $tax_class ); + return apply_filters( 'woocommerce_matched_rates', $matched_tax_rates, $tax_class, $customer ); } /** diff --git a/includes/class-woocommerce.php b/includes/class-woocommerce.php index f5acc2122c2..42c78cd5c9e 100644 --- a/includes/class-woocommerce.php +++ b/includes/class-woocommerce.php @@ -20,7 +20,16 @@ final class WooCommerce { * * @var string */ - public $version = '4.1.0'; + public $version = '4.3.0'; + + /** + * WooCommerce Schema version. + * + * @since 4.3 started with version string 430. + * + * @var string + */ + public $db_version = '430'; /** * The single instance of the class. @@ -229,7 +238,7 @@ final class WooCommerce { $this->define( 'WC_LOG_DIR', $upload_dir['basedir'] . '/wc-logs/' ); $this->define( 'WC_SESSION_CACHE_GROUP', 'wc_session_id' ); $this->define( 'WC_TEMPLATE_DEBUG_MODE', false ); - $this->define( 'WC_NOTICE_MIN_PHP_VERSION', '7.0' ); + $this->define( 'WC_NOTICE_MIN_PHP_VERSION', '7.2' ); $this->define( 'WC_NOTICE_MIN_WP_VERSION', '5.2' ); $this->define( 'WC_PHP_MIN_REQUIREMENTS_NOTICE', 'wp_php_min_requirements_' . WC_NOTICE_MIN_PHP_VERSION . '_' . WC_NOTICE_MIN_WP_VERSION ); } @@ -246,6 +255,7 @@ final class WooCommerce { 'order_itemmeta' => 'woocommerce_order_itemmeta', 'wc_product_meta_lookup' => 'wc_product_meta_lookup', 'wc_tax_rate_classes' => 'wc_tax_rate_classes', + 'wc_reserved_stock' => 'wc_reserved_stock', ); foreach ( $tables as $name => $table ) { diff --git a/includes/data-stores/class-wc-coupon-data-store-cpt.php b/includes/data-stores/class-wc-coupon-data-store-cpt.php index 4590a24c086..dab16bfc1b9 100644 --- a/includes/data-stores/class-wc-coupon-data-store-cpt.php +++ b/includes/data-stores/class-wc-coupon-data-store-cpt.php @@ -69,7 +69,9 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat * @param WC_Coupon $coupon Coupon object. */ public function create( &$coupon ) { - $coupon->set_date_created( time() ); + if ( ! $coupon->get_date_created( 'edit' ) ) { + $coupon->set_date_created( time() ); + } $coupon_id = wp_insert_post( apply_filters( diff --git a/includes/data-stores/class-wc-product-data-store-cpt.php b/includes/data-stores/class-wc-product-data-store-cpt.php index 6c2baf5afff..e417c1d9c6a 100644 --- a/includes/data-stores/class-wc-product-data-store-cpt.php +++ b/includes/data-stores/class-wc-product-data-store-cpt.php @@ -881,8 +881,8 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da $outofstock_where = ' AND exclude_join.object_id IS NULL'; } + // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared return $wpdb->get_results( - // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared " SELECT posts.ID as id, posts.post_parent as parent_id FROM {$wpdb->posts} AS posts @@ -900,8 +900,8 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da ) GROUP BY posts.ID " - // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared ); + // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared } /** @@ -1603,7 +1603,7 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da foreach ( $search_terms as $search_term ) { $like = '%' . $wpdb->esc_like( $search_term ) . '%'; - $term_group_query .= $wpdb->prepare( " {$searchand} ( ( posts.post_title LIKE %s) OR ( posts.post_excerpt LIKE %s) OR ( posts.post_content LIKE %s ) OR ( wc_product_meta_lookup.sku LIKE %s ) )", $like, $like, $like, $like ); // @codingStandardsIgnoreLine. + $term_group_query .= $wpdb->prepare( " {$searchand} ( ( posts.post_title LIKE %s) OR ( posts.post_excerpt LIKE %s) OR ( posts.post_content LIKE %s ) OR ( wc_product_meta_lookup.sku LIKE %s ) )", $like, $like, $like, $like ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared $searchand = ' AND '; } @@ -2062,4 +2062,23 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da } return ''; } + + /** + * Returns query statement for getting current `_stock` of a product. + * + * @internal MAX function below is used to make sure result is a scalar. + * @param int $product_id Product ID. + * @return string|void Query statement. + */ + public function get_query_for_stock( $product_id ) { + global $wpdb; + return $wpdb->prepare( + " + SELECT COALESCE ( MAX( meta_value ), 0 ) FROM $wpdb->postmeta as meta_table + WHERE meta_table.meta_key = '_stock' + AND meta_table.post_id = %d + ", + $product_id + ); + } } diff --git a/includes/data-stores/class-wc-shipping-zone-data-store.php b/includes/data-stores/class-wc-shipping-zone-data-store.php index e4a55322bef..453ec877f15 100644 --- a/includes/data-stores/class-wc-shipping-zone-data-store.php +++ b/includes/data-stores/class-wc-shipping-zone-data-store.php @@ -282,7 +282,7 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin "SELECT zones.zone_id FROM {$wpdb->prefix}woocommerce_shipping_zones as zones LEFT OUTER JOIN {$wpdb->prefix}woocommerce_shipping_zone_locations as locations ON zones.zone_id = locations.zone_id AND location_type != 'postcode' WHERE " . implode( ' ', $criteria ) // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared - . ' ORDER BY zone_order ASC, zone_id ASC LIMIT 1' + . ' ORDER BY zone_order ASC, zones.zone_id ASC LIMIT 1' ); } diff --git a/includes/emails/class-wc-email-customer-invoice.php b/includes/emails/class-wc-email-customer-invoice.php index 320509cb7a9..a1973bfbc3e 100644 --- a/includes/emails/class-wc-email-customer-invoice.php +++ b/includes/emails/class-wc-email-customer-invoice.php @@ -112,7 +112,7 @@ if ( ! class_exists( 'WC_Email_Customer_Invoice', false ) ) : * @return string */ public function get_default_additional_content() { - return __( 'Thanks for using {site_address}!', 'woocommerce' ); + return __( 'Thanks for using {site_url}!', 'woocommerce' ); } /** diff --git a/includes/emails/class-wc-email-customer-processing-order.php b/includes/emails/class-wc-email-customer-processing-order.php index 589f4a7359c..42fc858c038 100644 --- a/includes/emails/class-wc-email-customer-processing-order.php +++ b/includes/emails/class-wc-email-customer-processing-order.php @@ -141,7 +141,7 @@ if ( ! class_exists( 'WC_Email_Customer_Processing_Order', false ) ) : * @return string */ public function get_default_additional_content() { - return __( 'Thanks for using {site_address}!', 'woocommerce' ); + return __( 'Thanks for using {site_url}!', 'woocommerce' ); } } diff --git a/includes/emails/class-wc-email.php b/includes/emails/class-wc-email.php index e98e185fcd2..a16abe1a252 100644 --- a/includes/emails/class-wc-email.php +++ b/includes/emails/class-wc-email.php @@ -233,6 +233,7 @@ class WC_Email extends WC_Settings_API { array( '{site_title}' => $this->get_blogname(), '{site_address}' => wp_parse_url( home_url(), PHP_URL_HOST ), + '{site_url}' => wp_parse_url( home_url(), PHP_URL_HOST ), ), $this->placeholders ); diff --git a/includes/export/class-wc-product-csv-exporter.php b/includes/export/class-wc-product-csv-exporter.php index 78c92c9f857..53b7242251f 100644 --- a/includes/export/class-wc-product-csv-exporter.php +++ b/includes/export/class-wc-product-csv-exporter.php @@ -656,10 +656,10 @@ class WC_Product_CSV_Exporter extends WC_CSV_Batch_Exporter { if ( 0 === strpos( $attribute_name, 'pa_' ) ) { $option_term = get_term_by( 'slug', $attribute, $attribute_name ); // @codingStandardsIgnoreLine. - $row[ 'attributes:value' . $i ] = $option_term && ! is_wp_error( $option_term ) ? str_replace( ',', '\\,', $option_term->name ) : $attribute; + $row[ 'attributes:value' . $i ] = $option_term && ! is_wp_error( $option_term ) ? str_replace( ',', '\\,', $option_term->name ) : str_replace( ',', '\\,', $attribute ); $row[ 'attributes:taxonomy' . $i ] = 1; } else { - $row[ 'attributes:value' . $i ] = $attribute; + $row[ 'attributes:value' . $i ] = str_replace( ',', '\\,', $attribute ); $row[ 'attributes:taxonomy' . $i ] = 0; } diff --git a/includes/import/class-wc-product-csv-importer.php b/includes/import/class-wc-product-csv-importer.php index 14eddea04a1..06a8bb3e8bc 100644 --- a/includes/import/class-wc-product-csv-importer.php +++ b/includes/import/class-wc-product-csv-importer.php @@ -400,21 +400,22 @@ class WC_Product_CSV_Importer extends WC_Product_Importer { $total = count( $_terms ); foreach ( $_terms as $index => $_term ) { - // Check if category exists. Parent must be empty string or null if doesn't exists. - $term = term_exists( $_term, 'product_cat', $parent ); - - if ( is_array( $term ) ) { - $term_id = $term['term_id']; - // Don't allow users without capabilities to create new categories. - } elseif ( ! current_user_can( 'manage_product_terms' ) ) { + // Don't allow users without capabilities to create new categories. + if ( ! current_user_can( 'manage_product_terms' ) ) { break; - } else { - $term = wp_insert_term( $_term, 'product_cat', array( 'parent' => intval( $parent ) ) ); + } - if ( is_wp_error( $term ) ) { - break; // We cannot continue if the term cannot be inserted. + $term = wp_insert_term( $_term, 'product_cat', array( 'parent' => intval( $parent ) ) ); + + if ( is_wp_error( $term ) ) { + if ( $term->get_error_code() === 'term_exists' ) { + // When term exists, error data should contain existing term id. + $term_id = $term->get_error_data(); + } else { + break; // We cannot continue on any other error. } - + } else { + // New term. $term_id = $term['term_id']; } diff --git a/includes/shortcodes/class-wc-shortcode-checkout.php b/includes/shortcodes/class-wc-shortcode-checkout.php index 6316d07e2f8..31413213a72 100644 --- a/includes/shortcodes/class-wc-shortcode-checkout.php +++ b/includes/shortcodes/class-wc-shortcode-checkout.php @@ -84,9 +84,8 @@ class WC_Shortcode_Checkout { // Pay for existing order. if ( isset( $_GET['pay_for_order'], $_GET['key'] ) && $order_id ) { // WPCS: input var ok, CSRF ok. try { - $order_key = isset( $_GET['key'] ) ? wc_clean( wp_unslash( $_GET['key'] ) ) : ''; // WPCS: input var ok, CSRF ok. - $order = wc_get_order( $order_id ); - $hold_stock_minutes = (int) get_option( 'woocommerce_hold_stock_minutes', 0 ); + $order_key = isset( $_GET['key'] ) ? wc_clean( wp_unslash( $_GET['key'] ) ) : ''; // WPCS: input var ok, CSRF ok. + $order = wc_get_order( $order_id ); // Order or payment link is invalid. if ( ! $order || $order->get_id() !== $order_id || ! hash_equals( $order->get_order_key(), $order_key ) ) { @@ -158,7 +157,7 @@ class WC_Shortcode_Checkout { } // Check stock based on all items in the cart and consider any held stock within pending orders. - $held_stock = ( $hold_stock_minutes > 0 ) ? wc_get_held_stock_quantity( $product, $order->get_id() ) : 0; + $held_stock = wc_get_held_stock_quantity( $product, $order->get_id() ); $required_stock = $quantities[ $product->get_stock_managed_by_id() ]; if ( ! apply_filters( 'woocommerce_pay_order_product_has_enough_stock', ( $product->get_stock_quantity() >= ( $held_stock + $required_stock ) ), $product, $order ) ) { diff --git a/includes/shortcodes/class-wc-shortcode-products.php b/includes/shortcodes/class-wc-shortcode-products.php index 4e31f8418ef..b195676a607 100644 --- a/includes/shortcodes/class-wc-shortcode-products.php +++ b/includes/shortcodes/class-wc-shortcode-products.php @@ -507,7 +507,7 @@ class WC_Shortcode_Products { } /** - * Set product as visible when quering for hidden products. + * Set product as visible when querying for hidden products. * * @since 3.2.0 * @param bool $visibility Product visibility. diff --git a/includes/tracks/class-wc-site-tracking.php b/includes/tracks/class-wc-site-tracking.php index 82697a05791..1890045fd9c 100644 --- a/includes/tracks/class-wc-site-tracking.php +++ b/includes/tracks/class-wc-site-tracking.php @@ -44,17 +44,18 @@ class WC_Site_Tracking { return true; } + /** + * Register scripts required to record events from javascript. + */ + public static function register_scripts() { + wp_register_script( 'woo-tracks', 'https://stats.wp.com/w.js', array( 'wp-hooks' ), gmdate( 'YW' ), false ); + } + /** * Add scripts required to record events from javascript. */ public static function enqueue_scripts() { - - // Add w.js to the page. - wp_enqueue_script( 'woo-tracks', 'https://stats.wp.com/w.js', array( 'wp-hooks' ), gmdate( 'YW' ), false ); - - // Expose tracking via a function in the wcTracks global namespace directly before wc_print_js. - add_filter( 'admin_footer', array( __CLASS__, 'add_tracking_function' ), 24 ); - + wp_enqueue_script( 'woo-tracks' ); } /** @@ -65,7 +66,12 @@ class WC_Site_Tracking { id ) { + // we are on the order listing page, and query results are being shown. + WC_Tracks::record_event( 'orders_view_search' ); + } + + return $order_ids; } /** diff --git a/includes/tracks/events/class-wc-products-tracking.php b/includes/tracks/events/class-wc-products-tracking.php index 3fd0bc6c2a5..577e1d534a2 100644 --- a/includes/tracks/events/class-wc-products-tracking.php +++ b/includes/tracks/events/class-wc-products-tracking.php @@ -17,12 +17,88 @@ class WC_Products_Tracking { * Init tracking. */ public function init() { + add_action( 'load-edit.php', array( $this, 'track_products_view' ), 10 ); + add_action( 'load-edit-tags.php', array( $this, 'track_categories_and_tags_view' ), 10, 2 ); add_action( 'edit_post', array( $this, 'track_product_updated' ), 10, 2 ); add_action( 'transition_post_status', array( $this, 'track_product_published' ), 10, 3 ); add_action( 'created_product_cat', array( $this, 'track_product_category_created' ) ); add_action( 'add_meta_boxes_product', array( $this, 'track_product_updated_client_side' ), 10 ); } + /** + * Send a Tracks event when the Products page is viewed. + */ + public function track_products_view() { + // We only record Tracks event when no `_wp_http_referer` query arg is set, since + // when searching, the request gets sent from the browser twice, + // once with the `_wp_http_referer` and once without it. + // + // Otherwise, we would double-record the view and search events. + + // phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification + if ( + isset( $_GET['post_type'] ) + && 'product' === wp_unslash( $_GET['post_type'] ) + && ! isset( $_GET['_wp_http_referer'] ) + ) { + // phpcs:enable + + WC_Tracks::record_event( 'products_view' ); + + // phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification + if ( + isset( $_GET['s'] ) + && 0 < strlen( sanitize_text_field( wp_unslash( $_GET['s'] ) ) ) + ) { + // phpcs:enable + + WC_Tracks::record_event( 'products_search' ); + } + } + } + + /** + * Send a Tracks event when the Products Categories and Tags page is viewed. + */ + public function track_categories_and_tags_view() { + // We only record Tracks event when no `_wp_http_referer` query arg is set, since + // when searching, the request gets sent from the browser twice, + // once with the `_wp_http_referer` and once without it. + // + // Otherwise, we would double-record the view and search events. + + // phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification + if ( + isset( $_GET['post_type'] ) + && 'product' === wp_unslash( $_GET['post_type'] ) + && isset( $_GET['taxonomy'] ) + && ! isset( $_GET['_wp_http_referer'] ) + ) { + $taxonomy = wp_unslash( $_GET['taxonomy'] ); + // phpcs:enable + + if ( 'product_cat' === $taxonomy ) { + WC_Tracks::record_event( 'categories_view' ); + } elseif ( 'product_tag' === $taxonomy ) { + WC_Tracks::record_event( 'tags_view' ); + } + + // phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification + if ( + isset( $_GET['s'] ) + && 0 < strlen( sanitize_text_field( wp_unslash( $_GET['s'] ) ) ) + ) { + // phpcs:enable + + if ( 'product_cat' === $taxonomy ) { + WC_Tracks::record_event( 'categories_search' ); + } elseif ( 'product_tag' === $taxonomy ) { + WC_Tracks::record_event( 'tags_search' ); + } + } + } + } + /** * Send a Tracks event when a product is updated. * diff --git a/includes/wc-attribute-functions.php b/includes/wc-attribute-functions.php index 3820b107a62..24bbd1ef358 100644 --- a/includes/wc-attribute-functions.php +++ b/includes/wc-attribute-functions.php @@ -185,9 +185,9 @@ function wc_attribute_taxonomy_id_by_name( $name ) { */ function wc_attribute_label( $name, $product = '' ) { if ( taxonomy_is_product_attribute( $name ) ) { - $name = wc_attribute_taxonomy_slug( $name ); + $slug = wc_attribute_taxonomy_slug( $name ); $all_labels = wc_get_attribute_taxonomy_labels(); - $label = isset( $all_labels[ $name ] ) ? $all_labels[ $name ] : $name; + $label = isset( $all_labels[ $slug ] ) ? $all_labels[ $slug ] : $slug; } elseif ( $product ) { if ( $product->is_type( 'variation' ) ) { $product = wc_get_product( $product->get_parent_id() ); diff --git a/includes/wc-cart-functions.php b/includes/wc-cart-functions.php index a6f2755d675..b9f05304c04 100644 --- a/includes/wc-cart-functions.php +++ b/includes/wc-cart-functions.php @@ -318,8 +318,13 @@ function wc_cart_totals_order_total_html() { $taxable_address = WC()->customer->get_taxable_address(); /* translators: %s: country name */ $estimated_text = WC()->customer->is_customer_outside_base() && ! WC()->customer->has_calculated_shipping() ? sprintf( ' ' . __( 'estimated for %s', 'woocommerce' ), WC()->countries->estimated_for_prefix( $taxable_address[0] ) . WC()->countries->countries[ $taxable_address[0] ] ) : ''; - /* translators: %s: tax information */ - $value .= '' . sprintf( __( '(includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) . $estimated_text ) . ''; + $value .= '(' + /* translators: includes tax information */ + . esc_html__( 'includes', 'woocommerce' ) + . ' ' + . wp_kses_post( implode( ', ', $tax_string_array ) ) + . esc_html( $estimated_text ) + . ')'; } } diff --git a/includes/wc-core-functions.php b/includes/wc-core-functions.php index e197a0ea64c..d8a336ee747 100644 --- a/includes/wc-core-functions.php +++ b/includes/wc-core-functions.php @@ -150,6 +150,86 @@ function wc_update_order( $args ) { return wc_create_order( $args ); } +/** + * Given a path, this will convert any of the subpaths into their corresponding tokens. + * + * @since 4.3.0 + * @param string $path The absolute path to tokenize. + * @param array $path_tokens An array keyed with the token, containing paths that should be replaced. + * @return string The tokenized path. + */ +function wc_tokenize_path( $path, $path_tokens ) { + // Order most to least specific so that the token can encompass as much of the path as possible. + uasort( + $path_tokens, + function ( $a, $b ) { + $a = strlen( $a ); + $b = strlen( $b ); + + if ( $a > $b ) { + return -1; + } + + if ( $b > $a ) { + return 1; + } + + return 0; + } + ); + + foreach ( $path_tokens as $token => $token_path ) { + if ( 0 !== strpos( $path, $token_path ) ) { + continue; + } + + $path = str_replace( $token_path, '{{' . $token . '}}', $path ); + } + + return $path; +} + +/** + * Given a tokenized path, this will expand the tokens to their full path. + * + * @since 4.3.0 + * @param string $path The absolute path to expand. + * @param array $path_tokens An array keyed with the token, containing paths that should be expanded. + * @return string The absolute path. + */ +function wc_untokenize_path( $path, $path_tokens ) { + foreach ( $path_tokens as $token => $token_path ) { + $path = str_replace( '{{' . $token . '}}', $token_path, $path ); + } + + return $path; +} + +/** + * Fetches an array containing all of the configurable path constants to be used in tokenization. + * + * @return array The key is the define and the path is the constant. + */ +function wc_get_path_define_tokens() { + $defines = array( + 'ABSPATH', + 'WP_CONTENT_DIR', + 'WP_PLUGIN_DIR', + 'WPMU_PLUGIN_DIR', + 'PLUGINDIR', + 'WP_THEME_DIR', + ); + + $path_tokens = array(); + foreach ( $defines as $define ) { + if ( defined( $define ) ) { + $path_tokens[ $define ] = constant( $define ); + } + } + + return apply_filters( 'woocommerce_get_path_define_tokens', $path_tokens ); +} + /** * Get template part (for templates like the shop-loop). * @@ -187,7 +267,13 @@ function wc_get_template_part( $slug, $name = '' ) { ); } - wp_cache_set( $cache_key, $template, 'woocommerce' ); + // Don't cache the absolute path so that it can be shared between web servers with different paths. + $cache_path = wc_tokenize_path( $template, wc_get_path_define_tokens() ); + + wc_set_template_cache( $cache_key, $cache_path ); + } else { + // Make sure that the absolute path to the template is resolved. + $template = wc_untokenize_path( $template, wc_get_path_define_tokens() ); } // Allow 3rd party plugins to filter template file from their plugin. @@ -212,7 +298,14 @@ function wc_get_template( $template_name, $args = array(), $template_path = '', if ( ! $template ) { $template = wc_locate_template( $template_name, $template_path, $default_path ); - wp_cache_set( $cache_key, $template, 'woocommerce' ); + + // Don't cache the absolute path so that it can be shared between web servers with different paths. + $cache_path = wc_tokenize_path( $template, wc_get_path_define_tokens() ); + + wc_set_template_cache( $cache_key, $cache_path ); + } else { + // Make sure that the absolute path to the template is resolved. + $template = wc_untokenize_path( $template, wc_get_path_define_tokens() ); } // Allow 3rd party plugin filter template file from their plugin. @@ -310,6 +403,42 @@ function wc_locate_template( $template_name, $template_path = '', $default_path return apply_filters( 'woocommerce_locate_template', $template, $template_name, $template_path ); } +/** + * Add a template to the template cache. + * + * @since 4.3.0 + * @param string $cache_key Object cache key. + * @param string $template Located template. + */ +function wc_set_template_cache( $cache_key, $template ) { + wp_cache_set( $cache_key, $template, 'woocommerce' ); + + $cached_templates = wp_cache_get( 'cached_templates', 'woocommerce' ); + if ( is_array( $cached_templates ) ) { + $cached_templates[] = $cache_key; + } else { + $cached_templates = array( $cache_key ); + } + + wp_cache_set( 'cached_templates', $cached_templates, 'woocommerce' ); +} + +/** + * Clear the template cache. + * + * @since 4.3.0 + */ +function wc_clear_template_cache() { + $cached_templates = wp_cache_get( 'cached_templates', 'woocommerce' ); + if ( is_array( $cached_templates ) ) { + foreach ( $cached_templates as $cache_key ) { + wp_cache_delete( $cache_key, 'woocommerce' ); + } + + wp_cache_delete( 'cached_templates', 'woocommerce' ); + } +} + /** * Get Base Currency Code. * @@ -1493,9 +1622,12 @@ function wc_postcode_location_matcher( $postcode, $objects, $object_id_key, $obj * * @since 2.6.0 * @param bool $include_legacy Count legacy shipping methods too. + * @param bool $enabled_only Whether non-legacy shipping methods should be + * restricted to enabled ones. It doesn't affect + * legacy shipping methods. @since 4.3.0. * @return int */ -function wc_get_shipping_method_count( $include_legacy = false ) { +function wc_get_shipping_method_count( $include_legacy = false, $enabled_only = false ) { global $wpdb; $transient_name = $include_legacy ? 'wc_shipping_method_count_legacy' : 'wc_shipping_method_count'; @@ -1506,7 +1638,8 @@ function wc_get_shipping_method_count( $include_legacy = false ) { return absint( $transient_value['value'] ); } - $method_count = absint( $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}woocommerce_shipping_zone_methods" ) ); + $where_clause = $enabled_only ? 'WHERE is_enabled=1' : ''; + $method_count = absint( $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}woocommerce_shipping_zone_methods ${where_clause}" ) ); if ( $include_legacy ) { // Count activated methods that don't support shipping zones. diff --git a/includes/wc-formatting-functions.php b/includes/wc-formatting-functions.php index 967bb207f34..cc5d0f6872d 100644 --- a/includes/wc-formatting-functions.php +++ b/includes/wc-formatting-functions.php @@ -713,6 +713,11 @@ function wc_string_to_datetime( $time_string ) { * @return string PHP timezone string for the site */ function wc_timezone_string() { + // Added in WordPress 5.3 Ref https://developer.wordpress.org/reference/functions/wp_timezone_string/. + if ( function_exists( 'wp_timezone_string' ) ) { + return wp_timezone_string(); + } + // If site timezone string exists, return it. $timezone = get_option( 'timezone_string' ); if ( $timezone ) { @@ -720,13 +725,13 @@ function wc_timezone_string() { } // Get UTC offset, if it isn't set then return UTC. - $utc_offset = intval( get_option( 'gmt_offset', 0 ) ); - if ( 0 === $utc_offset ) { + $utc_offset = floatval( get_option( 'gmt_offset', 0 ) ); + if ( ! is_numeric( $utc_offset ) || 0.0 === $utc_offset ) { return 'UTC'; } // Adjust UTC offset from hours to seconds. - $utc_offset *= 3600; + $utc_offset = (int) ( $utc_offset * 3600 ); // Attempt to guess the timezone string from the UTC offset. $timezone = timezone_name_from_abbr( '', $utc_offset ); diff --git a/includes/wc-stock-functions.php b/includes/wc-stock-functions.php index 2deb1580e4c..d39065cd3d1 100644 --- a/includes/wc-stock-functions.php +++ b/includes/wc-stock-functions.php @@ -299,33 +299,80 @@ function wc_increase_stock_levels( $order_id ) { * @param integer $exclude_order_id Order ID to exclude. * @return int */ -function wc_get_held_stock_quantity( $product, $exclude_order_id = 0 ) { - global $wpdb; +function wc_get_held_stock_quantity( WC_Product $product, $exclude_order_id = 0 ) { + /** + * Filter: woocommerce_hold_stock_for_checkout + * Allows enable/disable hold stock functionality on checkout. + * + * @since 4.3.0 + * @param bool $enabled Default to true if managing stock globally. + */ + if ( ! apply_filters( 'woocommerce_hold_stock_for_checkout', wc_string_to_bool( get_option( 'woocommerce_manage_stock', 'yes' ) ) ) ) { + return 0; + } - return $wpdb->get_var( - $wpdb->prepare( - " - SELECT SUM( order_item_meta.meta_value ) AS held_qty - FROM {$wpdb->posts} AS posts - LEFT JOIN {$wpdb->postmeta} as postmeta ON posts.ID = postmeta.post_id - LEFT JOIN {$wpdb->prefix}woocommerce_order_items as order_items ON posts.ID = order_items.order_id - LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta as order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id - LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta as order_item_meta2 ON order_items.order_item_id = order_item_meta2.order_item_id - WHERE order_item_meta.meta_key = '_qty' - AND order_item_meta2.meta_key = %s - AND order_item_meta2.meta_value = %d - AND postmeta.meta_key = '_created_via' - AND postmeta.meta_value = 'checkout' - AND posts.post_type IN ( '" . implode( "','", wc_get_order_types() ) . "' ) - AND posts.post_status = 'wc-pending' - AND posts.ID != %d;", - 'product_variation' === get_post_type( $product->get_stock_managed_by_id() ) ? '_variation_id' : '_product_id', - $product->get_stock_managed_by_id(), - $exclude_order_id - ) - ); // WPCS: unprepared SQL ok. + return ( new \Automattic\WooCommerce\Checkout\Helpers\ReserveStock() )->get_reserved_stock( $product, $exclude_order_id ); } +/** + * Hold stock for an order. + * + * @throws ReserveStockException If reserve stock fails. + * + * @since 4.1.0 + * @param \WC_Order|int $order Order ID or instance. + */ +function wc_reserve_stock_for_order( $order ) { + /** + * Filter: woocommerce_hold_stock_for_checkout + * Allows enable/disable hold stock functionality on checkout. + * + * @since @since 4.1.0 + * @param bool $enabled Default to true if managing stock globally. + */ + if ( ! apply_filters( 'woocommerce_hold_stock_for_checkout', wc_string_to_bool( get_option( 'woocommerce_manage_stock', 'yes' ) ) ) ) { + return; + } + + $order = $order instanceof WC_Order ? $order : wc_get_order( $order ); + + if ( $order ) { + ( new \Automattic\WooCommerce\Checkout\Helpers\ReserveStock() )->reserve_stock_for_order( $order ); + } +} +add_action( 'woocommerce_checkout_order_created', 'wc_reserve_stock_for_order' ); + +/** + * Release held stock for an order. + * + * @since 4.3.0 + * @param \WC_Order|int $order Order ID or instance. + */ +function wc_release_stock_for_order( $order ) { + /** + * Filter: woocommerce_hold_stock_for_checkout + * Allows enable/disable hold stock functionality on checkout. + * + * @since 4.3.0 + * @param bool $enabled Default to true if managing stock globally. + */ + if ( ! apply_filters( 'woocommerce_hold_stock_for_checkout', wc_string_to_bool( get_option( 'woocommerce_manage_stock', 'yes' ) ) ) ) { + return; + } + + $order = $order instanceof WC_Order ? $order : wc_get_order( $order ); + + if ( $order ) { + ( new \Automattic\WooCommerce\Checkout\Helpers\ReserveStock() )->release_stock_for_order( $order ); + } +} +add_action( 'woocommerce_checkout_order_exception', 'wc_release_stock_for_order' ); +add_action( 'woocommerce_payment_complete', 'wc_release_stock_for_order', 11 ); +add_action( 'woocommerce_order_status_cancelled', 'wc_release_stock_for_order', 11 ); +add_action( 'woocommerce_order_status_completed', 'wc_release_stock_for_order', 11 ); +add_action( 'woocommerce_order_status_processing', 'wc_release_stock_for_order', 11 ); +add_action( 'woocommerce_order_status_on-hold', 'wc_release_stock_for_order', 11 ); + /** * Return low stock amount to determine if notification needs to be sent * diff --git a/includes/wc-template-functions.php b/includes/wc-template-functions.php index 26a2f26c45a..18f5947bd72 100644 --- a/includes/wc-template-functions.php +++ b/includes/wc-template-functions.php @@ -673,7 +673,7 @@ function wc_get_product_class( $class = '', $product = null ) { * WooCommerce Post Class filter. * * @since 3.6.2 - * @param array $class Array of CSS classes. + * @param array $classes Array of CSS classes. * @param WC_Product $product Product object. */ $classes = apply_filters( 'woocommerce_post_class', $classes, $product ); @@ -2097,7 +2097,7 @@ if ( ! function_exists( 'woocommerce_widget_shopping_cart_subtotal' ) ) { * @since 3.7.0 */ function woocommerce_widget_shopping_cart_subtotal() { - echo '' . esc_html__( 'Subtotal', 'woocommerce' ) . ': ' . WC()->cart->get_cart_subtotal(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo '' . esc_html__( 'Subtotal:', 'woocommerce' ) . ' ' . WC()->cart->get_cart_subtotal(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } @@ -2706,7 +2706,7 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) { $field = ''; @@ -2733,7 +2733,7 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) { '; foreach ( $states as $ckey => $cvalue ) { - $field .= ''; + $field .= ''; } $field .= ''; @@ -2782,7 +2782,7 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) { } $custom_attributes[] = 'data-allow_clear="true"'; } - $options .= ''; + $options .= ''; } $field .= ''; - $field .= ''; + $field .= ''; } } diff --git a/lerna.json b/lerna.json new file mode 100644 index 00000000000..eb74a66b0dd --- /dev/null +++ b/lerna.json @@ -0,0 +1,10 @@ +{ + "command": { + "publish": { + "message": "chore(release): publish" + } + }, + "ignoreChanges": [ "**/CHANGELOG.md", "**/test/**" ], + "packages": [ "tests/e2e/*" ], + "version": "independent" +} diff --git a/package-lock.json b/package-lock.json index 90348b8183f..8e1b8b9182f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "woocommerce", - "version": "4.0.0", + "version": "4.3.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -319,6 +319,77 @@ } } }, + "@babel/helper-builder-react-jsx": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.9.0.tgz", + "integrity": "sha512-weiIo4gaoGgnhff54GQ3P5wsUQmnSwpkvU0r6ZHq6TzoSzKy4JxHEgnxNytaKbov2a9z/CVNyzliuCOUPEX3Jw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/types": "^7.9.0" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", + "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", + "dev": true + }, + "@babel/types": { + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz", + "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.9.5", + "lodash": "^4.17.13", + "to-fast-properties": "^2.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/helper-builder-react-jsx-experimental": { + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.9.5.tgz", + "integrity": "sha512-HAagjAC93tk748jcXpZ7oYRZH485RCq/+yEv9SIWezHRPv9moZArTnkUNciUNzvwHUABmiWKlcxJvMcu59UwTg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-module-imports": "^7.8.3", + "@babel/types": "^7.9.5" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", + "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", + "dev": true + }, + "@babel/types": { + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz", + "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.9.5", + "lodash": "^4.17.13", + "to-fast-properties": "^2.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/helper-compilation-targets": { "version": "7.8.7", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz", @@ -1779,6 +1850,23 @@ } } }, + "@babel/plugin-syntax-jsx": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz", + "integrity": "sha512-WxdW9xyLgBdefoo0Ynn3MRSkhe5tFVxxKNVdnZSh318WrG2e2jH+E9wd/++JsqcLJZPfz87njQJ8j2Upjm0M0A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, "@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", @@ -2477,6 +2565,26 @@ } } }, + "@babel/plugin-transform-react-jsx": { + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.9.4.tgz", + "integrity": "sha512-Mjqf3pZBNLt854CK0C/kRuXAnE6H/bo7xYojP+WGtX8glDGSibcwnsWwhwoSuRg0+EBnxPC1ouVnuetUIlPSAw==", + "dev": true, + "requires": { + "@babel/helper-builder-react-jsx": "^7.9.0", + "@babel/helper-builder-react-jsx-experimental": "^7.9.0", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-jsx": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, "@babel/plugin-transform-regenerator": { "version": "7.8.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz", @@ -2503,6 +2611,26 @@ } } }, + "@babel/plugin-transform-runtime": { + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.9.6.tgz", + "integrity": "sha512-qcmiECD0mYOjOIt8YHNsAP1SxPooC/rDmfmiSK9BNY72EitdSc7l44WTEklaWuFtbOEBjNhWWyph/kOImbNJ4w==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "resolve": "^1.8.1", + "semver": "^5.5.1" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, "@babel/plugin-transform-shorthand-properties": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz", @@ -2854,6 +2982,173 @@ } } }, + "@evocateur/libnpmaccess": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@evocateur/libnpmaccess/-/libnpmaccess-3.1.2.tgz", + "integrity": "sha512-KSCAHwNWro0CF2ukxufCitT9K5LjL/KuMmNzSu8wuwN2rjyKHD8+cmOsiybK+W5hdnwc5M1SmRlVCaMHQo+3rg==", + "dev": true, + "requires": { + "@evocateur/npm-registry-fetch": "^4.0.0", + "aproba": "^2.0.0", + "figgy-pudding": "^3.5.1", + "get-stream": "^4.0.0", + "npm-package-arg": "^6.1.0" + }, + "dependencies": { + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + } + } + }, + "@evocateur/libnpmpublish": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@evocateur/libnpmpublish/-/libnpmpublish-1.2.2.tgz", + "integrity": "sha512-MJrrk9ct1FeY9zRlyeoyMieBjGDG9ihyyD9/Ft6MMrTxql9NyoEx2hw9casTIP4CdqEVu+3nQ2nXxoJ8RCXyFg==", + "dev": true, + "requires": { + "@evocateur/npm-registry-fetch": "^4.0.0", + "aproba": "^2.0.0", + "figgy-pudding": "^3.5.1", + "get-stream": "^4.0.0", + "lodash.clonedeep": "^4.5.0", + "normalize-package-data": "^2.4.0", + "npm-package-arg": "^6.1.0", + "semver": "^5.5.1", + "ssri": "^6.0.1" + }, + "dependencies": { + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + } + } + }, + "@evocateur/npm-registry-fetch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@evocateur/npm-registry-fetch/-/npm-registry-fetch-4.0.0.tgz", + "integrity": "sha512-k1WGfKRQyhJpIr+P17O5vLIo2ko1PFLKwoetatdduUSt/aQ4J2sJrJwwatdI5Z3SiYk/mRH9S3JpdmMFd/IK4g==", + "dev": true, + "requires": { + "JSONStream": "^1.3.4", + "bluebird": "^3.5.1", + "figgy-pudding": "^3.4.1", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^5.0.0", + "npm-package-arg": "^6.1.0", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@evocateur/pacote": { + "version": "9.6.5", + "resolved": "https://registry.npmjs.org/@evocateur/pacote/-/pacote-9.6.5.tgz", + "integrity": "sha512-EI552lf0aG2nOV8NnZpTxNo2PcXKPmDbF9K8eCBFQdIZwHNGN/mi815fxtmUMa2wTa1yndotICIDt/V0vpEx2w==", + "dev": true, + "requires": { + "@evocateur/npm-registry-fetch": "^4.0.0", + "bluebird": "^3.5.3", + "cacache": "^12.0.3", + "chownr": "^1.1.2", + "figgy-pudding": "^3.5.1", + "get-stream": "^4.1.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^5.0.0", + "minimatch": "^3.0.4", + "minipass": "^2.3.5", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "normalize-package-data": "^2.5.0", + "npm-package-arg": "^6.1.0", + "npm-packlist": "^1.4.4", + "npm-pick-manifest": "^3.0.0", + "osenv": "^0.1.5", + "promise-inflight": "^1.0.1", + "promise-retry": "^1.1.1", + "protoduck": "^5.0.1", + "rimraf": "^2.6.3", + "safe-buffer": "^5.2.0", + "semver": "^5.7.0", + "ssri": "^6.0.1", + "tar": "^4.4.10", + "unique-filename": "^1.1.1", + "which": "^1.3.1" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true + }, + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, "@hapi/address": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", @@ -4435,6 +4730,1767 @@ } } }, + "@lerna/add": { + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@lerna/add/-/add-3.20.0.tgz", + "integrity": "sha512-AnH1oRIEEg/VDa3SjYq4x1/UglEAvrZuV0WssHUMN81RTZgQk3we+Mv3qZNddrZ/fBcZu2IAdN/EQ3+ie2JxKQ==", + "dev": true, + "requires": { + "@evocateur/pacote": "^9.6.3", + "@lerna/bootstrap": "3.20.0", + "@lerna/command": "3.18.5", + "@lerna/filter-options": "3.20.0", + "@lerna/npm-conf": "3.16.0", + "@lerna/validation-error": "3.13.0", + "dedent": "^0.7.0", + "npm-package-arg": "^6.1.0", + "p-map": "^2.1.0", + "semver": "^6.2.0" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@lerna/bootstrap": { + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@lerna/bootstrap/-/bootstrap-3.20.0.tgz", + "integrity": "sha512-Wylullx3uthKE7r4izo09qeRGL20Y5yONlQEjPCfnbxCC2Elu+QcPu4RC6kqKQ7b+g7pdC3OOgcHZjngrwr5XQ==", + "dev": true, + "requires": { + "@lerna/command": "3.18.5", + "@lerna/filter-options": "3.20.0", + "@lerna/has-npm-version": "3.16.5", + "@lerna/npm-install": "3.16.5", + "@lerna/package-graph": "3.18.5", + "@lerna/pulse-till-done": "3.13.0", + "@lerna/rimraf-dir": "3.16.5", + "@lerna/run-lifecycle": "3.16.2", + "@lerna/run-topologically": "3.18.5", + "@lerna/symlink-binary": "3.17.0", + "@lerna/symlink-dependencies": "3.17.0", + "@lerna/validation-error": "3.13.0", + "dedent": "^0.7.0", + "get-port": "^4.2.0", + "multimatch": "^3.0.0", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2", + "p-finally": "^1.0.0", + "p-map": "^2.1.0", + "p-map-series": "^1.0.0", + "p-waterfall": "^1.0.0", + "read-package-tree": "^5.1.6", + "semver": "^6.2.0" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@lerna/changed": { + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@lerna/changed/-/changed-3.20.0.tgz", + "integrity": "sha512-+hzMFSldbRPulZ0vbKk6RD9f36gaH3Osjx34wrrZ62VB4pKmjyuS/rxVYkCA3viPLHoiIw2F8zHM5BdYoDSbjw==", + "dev": true, + "requires": { + "@lerna/collect-updates": "3.20.0", + "@lerna/command": "3.18.5", + "@lerna/listable": "3.18.5", + "@lerna/output": "3.13.0" + } + }, + "@lerna/check-working-tree": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/check-working-tree/-/check-working-tree-3.16.5.tgz", + "integrity": "sha512-xWjVBcuhvB8+UmCSb5tKVLB5OuzSpw96WEhS2uz6hkWVa/Euh1A0/HJwn2cemyK47wUrCQXtczBUiqnq9yX5VQ==", + "dev": true, + "requires": { + "@lerna/collect-uncommitted": "3.16.5", + "@lerna/describe-ref": "3.16.5", + "@lerna/validation-error": "3.13.0" + } + }, + "@lerna/child-process": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/child-process/-/child-process-3.16.5.tgz", + "integrity": "sha512-vdcI7mzei9ERRV4oO8Y1LHBZ3A5+ampRKg1wq5nutLsUA4mEBN6H7JqjWOMY9xZemv6+kATm2ofjJ3lW5TszQg==", + "dev": true, + "requires": { + "chalk": "^2.3.1", + "execa": "^1.0.0", + "strong-log-transformer": "^2.0.0" + } + }, + "@lerna/clean": { + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@lerna/clean/-/clean-3.20.0.tgz", + "integrity": "sha512-9ZdYrrjQvR5wNXmHfDsfjWjp0foOkCwKe3hrckTzkAeQA1ibyz5llGwz5e1AeFrV12e2/OLajVqYfe+qdkZUgg==", + "dev": true, + "requires": { + "@lerna/command": "3.18.5", + "@lerna/filter-options": "3.20.0", + "@lerna/prompt": "3.18.5", + "@lerna/pulse-till-done": "3.13.0", + "@lerna/rimraf-dir": "3.16.5", + "p-map": "^2.1.0", + "p-map-series": "^1.0.0", + "p-waterfall": "^1.0.0" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + } + } + }, + "@lerna/cli": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/cli/-/cli-3.18.5.tgz", + "integrity": "sha512-erkbxkj9jfc89vVs/jBLY/fM0I80oLmJkFUV3Q3wk9J3miYhP14zgVEBsPZY68IZlEjT6T3Xlq2xO1AVaatHsA==", + "dev": true, + "requires": { + "@lerna/global-options": "3.13.0", + "dedent": "^0.7.0", + "npmlog": "^4.1.2", + "yargs": "^14.2.2" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "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" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", + "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^15.0.1" + } + }, + "yargs-parser": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz", + "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "@lerna/collect-uncommitted": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/collect-uncommitted/-/collect-uncommitted-3.16.5.tgz", + "integrity": "sha512-ZgqnGwpDZiWyzIQVZtQaj9tRizsL4dUOhuOStWgTAw1EMe47cvAY2kL709DzxFhjr6JpJSjXV5rZEAeU3VE0Hg==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "chalk": "^2.3.1", + "figgy-pudding": "^3.5.1", + "npmlog": "^4.1.2" + } + }, + "@lerna/collect-updates": { + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@lerna/collect-updates/-/collect-updates-3.20.0.tgz", + "integrity": "sha512-qBTVT5g4fupVhBFuY4nI/3FSJtQVcDh7/gEPOpRxoXB/yCSnT38MFHXWl+y4einLciCjt/+0x6/4AG80fjay2Q==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@lerna/describe-ref": "3.16.5", + "minimatch": "^3.0.4", + "npmlog": "^4.1.2", + "slash": "^2.0.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "@lerna/command": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/command/-/command-3.18.5.tgz", + "integrity": "sha512-36EnqR59yaTU4HrR1C9XDFti2jRx0BgpIUBeWn129LZZB8kAB3ov1/dJNa1KcNRKp91DncoKHLY99FZ6zTNpMQ==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@lerna/package-graph": "3.18.5", + "@lerna/project": "3.18.0", + "@lerna/validation-error": "3.13.0", + "@lerna/write-log-file": "3.13.0", + "clone-deep": "^4.0.1", + "dedent": "^0.7.0", + "execa": "^1.0.0", + "is-ci": "^2.0.0", + "npmlog": "^4.1.2" + }, + "dependencies": { + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + } + } + }, + "@lerna/conventional-commits": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/conventional-commits/-/conventional-commits-3.18.5.tgz", + "integrity": "sha512-qcvXIEJ3qSgalxXnQ7Yxp5H9Ta5TVyai6vEor6AAEHc20WiO7UIdbLDCxBtiiHMdGdpH85dTYlsoYUwsCJu3HQ==", + "dev": true, + "requires": { + "@lerna/validation-error": "3.13.0", + "conventional-changelog-angular": "^5.0.3", + "conventional-changelog-core": "^3.1.6", + "conventional-recommended-bump": "^5.0.0", + "fs-extra": "^8.1.0", + "get-stream": "^4.0.0", + "lodash.template": "^4.5.0", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2", + "pify": "^4.0.1", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@lerna/create": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/create/-/create-3.18.5.tgz", + "integrity": "sha512-cHpjocbpKmLopCuZFI7cKEM3E/QY8y+yC7VtZ4FQRSaLU8D8i2xXtXmYaP1GOlVNavji0iwoXjuNpnRMInIr2g==", + "dev": true, + "requires": { + "@evocateur/pacote": "^9.6.3", + "@lerna/child-process": "3.16.5", + "@lerna/command": "3.18.5", + "@lerna/npm-conf": "3.16.0", + "@lerna/validation-error": "3.13.0", + "camelcase": "^5.0.0", + "dedent": "^0.7.0", + "fs-extra": "^8.1.0", + "globby": "^9.2.0", + "init-package-json": "^1.10.3", + "npm-package-arg": "^6.1.0", + "p-reduce": "^1.0.0", + "pify": "^4.0.1", + "semver": "^6.2.0", + "slash": "^2.0.0", + "validate-npm-package-license": "^3.0.3", + "validate-npm-package-name": "^3.0.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "@nodelib/fs.stat": { + "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 + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "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" + } + } + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "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" + } + }, + "fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "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" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "globby": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", + "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^1.0.2", + "dir-glob": "^2.2.2", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "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" + } + } + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "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" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "@lerna/create-symlink": { + "version": "3.16.2", + "resolved": "https://registry.npmjs.org/@lerna/create-symlink/-/create-symlink-3.16.2.tgz", + "integrity": "sha512-pzXIJp6av15P325sgiIRpsPXLFmkisLhMBCy4764d+7yjf2bzrJ4gkWVMhsv4AdF0NN3OyZ5jjzzTtLNqfR+Jw==", + "dev": true, + "requires": { + "@zkochan/cmd-shim": "^3.1.0", + "fs-extra": "^8.1.0", + "npmlog": "^4.1.2" + } + }, + "@lerna/describe-ref": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/describe-ref/-/describe-ref-3.16.5.tgz", + "integrity": "sha512-c01+4gUF0saOOtDBzbLMFOTJDHTKbDFNErEY6q6i9QaXuzy9LNN62z+Hw4acAAZuJQhrVWncVathcmkkjvSVGw==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "npmlog": "^4.1.2" + } + }, + "@lerna/diff": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/diff/-/diff-3.18.5.tgz", + "integrity": "sha512-u90lGs+B8DRA9Z/2xX4YaS3h9X6GbypmGV6ITzx9+1Ga12UWGTVlKaCXBgONMBjzJDzAQOK8qPTwLA57SeBLgA==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@lerna/command": "3.18.5", + "@lerna/validation-error": "3.13.0", + "npmlog": "^4.1.2" + } + }, + "@lerna/exec": { + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@lerna/exec/-/exec-3.20.0.tgz", + "integrity": "sha512-pS1mmC7kzV668rHLWuv31ClngqeXjeHC8kJuM+W2D6IpUVMGQHLcCTYLudFgQsuKGVpl0DGNYG+sjLhAPiiu6A==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@lerna/command": "3.18.5", + "@lerna/filter-options": "3.20.0", + "@lerna/profiler": "3.20.0", + "@lerna/run-topologically": "3.18.5", + "@lerna/validation-error": "3.13.0", + "p-map": "^2.1.0" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + } + } + }, + "@lerna/filter-options": { + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@lerna/filter-options/-/filter-options-3.20.0.tgz", + "integrity": "sha512-bmcHtvxn7SIl/R9gpiNMVG7yjx7WyT0HSGw34YVZ9B+3xF/83N3r5Rgtjh4hheLZ+Q91Or0Jyu5O3Nr+AwZe2g==", + "dev": true, + "requires": { + "@lerna/collect-updates": "3.20.0", + "@lerna/filter-packages": "3.18.0", + "dedent": "^0.7.0", + "figgy-pudding": "^3.5.1", + "npmlog": "^4.1.2" + } + }, + "@lerna/filter-packages": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@lerna/filter-packages/-/filter-packages-3.18.0.tgz", + "integrity": "sha512-6/0pMM04bCHNATIOkouuYmPg6KH3VkPCIgTfQmdkPJTullERyEQfNUKikrefjxo1vHOoCACDpy65JYyKiAbdwQ==", + "dev": true, + "requires": { + "@lerna/validation-error": "3.13.0", + "multimatch": "^3.0.0", + "npmlog": "^4.1.2" + } + }, + "@lerna/get-npm-exec-opts": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/get-npm-exec-opts/-/get-npm-exec-opts-3.13.0.tgz", + "integrity": "sha512-Y0xWL0rg3boVyJk6An/vurKzubyJKtrxYv2sj4bB8Mc5zZ3tqtv0ccbOkmkXKqbzvNNF7VeUt1OJ3DRgtC/QZw==", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + }, + "@lerna/get-packed": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@lerna/get-packed/-/get-packed-3.16.0.tgz", + "integrity": "sha512-AjsFiaJzo1GCPnJUJZiTW6J1EihrPkc2y3nMu6m3uWFxoleklsSCyImumzVZJssxMi3CPpztj8LmADLedl9kXw==", + "dev": true, + "requires": { + "fs-extra": "^8.1.0", + "ssri": "^6.0.1", + "tar": "^4.4.8" + }, + "dependencies": { + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@lerna/github-client": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/github-client/-/github-client-3.16.5.tgz", + "integrity": "sha512-rHQdn8Dv/CJrO3VouOP66zAcJzrHsm+wFuZ4uGAai2At2NkgKH+tpNhQy2H1PSC0Ezj9LxvdaHYrUzULqVK5Hw==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@octokit/plugin-enterprise-rest": "^3.6.1", + "@octokit/rest": "^16.28.4", + "git-url-parse": "^11.1.2", + "npmlog": "^4.1.2" + } + }, + "@lerna/gitlab-client": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@lerna/gitlab-client/-/gitlab-client-3.15.0.tgz", + "integrity": "sha512-OsBvRSejHXUBMgwWQqNoioB8sgzL/Pf1pOUhHKtkiMl6aAWjklaaq5HPMvTIsZPfS6DJ9L5OK2GGZuooP/5c8Q==", + "dev": true, + "requires": { + "node-fetch": "^2.5.0", + "npmlog": "^4.1.2", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "node-fetch": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", + "dev": true + } + } + }, + "@lerna/global-options": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/global-options/-/global-options-3.13.0.tgz", + "integrity": "sha512-SlZvh1gVRRzYLVluz9fryY1nJpZ0FHDGB66U9tFfvnnxmueckRQxLopn3tXj3NU1kc3QANT2I5BsQkOqZ4TEFQ==", + "dev": true + }, + "@lerna/has-npm-version": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/has-npm-version/-/has-npm-version-3.16.5.tgz", + "integrity": "sha512-WL7LycR9bkftyqbYop5rEGJ9sRFIV55tSGmbN1HLrF9idwOCD7CLrT64t235t3t4O5gehDnwKI5h2U3oxTrF8Q==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@lerna/import": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/import/-/import-3.18.5.tgz", + "integrity": "sha512-PH0WVLEgp+ORyNKbGGwUcrueW89K3Iuk/DDCz8mFyG2IG09l/jOF0vzckEyGyz6PO5CMcz4TI1al/qnp3FrahQ==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@lerna/command": "3.18.5", + "@lerna/prompt": "3.18.5", + "@lerna/pulse-till-done": "3.13.0", + "@lerna/validation-error": "3.13.0", + "dedent": "^0.7.0", + "fs-extra": "^8.1.0", + "p-map-series": "^1.0.0" + } + }, + "@lerna/info": { + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@lerna/info/-/info-3.20.0.tgz", + "integrity": "sha512-Rsz+KQF9mczbGUbPTrtOed1N0C+cA08Qz0eX/oI+NNjvsryZIju/o7uedG4I3P55MBiAioNrJI88fHH3eTgYug==", + "dev": true, + "requires": { + "@lerna/command": "3.18.5", + "@lerna/output": "3.13.0", + "envinfo": "^7.3.1" + } + }, + "@lerna/init": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/init/-/init-3.18.5.tgz", + "integrity": "sha512-oCwipWrha98EcJAHm8AGd2YFFLNI7AW9AWi0/LbClj1+XY9ah+uifXIgYGfTk63LbgophDd8936ZEpHMxBsbAg==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@lerna/command": "3.18.5", + "fs-extra": "^8.1.0", + "p-map": "^2.1.0", + "write-json-file": "^3.2.0" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + } + } + }, + "@lerna/link": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/link/-/link-3.18.5.tgz", + "integrity": "sha512-xTN3vktJpkT7Nqc3QkZRtHO4bT5NvuLMtKNIBDkks0HpGxC9PRyyqwOoCoh1yOGbrWIuDezhfMg3Qow+6I69IQ==", + "dev": true, + "requires": { + "@lerna/command": "3.18.5", + "@lerna/package-graph": "3.18.5", + "@lerna/symlink-dependencies": "3.17.0", + "p-map": "^2.1.0", + "slash": "^2.0.0" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "@lerna/list": { + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@lerna/list/-/list-3.20.0.tgz", + "integrity": "sha512-fXTicPrfioVnRzknyPawmYIVkzDRBaQqk9spejS1S3O1DOidkihK0xxNkr8HCVC0L22w6f92g83qWDp2BYRUbg==", + "dev": true, + "requires": { + "@lerna/command": "3.18.5", + "@lerna/filter-options": "3.20.0", + "@lerna/listable": "3.18.5", + "@lerna/output": "3.13.0" + } + }, + "@lerna/listable": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/listable/-/listable-3.18.5.tgz", + "integrity": "sha512-Sdr3pVyaEv5A7ZkGGYR7zN+tTl2iDcinryBPvtuv20VJrXBE8wYcOks1edBTcOWsPjCE/rMP4bo1pseyk3UTsg==", + "dev": true, + "requires": { + "@lerna/query-graph": "3.18.5", + "chalk": "^2.3.1", + "columnify": "^1.5.4" + } + }, + "@lerna/log-packed": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@lerna/log-packed/-/log-packed-3.16.0.tgz", + "integrity": "sha512-Fp+McSNBV/P2mnLUYTaSlG8GSmpXM7krKWcllqElGxvAqv6chk2K3c2k80MeVB4WvJ9tRjUUf+i7HUTiQ9/ckQ==", + "dev": true, + "requires": { + "byte-size": "^5.0.1", + "columnify": "^1.5.4", + "has-unicode": "^2.0.1", + "npmlog": "^4.1.2" + } + }, + "@lerna/npm-conf": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@lerna/npm-conf/-/npm-conf-3.16.0.tgz", + "integrity": "sha512-HbO3DUrTkCAn2iQ9+FF/eisDpWY5POQAOF1m7q//CZjdC2HSW3UYbKEGsSisFxSfaF9Z4jtrV+F/wX6qWs3CuA==", + "dev": true, + "requires": { + "config-chain": "^1.1.11", + "pify": "^4.0.1" + } + }, + "@lerna/npm-dist-tag": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/npm-dist-tag/-/npm-dist-tag-3.18.5.tgz", + "integrity": "sha512-xw0HDoIG6HreVsJND9/dGls1c+lf6vhu7yJoo56Sz5bvncTloYGLUppIfDHQr4ZvmPCK8rsh0euCVh2giPxzKQ==", + "dev": true, + "requires": { + "@evocateur/npm-registry-fetch": "^4.0.0", + "@lerna/otplease": "3.18.5", + "figgy-pudding": "^3.5.1", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2" + } + }, + "@lerna/npm-install": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/npm-install/-/npm-install-3.16.5.tgz", + "integrity": "sha512-hfiKk8Eku6rB9uApqsalHHTHY+mOrrHeWEs+gtg7+meQZMTS3kzv4oVp5cBZigndQr3knTLjwthT/FX4KvseFg==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@lerna/get-npm-exec-opts": "3.13.0", + "fs-extra": "^8.1.0", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2", + "signal-exit": "^3.0.2", + "write-pkg": "^3.1.0" + } + }, + "@lerna/npm-publish": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/npm-publish/-/npm-publish-3.18.5.tgz", + "integrity": "sha512-3etLT9+2L8JAx5F8uf7qp6iAtOLSMj+ZYWY6oUgozPi/uLqU0/gsMsEXh3F0+YVW33q0M61RpduBoAlOOZnaTg==", + "dev": true, + "requires": { + "@evocateur/libnpmpublish": "^1.2.2", + "@lerna/otplease": "3.18.5", + "@lerna/run-lifecycle": "3.16.2", + "figgy-pudding": "^3.5.1", + "fs-extra": "^8.1.0", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2", + "pify": "^4.0.1", + "read-package-json": "^2.0.13" + } + }, + "@lerna/npm-run-script": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/npm-run-script/-/npm-run-script-3.16.5.tgz", + "integrity": "sha512-1asRi+LjmVn3pMjEdpqKJZFT/3ZNpb+VVeJMwrJaV/3DivdNg7XlPK9LTrORuKU4PSvhdEZvJmSlxCKyDpiXsQ==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@lerna/get-npm-exec-opts": "3.13.0", + "npmlog": "^4.1.2" + } + }, + "@lerna/otplease": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/otplease/-/otplease-3.18.5.tgz", + "integrity": "sha512-S+SldXAbcXTEDhzdxYLU0ZBKuYyURP/ND2/dK6IpKgLxQYh/z4ScljPDMyKymmEvgiEJmBsPZAAPfmNPEzxjog==", + "dev": true, + "requires": { + "@lerna/prompt": "3.18.5", + "figgy-pudding": "^3.5.1" + } + }, + "@lerna/output": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/output/-/output-3.13.0.tgz", + "integrity": "sha512-7ZnQ9nvUDu/WD+bNsypmPG5MwZBwu86iRoiW6C1WBuXXDxM5cnIAC1m2WxHeFnjyMrYlRXM9PzOQ9VDD+C15Rg==", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + }, + "@lerna/pack-directory": { + "version": "3.16.4", + "resolved": "https://registry.npmjs.org/@lerna/pack-directory/-/pack-directory-3.16.4.tgz", + "integrity": "sha512-uxSF0HZeGyKaaVHz5FroDY9A5NDDiCibrbYR6+khmrhZtY0Bgn6hWq8Gswl9iIlymA+VzCbshWIMX4o2O8C8ng==", + "dev": true, + "requires": { + "@lerna/get-packed": "3.16.0", + "@lerna/package": "3.16.0", + "@lerna/run-lifecycle": "3.16.2", + "figgy-pudding": "^3.5.1", + "npm-packlist": "^1.4.4", + "npmlog": "^4.1.2", + "tar": "^4.4.10", + "temp-write": "^3.4.0" + }, + "dependencies": { + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@lerna/package": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@lerna/package/-/package-3.16.0.tgz", + "integrity": "sha512-2lHBWpaxcBoiNVbtyLtPUuTYEaB/Z+eEqRS9duxpZs6D+mTTZMNy6/5vpEVSCBmzvdYpyqhqaYjjSLvjjr5Riw==", + "dev": true, + "requires": { + "load-json-file": "^5.3.0", + "npm-package-arg": "^6.1.0", + "write-pkg": "^3.1.0" + }, + "dependencies": { + "load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true + } + } + }, + "@lerna/package-graph": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/package-graph/-/package-graph-3.18.5.tgz", + "integrity": "sha512-8QDrR9T+dBegjeLr+n9WZTVxUYUhIUjUgZ0gvNxUBN8S1WB9r6H5Yk56/MVaB64tA3oGAN9IIxX6w0WvTfFudA==", + "dev": true, + "requires": { + "@lerna/prerelease-id-from-version": "3.16.0", + "@lerna/validation-error": "3.13.0", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@lerna/prerelease-id-from-version": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-3.16.0.tgz", + "integrity": "sha512-qZyeUyrE59uOK8rKdGn7jQz+9uOpAaF/3hbslJVFL1NqF9ELDTqjCPXivuejMX/lN4OgD6BugTO4cR7UTq/sZA==", + "dev": true, + "requires": { + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@lerna/profiler": { + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@lerna/profiler/-/profiler-3.20.0.tgz", + "integrity": "sha512-bh8hKxAlm6yu8WEOvbLENm42i2v9SsR4WbrCWSbsmOElx3foRnMlYk7NkGECa+U5c3K4C6GeBbwgqs54PP7Ljg==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1", + "fs-extra": "^8.1.0", + "npmlog": "^4.1.2", + "upath": "^1.2.0" + } + }, + "@lerna/project": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@lerna/project/-/project-3.18.0.tgz", + "integrity": "sha512-+LDwvdAp0BurOAWmeHE3uuticsq9hNxBI0+FMHiIai8jrygpJGahaQrBYWpwbshbQyVLeQgx3+YJdW2TbEdFWA==", + "dev": true, + "requires": { + "@lerna/package": "3.16.0", + "@lerna/validation-error": "3.13.0", + "cosmiconfig": "^5.1.0", + "dedent": "^0.7.0", + "dot-prop": "^4.2.0", + "glob-parent": "^5.0.0", + "globby": "^9.2.0", + "load-json-file": "^5.3.0", + "npmlog": "^4.1.2", + "p-map": "^2.1.0", + "resolve-from": "^4.0.0", + "write-json-file": "^3.2.0" + }, + "dependencies": { + "@nodelib/fs.stat": { + "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 + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "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" + } + } + } + }, + "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" + } + }, + "fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + }, + "dependencies": { + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "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" + } + } + } + }, + "globby": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", + "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^1.0.2", + "dir-glob": "^2.2.2", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "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" + } + } + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" + } + }, + "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" + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true + } + } + }, + "@lerna/prompt": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/prompt/-/prompt-3.18.5.tgz", + "integrity": "sha512-rkKj4nm1twSbBEb69+Em/2jAERK8htUuV8/xSjN0NPC+6UjzAwY52/x9n5cfmpa9lyKf/uItp7chCI7eDmNTKQ==", + "dev": true, + "requires": { + "inquirer": "^6.2.0", + "npmlog": "^4.1.2" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + } + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "@lerna/publish": { + "version": "3.20.2", + "resolved": "https://registry.npmjs.org/@lerna/publish/-/publish-3.20.2.tgz", + "integrity": "sha512-N7Y6PdhJ+tYQPdI1tZum8W25cDlTp4D6brvRacKZusweWexxaopbV8RprBaKexkEX/KIbncuADq7qjDBdQHzaA==", + "dev": true, + "requires": { + "@evocateur/libnpmaccess": "^3.1.2", + "@evocateur/npm-registry-fetch": "^4.0.0", + "@evocateur/pacote": "^9.6.3", + "@lerna/check-working-tree": "3.16.5", + "@lerna/child-process": "3.16.5", + "@lerna/collect-updates": "3.20.0", + "@lerna/command": "3.18.5", + "@lerna/describe-ref": "3.16.5", + "@lerna/log-packed": "3.16.0", + "@lerna/npm-conf": "3.16.0", + "@lerna/npm-dist-tag": "3.18.5", + "@lerna/npm-publish": "3.18.5", + "@lerna/otplease": "3.18.5", + "@lerna/output": "3.13.0", + "@lerna/pack-directory": "3.16.4", + "@lerna/prerelease-id-from-version": "3.16.0", + "@lerna/prompt": "3.18.5", + "@lerna/pulse-till-done": "3.13.0", + "@lerna/run-lifecycle": "3.16.2", + "@lerna/run-topologically": "3.18.5", + "@lerna/validation-error": "3.13.0", + "@lerna/version": "3.20.2", + "figgy-pudding": "^3.5.1", + "fs-extra": "^8.1.0", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2", + "p-finally": "^1.0.0", + "p-map": "^2.1.0", + "p-pipe": "^1.2.0", + "semver": "^6.2.0" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@lerna/pulse-till-done": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/pulse-till-done/-/pulse-till-done-3.13.0.tgz", + "integrity": "sha512-1SOHpy7ZNTPulzIbargrgaJX387csN7cF1cLOGZiJQA6VqnS5eWs2CIrG8i8wmaUavj2QlQ5oEbRMVVXSsGrzA==", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + }, + "@lerna/query-graph": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/query-graph/-/query-graph-3.18.5.tgz", + "integrity": "sha512-50Lf4uuMpMWvJ306be3oQDHrWV42nai9gbIVByPBYJuVW8dT8O8pA3EzitNYBUdLL9/qEVbrR0ry1HD7EXwtRA==", + "dev": true, + "requires": { + "@lerna/package-graph": "3.18.5", + "figgy-pudding": "^3.5.1" + } + }, + "@lerna/resolve-symlink": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@lerna/resolve-symlink/-/resolve-symlink-3.16.0.tgz", + "integrity": "sha512-Ibj5e7njVHNJ/NOqT4HlEgPFPtPLWsO7iu59AM5bJDcAJcR96mLZ7KGVIsS2tvaO7akMEJvt2P+ErwCdloG3jQ==", + "dev": true, + "requires": { + "fs-extra": "^8.1.0", + "npmlog": "^4.1.2", + "read-cmd-shim": "^1.0.1" + } + }, + "@lerna/rimraf-dir": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/rimraf-dir/-/rimraf-dir-3.16.5.tgz", + "integrity": "sha512-bQlKmO0pXUsXoF8lOLknhyQjOZsCc0bosQDoX4lujBXSWxHVTg1VxURtWf2lUjz/ACsJVDfvHZbDm8kyBk5okA==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "npmlog": "^4.1.2", + "path-exists": "^3.0.0", + "rimraf": "^2.6.2" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "@lerna/run": { + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@lerna/run/-/run-3.20.0.tgz", + "integrity": "sha512-9U3AqeaCeB7KsGS9oyKNp62s9vYoULg/B4cqXTKZkc+OKL6QOEjYHYVSBcMK9lUXrMjCjDIuDSX3PnTCPxQ2Dw==", + "dev": true, + "requires": { + "@lerna/command": "3.18.5", + "@lerna/filter-options": "3.20.0", + "@lerna/npm-run-script": "3.16.5", + "@lerna/output": "3.13.0", + "@lerna/profiler": "3.20.0", + "@lerna/run-topologically": "3.18.5", + "@lerna/timer": "3.13.0", + "@lerna/validation-error": "3.13.0", + "p-map": "^2.1.0" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + } + } + }, + "@lerna/run-lifecycle": { + "version": "3.16.2", + "resolved": "https://registry.npmjs.org/@lerna/run-lifecycle/-/run-lifecycle-3.16.2.tgz", + "integrity": "sha512-RqFoznE8rDpyyF0rOJy3+KjZCeTkO8y/OB9orPauR7G2xQ7PTdCpgo7EO6ZNdz3Al+k1BydClZz/j78gNCmL2A==", + "dev": true, + "requires": { + "@lerna/npm-conf": "3.16.0", + "figgy-pudding": "^3.5.1", + "npm-lifecycle": "^3.1.2", + "npmlog": "^4.1.2" + } + }, + "@lerna/run-topologically": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/run-topologically/-/run-topologically-3.18.5.tgz", + "integrity": "sha512-6N1I+6wf4hLOnPW+XDZqwufyIQ6gqoPfHZFkfWlvTQ+Ue7CuF8qIVQ1Eddw5HKQMkxqN10thKOFfq/9NQZ4NUg==", + "dev": true, + "requires": { + "@lerna/query-graph": "3.18.5", + "figgy-pudding": "^3.5.1", + "p-queue": "^4.0.0" + }, + "dependencies": { + "p-queue": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-4.0.0.tgz", + "integrity": "sha512-3cRXXn3/O0o3+eVmUroJPSj/esxoEFIm0ZOno/T+NzG/VZgPOqQ8WKmlNqubSEpZmCIngEy34unkHGg83ZIBmg==", + "dev": true, + "requires": { + "eventemitter3": "^3.1.0" + } + } + } + }, + "@lerna/symlink-binary": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@lerna/symlink-binary/-/symlink-binary-3.17.0.tgz", + "integrity": "sha512-RLpy9UY6+3nT5J+5jkM5MZyMmjNHxZIZvXLV+Q3MXrf7Eaa1hNqyynyj4RO95fxbS+EZc4XVSk25DGFQbcRNSQ==", + "dev": true, + "requires": { + "@lerna/create-symlink": "3.16.2", + "@lerna/package": "3.16.0", + "fs-extra": "^8.1.0", + "p-map": "^2.1.0" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + } + } + }, + "@lerna/symlink-dependencies": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@lerna/symlink-dependencies/-/symlink-dependencies-3.17.0.tgz", + "integrity": "sha512-KmjU5YT1bpt6coOmdFueTJ7DFJL4H1w5eF8yAQ2zsGNTtZ+i5SGFBWpb9AQaw168dydc3s4eu0W0Sirda+F59Q==", + "dev": true, + "requires": { + "@lerna/create-symlink": "3.16.2", + "@lerna/resolve-symlink": "3.16.0", + "@lerna/symlink-binary": "3.17.0", + "fs-extra": "^8.1.0", + "p-finally": "^1.0.0", + "p-map": "^2.1.0", + "p-map-series": "^1.0.0" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + } + } + }, + "@lerna/timer": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/timer/-/timer-3.13.0.tgz", + "integrity": "sha512-RHWrDl8U4XNPqY5MQHkToWS9jHPnkLZEt5VD+uunCKTfzlxGnRCr3/zVr8VGy/uENMYpVP3wJa4RKGY6M0vkRw==", + "dev": true + }, + "@lerna/validation-error": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-3.13.0.tgz", + "integrity": "sha512-SiJP75nwB8GhgwLKQfdkSnDufAaCbkZWJqEDlKOUPUvVOplRGnfL+BPQZH5nvq2BYSRXsksXWZ4UHVnQZI/HYA==", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + }, + "@lerna/version": { + "version": "3.20.2", + "resolved": "https://registry.npmjs.org/@lerna/version/-/version-3.20.2.tgz", + "integrity": "sha512-ckBJMaBWc+xJen0cMyCE7W67QXLLrc0ELvigPIn8p609qkfNM0L0CF803MKxjVOldJAjw84b8ucNWZLvJagP/Q==", + "dev": true, + "requires": { + "@lerna/check-working-tree": "3.16.5", + "@lerna/child-process": "3.16.5", + "@lerna/collect-updates": "3.20.0", + "@lerna/command": "3.18.5", + "@lerna/conventional-commits": "3.18.5", + "@lerna/github-client": "3.16.5", + "@lerna/gitlab-client": "3.15.0", + "@lerna/output": "3.13.0", + "@lerna/prerelease-id-from-version": "3.16.0", + "@lerna/prompt": "3.18.5", + "@lerna/run-lifecycle": "3.16.2", + "@lerna/run-topologically": "3.18.5", + "@lerna/validation-error": "3.13.0", + "chalk": "^2.3.1", + "dedent": "^0.7.0", + "load-json-file": "^5.3.0", + "minimatch": "^3.0.4", + "npmlog": "^4.1.2", + "p-map": "^2.1.0", + "p-pipe": "^1.2.0", + "p-reduce": "^1.0.0", + "p-waterfall": "^1.0.0", + "semver": "^6.2.0", + "slash": "^2.0.0", + "temp-write": "^3.4.0", + "write-json-file": "^3.2.0" + }, + "dependencies": { + "load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true + } + } + }, + "@lerna/write-log-file": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/write-log-file/-/write-log-file-3.13.0.tgz", + "integrity": "sha512-RibeMnDPvlL8bFYW5C8cs4mbI3AHfQef73tnJCQ/SgrXZHehmHnsyWUiE7qDQCAo+B1RfTapvSyFF69iPj326A==", + "dev": true, + "requires": { + "npmlog": "^4.1.2", + "write-file-atomic": "^2.3.0" + }, + "dependencies": { + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + } + } + }, "@mrmlnc/readdir-enhanced": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", @@ -4471,6 +6527,186 @@ "fastq": "^1.6.0" } }, + "@octokit/auth-token": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.0.tgz", + "integrity": "sha512-eoOVMjILna7FVQf96iWc3+ZtE/ZT6y8ob8ZzcqKY1ibSQCnu4O/B7pJvzMx5cyZ/RjAff6DAdEb0O0Cjcxidkg==", + "dev": true, + "requires": { + "@octokit/types": "^2.0.0" + } + }, + "@octokit/endpoint": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.1.tgz", + "integrity": "sha512-pOPHaSz57SFT/m3R5P8MUu4wLPszokn5pXcB/pzavLTQf2jbU+6iayTvzaY6/BiotuRS0qyEUkx3QglT4U958A==", + "dev": true, + "requires": { + "@octokit/types": "^2.11.1", + "is-plain-object": "^3.0.0", + "universal-user-agent": "^5.0.0" + }, + "dependencies": { + "is-plain-object": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.0.tgz", + "integrity": "sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==", + "dev": true, + "requires": { + "isobject": "^4.0.0" + } + }, + "isobject": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", + "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==", + "dev": true + }, + "universal-user-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-5.0.0.tgz", + "integrity": "sha512-B5TPtzZleXyPrUMKCpEHFmVhMN6EhmJYjG5PQna9s7mXeSqGTLap4OpqLl5FCEFUI3UBmllkETwKf/db66Y54Q==", + "dev": true, + "requires": { + "os-name": "^3.1.0" + } + } + } + }, + "@octokit/plugin-enterprise-rest": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-3.6.2.tgz", + "integrity": "sha512-3wF5eueS5OHQYuAEudkpN+xVeUsg8vYEMMenEzLphUZ7PRZ8OJtDcsreL3ad9zxXmBbaFWzLmFcdob5CLyZftA==", + "dev": true + }, + "@octokit/plugin-paginate-rest": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-1.1.2.tgz", + "integrity": "sha512-jbsSoi5Q1pj63sC16XIUboklNw+8tL9VOnJsWycWYR78TKss5PVpIPb1TUUcMQ+bBh7cY579cVAWmf5qG+dw+Q==", + "dev": true, + "requires": { + "@octokit/types": "^2.0.1" + } + }, + "@octokit/plugin-request-log": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.0.tgz", + "integrity": "sha512-ywoxP68aOT3zHCLgWZgwUJatiENeHE7xJzYjfz8WI0goynp96wETBF+d95b8g/uL4QmS6owPVlaxiz3wyMAzcw==", + "dev": true + }, + "@octokit/plugin-rest-endpoint-methods": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-2.4.0.tgz", + "integrity": "sha512-EZi/AWhtkdfAYi01obpX0DF7U6b1VRr30QNQ5xSFPITMdLSfhcBqjamE3F+sKcxPbD7eZuMHu3Qkk2V+JGxBDQ==", + "dev": true, + "requires": { + "@octokit/types": "^2.0.1", + "deprecation": "^2.3.1" + } + }, + "@octokit/request": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.4.2.tgz", + "integrity": "sha512-zKdnGuQ2TQ2vFk9VU8awFT4+EYf92Z/v3OlzRaSh4RIP0H6cvW1BFPXq4XYvNez+TPQjqN+0uSkCYnMFFhcFrw==", + "dev": true, + "requires": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.0.0", + "@octokit/types": "^2.11.1", + "deprecation": "^2.0.0", + "is-plain-object": "^3.0.0", + "node-fetch": "^2.3.0", + "once": "^1.4.0", + "universal-user-agent": "^5.0.0" + }, + "dependencies": { + "@octokit/request-error": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.0.tgz", + "integrity": "sha512-rtYicB4Absc60rUv74Rjpzek84UbVHGHJRu4fNVlZ1mCcyUPPuzFfG9Rn6sjHrd95DEsmjSt1Axlc699ZlbDkw==", + "dev": true, + "requires": { + "@octokit/types": "^2.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "is-plain-object": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.0.tgz", + "integrity": "sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==", + "dev": true, + "requires": { + "isobject": "^4.0.0" + } + }, + "isobject": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", + "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==", + "dev": true + }, + "node-fetch": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", + "dev": true + }, + "universal-user-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-5.0.0.tgz", + "integrity": "sha512-B5TPtzZleXyPrUMKCpEHFmVhMN6EhmJYjG5PQna9s7mXeSqGTLap4OpqLl5FCEFUI3UBmllkETwKf/db66Y54Q==", + "dev": true, + "requires": { + "os-name": "^3.1.0" + } + } + } + }, + "@octokit/request-error": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-1.2.1.tgz", + "integrity": "sha512-+6yDyk1EES6WK+l3viRDElw96MvwfJxCt45GvmjDUKWjYIb3PJZQkq3i46TwGwoPD4h8NmTrENmtyA1FwbmhRA==", + "dev": true, + "requires": { + "@octokit/types": "^2.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "@octokit/rest": { + "version": "16.43.1", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.43.1.tgz", + "integrity": "sha512-gfFKwRT/wFxq5qlNjnW2dh+qh74XgTQ2B179UX5K1HYCluioWj8Ndbgqw2PVqa1NnVJkGHp2ovMpVn/DImlmkw==", + "dev": true, + "requires": { + "@octokit/auth-token": "^2.4.0", + "@octokit/plugin-paginate-rest": "^1.1.1", + "@octokit/plugin-request-log": "^1.0.0", + "@octokit/plugin-rest-endpoint-methods": "2.4.0", + "@octokit/request": "^5.2.0", + "@octokit/request-error": "^1.0.2", + "atob-lite": "^2.0.0", + "before-after-hook": "^2.0.0", + "btoa-lite": "^1.0.0", + "deprecation": "^2.0.0", + "lodash.get": "^4.4.2", + "lodash.set": "^4.3.2", + "lodash.uniq": "^4.5.0", + "octokit-pagination-methods": "^1.1.0", + "once": "^1.4.0", + "universal-user-agent": "^4.0.0" + } + }, + "@octokit/types": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.14.0.tgz", + "integrity": "sha512-1w2wxpN45rEXPDFeB7rGain7wcJ/aTRg8bdILITVnS0O7a4zEGELa3JmIe+jeLdekQjvZRbVfNPqS+mi5fKCKQ==", + "dev": true, + "requires": { + "@types/node": ">= 8" + } + }, "@samverschueren/stream-to-observable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", @@ -4671,6 +6907,12 @@ "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==", "dev": true }, + "@types/mime-types": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz", + "integrity": "sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM=", + "dev": true + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -4829,37 +7071,380 @@ } } }, - "@wordpress/e2e-test-utils": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@wordpress/e2e-test-utils/-/e2e-test-utils-4.3.1.tgz", - "integrity": "sha512-5/JWB68PaXH8eYLwMc1CfmJcAwSIySuBBJA6KyizV+kXRh45KNqkqRO6XluhUsgzDP5WhrBvF8XmATDpmntptw==", + "@webassemblyjs/ast": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", + "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", "dev": true, "requires": { - "@babel/runtime": "^7.8.3", - "@wordpress/keycodes": "^2.9.0", - "@wordpress/url": "^2.11.0", + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", + "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", + "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", + "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", + "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", + "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", + "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "mamacro": "^0.0.3" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", + "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", + "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", + "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", + "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", + "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", + "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/helper-wasm-section": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-opt": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", + "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", + "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", + "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", + "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/floating-point-hex-parser": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-code-frame": "1.8.5", + "@webassemblyjs/helper-fsm": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", + "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@woocommerce/e2e-environment": { + "version": "file:tests/e2e/env", + "dev": true, + "requires": { + "@wordpress/e2e-test-utils": "^4.6.0", + "@wordpress/jest-preset-default": "^5.4.0", + "app-root-path": "^3.0.0", + "jest": "^25.1.0", + "jest-puppeteer": "^4.4.0", + "puppeteer": "^2.1.1" + }, + "dependencies": { + "agent-base": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", + "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", + "dev": true + }, + "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" + } + }, + "https-proxy-agent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", + "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", + "dev": true, + "requires": { + "agent-base": "5", + "debug": "4" + } + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "puppeteer": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-2.1.1.tgz", + "integrity": "sha512-LWzaDVQkk1EPiuYeTOj+CZRIjda4k2s5w4MK4xoH2+kgWV/SDlkYHmxatDdtYrciHUKSXTsGgPgPP8ILVdBsxg==", + "dev": true, + "requires": { + "@types/mime-types": "^2.1.0", + "debug": "^4.1.0", + "extract-zip": "^1.6.6", + "https-proxy-agent": "^4.0.0", + "mime": "^2.0.3", + "mime-types": "^2.1.25", + "progress": "^2.0.1", + "proxy-from-env": "^1.0.0", + "rimraf": "^2.6.1", + "ws": "^6.1.0" + } + } + } + }, + "@wordpress/babel-plugin-import-jsx-pragma": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@wordpress/babel-plugin-import-jsx-pragma/-/babel-plugin-import-jsx-pragma-1.1.3.tgz", + "integrity": "sha512-WkVeFZpM5yuHigWe8llZDeMRa4bhMQoHu9dzs1s3cmB1do2mhk341Iw34FidWto14Dzd+383K71vxJejqjKOwQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.0.0" + } + }, + "@wordpress/babel-preset-default": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@wordpress/babel-preset-default/-/babel-preset-default-3.0.2.tgz", + "integrity": "sha512-bsa4piS4GU02isj2XJNUgSEC7MpzdYNy9wOFySrp8G6IHAvwrlwcPEXJf5EuwE8ZqTMmFAzPyKOHFEAx/j+J1A==", + "dev": true, + "requires": { + "@babel/core": "^7.0.0", + "@babel/plugin-proposal-async-generator-functions": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/preset-env": "^7.0.0", + "@babel/runtime": "^7.0.0", + "@wordpress/browserslist-config": "^2.2.3", + "babel-core": "^7.0.0-bridge.0" + } + }, + "@wordpress/browserslist-config": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@wordpress/browserslist-config/-/browserslist-config-2.6.0.tgz", + "integrity": "sha512-vRgzGoxhcNVChBP30XZlyK4w6r/9ZpO+Fi1dzmButp31lUEb1pT5WBxTIQl3HE0JZ9YTEJ00WWGO5sjGi5MHZA==", + "dev": true + }, + "@wordpress/e2e-test-utils": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@wordpress/e2e-test-utils/-/e2e-test-utils-4.6.0.tgz", + "integrity": "sha512-oqnFEOuWkUFwzSVGeKZOfs9YhWVyCKdsOtJKnXd6Vv5Q1quq2fmbDp6HL+dIUI2DlJZISUmOWG4B37mMVA0DLg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.9.2", + "@wordpress/keycodes": "^2.12.0", + "@wordpress/url": "^2.14.0", "lodash": "^4.17.15", "node-fetch": "^1.7.3" }, "dependencies": { "@babel/runtime": { - "version": "7.9.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", - "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.6.tgz", + "integrity": "sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ==", "dev": true, "requires": { "regenerator-runtime": "^0.13.4" } }, - "@wordpress/url": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@wordpress/url/-/url-2.11.0.tgz", - "integrity": "sha512-x7vac1Up64lxX7j69f1OYMcC61gADnz4iFYocJCPPioPjkp3OX1sTPIwBOARw/T/EzwRLSFJsyfEcxr7hJhCSw==", + "@tannin/compile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@tannin/compile/-/compile-1.1.0.tgz", + "integrity": "sha512-n8m9eNDfoNZoxdvWiTfW/hSPhehzLJ3zW7f8E7oT6mCROoMNWCB4TYtv041+2FMAxweiE0j7i1jubQU4MEC/Gg==", "dev": true, "requires": { - "@babel/runtime": "^7.8.3", + "@tannin/evaluate": "^1.2.0", + "@tannin/postfix": "^1.1.0" + } + }, + "@tannin/evaluate": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@tannin/evaluate/-/evaluate-1.2.0.tgz", + "integrity": "sha512-3ioXvNowbO/wSrxsDG5DKIMxC81P0QrQTYai8zFNY+umuoHWRPbQ/TuuDEOju9E+jQDXmj6yI5GyejNuh8I+eg==", + "dev": true + }, + "@tannin/plural-forms": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@tannin/plural-forms/-/plural-forms-1.1.0.tgz", + "integrity": "sha512-xl9R2mDZO/qiHam1AgMnAES6IKIg7OBhcXqy6eDsRCdXuxAFPcjrej9HMjyCLE0DJ/8cHf0i5OQTstuBRhpbHw==", + "dev": true, + "requires": { + "@tannin/compile": "^1.1.0" + } + }, + "@tannin/postfix": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@tannin/postfix/-/postfix-1.1.0.tgz", + "integrity": "sha512-oocsqY7g0cR+Gur5jRQLSrX2OtpMLMse1I10JQBm8CdGMrDkh1Mg2gjsiquMHRtBs4Qwu5wgEp5GgIYHk4SNPw==", + "dev": true + }, + "@wordpress/i18n": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-3.12.0.tgz", + "integrity": "sha512-QkdHd2Z2yTFItBnnzzjMW4IXJlofWMivct4BkgwRivrG7kLxE7nd2xMG3+hFkkdYGdzE67u8vmin0gmQ+14yPA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.9.2", + "gettext-parser": "^1.3.1", "lodash": "^4.17.15", - "qs": "^6.5.2" + "memize": "^1.1.0", + "sprintf-js": "^1.1.1", + "tannin": "^1.2.0" + } + }, + "@wordpress/keycodes": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@wordpress/keycodes/-/keycodes-2.12.0.tgz", + "integrity": "sha512-7fUwfquRLmE4CvJahZTHdNn31heoDcyZ4acgEQR4iKYsKjX6dF1coZjUe693xbf/4r8GmsOg0/uYDImMdDm+1Q==", + "dev": true, + "requires": { + "@babel/runtime": "^7.9.2", + "@wordpress/i18n": "^3.12.0", + "lodash": "^4.17.15" + } + }, + "@wordpress/url": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@wordpress/url/-/url-2.14.0.tgz", + "integrity": "sha512-TSp6vDpmBTiYTwhlc5mleT4g3mOsw2w5bu5AcqiX344o48rju+ktuTZBQofNIhl3m04zYtl6YR14M1dsXKTsNQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.9.2", + "lodash": "^4.17.15", + "qs": "^6.5.2", + "react-native-url-polyfill": "^1.1.2" } }, "lodash": { @@ -4868,11 +7453,26 @@ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, + "memize": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/memize/-/memize-1.1.0.tgz", + "integrity": "sha512-K4FcPETOMTwe7KL2LK0orMhpOmWD2wRGwWWpbZy0fyArwsyIKR8YJVz8+efBAh3BO4zPqlSICu4vsLTRRqtFAg==", + "dev": true + }, "regenerator-runtime": { "version": "0.13.5", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", "dev": true + }, + "tannin": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tannin/-/tannin-1.2.0.tgz", + "integrity": "sha512-U7GgX/RcSeUETbV7gYgoz8PD7Ni4y95pgIP/Z6ayI3CfhSujwKEBlGFTCRN+Aqnuyf4AN2yHL+L8x+TCGjb9uA==", + "dev": true, + "requires": { + "@tannin/plural-forms": "^1.1.0" + } } } }, @@ -4907,6 +7507,1140 @@ } } }, + "@wordpress/jest-console": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@wordpress/jest-console/-/jest-console-3.6.0.tgz", + "integrity": "sha512-0XpvIvgjdmVYYAA0l2XUktq+Z18upDhvaMFDdK8JDxu+vsso0XyFee5VNyHd/PvjInPrTXHoqGj0tx48uUqxhQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.9.2", + "jest-matcher-utils": "^25.3.0", + "lodash": "^4.17.15" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.6.tgz", + "integrity": "sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@jest/types": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.5.0.tgz", + "integrity": "sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^3.0.0" + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "diff-sequences": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz", + "integrity": "sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-diff": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.5.0.tgz", + "integrity": "sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "diff-sequences": "^25.2.6", + "jest-get-type": "^25.2.6", + "pretty-format": "^25.5.0" + } + }, + "jest-get-type": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", + "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", + "dev": true + }, + "jest-matcher-utils": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-25.5.0.tgz", + "integrity": "sha512-VWI269+9JS5cpndnpCwm7dy7JtGQT30UHfrnM3mXl22gHGt/b7NkjBqXfbhZ8V4B7ANUsjK18PlSBmG0YH7gjw==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "jest-diff": "^25.5.0", + "jest-get-type": "^25.2.6", + "pretty-format": "^25.5.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "pretty-format": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.5.0.tgz", + "integrity": "sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ==", + "dev": true, + "requires": { + "@jest/types": "^25.5.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@wordpress/jest-preset-default": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@wordpress/jest-preset-default/-/jest-preset-default-5.5.0.tgz", + "integrity": "sha512-LlO+cfKLN+insAcd1elXk5WIuXZBnBOeUQ/lnuOsd2cQfH5/y6ZvvBx1B3GSJJII8DM+SxAfi+I9f6HH8Fu3iw==", + "dev": true, + "requires": { + "@jest/reporters": "^24.8.0", + "@wordpress/jest-console": "^3.5.0", + "babel-jest": "^24.9.0", + "enzyme": "^3.9.0", + "enzyme-adapter-react-16": "^1.10.0", + "enzyme-to-json": "^3.3.5" + }, + "dependencies": { + "@jest/console": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", + "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "dev": true, + "requires": { + "@jest/source-map": "^24.9.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" + } + }, + "@jest/environment": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", + "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", + "dev": true, + "requires": { + "@jest/fake-timers": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/fake-timers": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", + "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/reporters": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.9.0.tgz", + "integrity": "sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.2", + "istanbul-lib-coverage": "^2.0.2", + "istanbul-lib-instrument": "^3.0.1", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.1", + "istanbul-reports": "^2.2.6", + "jest-haste-map": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "node-notifier": "^5.4.2", + "slash": "^2.0.0", + "source-map": "^0.6.0", + "string-length": "^2.0.0" + } + }, + "@jest/source-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", + "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", + "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "dev": true, + "requires": { + "@jest/console": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/istanbul-lib-coverage": "^2.0.0" + } + }, + "@jest/test-sequencer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz", + "integrity": "sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==", + "dev": true, + "requires": { + "@jest/test-result": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0" + } + }, + "@jest/transform": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", + "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^24.9.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.9.0", + "jest-regex-util": "^24.9.0", + "jest-util": "^24.9.0", + "micromatch": "^3.1.10", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" + } + }, + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@types/yargs": { + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", + "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "babel-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", + "integrity": "sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==", + "dev": true, + "requires": { + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.9.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", + "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.3.0", + "test-exclude": "^5.2.3" + } + }, + "babel-plugin-jest-hoist": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz", + "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==", + "dev": true, + "requires": { + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", + "integrity": "sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==", + "dev": true, + "requires": { + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.9.0" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "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" + } + } + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "cssstyle": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", + "dev": true, + "requires": { + "cssom": "0.3.x" + } + }, + "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" + } + }, + "diff-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", + "dev": true + }, + "expect": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", + "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-styles": "^3.2.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.9.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "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" + } + } + } + }, + "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" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "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" + } + } + } + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + } + }, + "istanbul-reports": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", + "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0" + } + }, + "jest-config": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", + "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.9.0", + "@jest/types": "^24.9.0", + "babel-jest": "^24.9.0", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.9.0", + "jest-environment-node": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.9.0", + "realpath-native": "^1.1.0" + } + }, + "jest-diff": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", + "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-docblock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.9.0.tgz", + "integrity": "sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA==", + "dev": true, + "requires": { + "detect-newline": "^2.1.0" + } + }, + "jest-each": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.9.0.tgz", + "integrity": "sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-environment-jsdom": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz", + "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0", + "jsdom": "^11.5.1" + } + }, + "jest-environment-node": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.9.0.tgz", + "integrity": "sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0" + } + }, + "jest-get-type": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "dev": true + }, + "jest-haste-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", + "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "anymatch": "^2.0.0", + "fb-watchman": "^2.0.0", + "fsevents": "^1.2.7", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.9.0", + "micromatch": "^3.1.10", + "sane": "^4.0.3", + "walker": "^1.0.7" + } + }, + "jest-jasmine2": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz", + "integrity": "sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "co": "^4.6.0", + "expect": "^24.9.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0", + "throat": "^4.0.0" + } + }, + "jest-leak-detector": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz", + "integrity": "sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==", + "dev": true, + "requires": { + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-matcher-utils": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", + "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-message-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", + "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + } + }, + "jest-mock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", + "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0" + } + }, + "jest-regex-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", + "dev": true + }, + "jest-resolve": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", + "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^1.1.0" + } + }, + "jest-runner": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.9.0.tgz", + "integrity": "sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.4.2", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-docblock": "^24.3.0", + "jest-haste-map": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-leak-detector": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "source-map-support": "^0.5.6", + "throat": "^4.0.0" + } + }, + "jest-runtime": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.9.0.tgz", + "integrity": "sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/source-map": "^24.3.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "strip-bom": "^3.0.0", + "yargs": "^13.3.0" + } + }, + "jest-serializer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", + "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", + "dev": true + }, + "jest-snapshot": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz", + "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "expect": "^24.9.0", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.9.0", + "semver": "^6.2.0" + } + }, + "jest-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", + "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "dev": true, + "requires": { + "@jest/console": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/source-map": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "callsites": "^3.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1", + "slash": "^2.0.0", + "source-map": "^0.6.0" + } + }, + "jest-validate": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", + "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "camelcase": "^5.3.1", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "leven": "^3.1.0", + "pretty-format": "^24.9.0" + } + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + } + }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "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" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node-notifier": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", + "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", + "dev": true, + "requires": { + "growly": "^1.3.0", + "is-wsl": "^1.1.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "string-length": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "dev": true, + "requires": { + "astral-regex": "^1.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "dev": true, + "requires": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + } + }, + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", + "dev": true + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "write-file-atomic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", + "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, "@wordpress/keycodes": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/@wordpress/keycodes/-/keycodes-2.9.0.tgz", @@ -4970,6 +8704,39 @@ } } }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "@zkochan/cmd-shim": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@zkochan/cmd-shim/-/cmd-shim-3.1.0.tgz", + "integrity": "sha512-o8l0+x7C7sMZU3v9GuJIAU10qQLtwR1dtRQIOmlNMtyaqhmpXOzx1HWiYoWfmmf9HHZoAkXpc9TM9PQYF9d4Jg==", + "dev": true, + "requires": { + "is-windows": "^1.0.0", + "mkdirp-promise": "^5.0.1", + "mz": "^2.5.0" + } + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, "abab": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", @@ -5027,6 +8794,15 @@ "es6-promisify": "^5.0.0" } }, + "agentkeepalive": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz", + "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==", + "dev": true, + "requires": { + "humanize-ms": "^1.2.1" + } + }, "aggregate-error": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", @@ -5045,6 +8821,24 @@ } } }, + "airbnb-prop-types": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.15.0.tgz", + "integrity": "sha512-jUh2/hfKsRjNFC4XONQrxo/n/3GG4Tn6Hl0WlFQN5PY9OMC9loSCoAYKnZsWaP8wEfd5xcrPloK0Zg6iS1xwVA==", + "dev": true, + "requires": { + "array.prototype.find": "^2.1.0", + "function.prototype.name": "^1.1.1", + "has": "^1.0.3", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object.assign": "^4.1.0", + "object.entries": "^1.1.0", + "prop-types": "^15.7.2", + "prop-types-exact": "^1.2.0", + "react-is": "^16.9.0" + } + }, "ajv": { "version": "6.10.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", @@ -5057,6 +8851,18 @@ "uri-js": "^4.2.2" } }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "dev": true + }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", @@ -5096,6 +8902,12 @@ "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", "dev": true }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", + "dev": true + }, "anymatch": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", @@ -5207,6 +9019,12 @@ } } }, + "app-root-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz", + "integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==", + "dev": true + }, "append-transform": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", @@ -5267,18 +9085,36 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, + "array-differ": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-2.1.0.tgz", + "integrity": "sha512-KbUpJgx909ZscOc/7CLATBFam7P1Z1QRQInvgT0UztM9Q72aGKCunKASAl7WNW0tnPmPyEMeMhdsfWhfmW037w==", + "dev": true + }, "array-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", "dev": true }, + "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 + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, + "array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", + "dev": true + }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", @@ -5300,12 +9136,38 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, + "array.prototype.find": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.1.1.tgz", + "integrity": "sha512-mi+MYNJYLTx2eNYy+Yh6raoQacCsNeeMUaspFPh9Y141lFSsWxxB8V9mM2ye+eqiRs917J6/pJ4M9ZPzenWckA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.4" + } + }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "dev": true + }, "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -5315,6 +9177,44 @@ "safer-buffer": "~2.1.0" } }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -5349,8 +9249,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true, - "optional": true + "dev": true }, "async-foreach": { "version": "0.1.3", @@ -5376,6 +9275,12 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, + "atob-lite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz", + "integrity": "sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY=", + "dev": true + }, "autoprefixer": { "version": "9.7.5", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.7.5.tgz", @@ -5520,6 +9425,12 @@ } } }, + "babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", + "dev": true + }, "babel-eslint": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", @@ -6306,19 +10217,29 @@ "tweetnacl": "^0.14.3" } }, + "before-after-hook": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.1.0.tgz", + "integrity": "sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A==", + "dev": true + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, "binary-extensions": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true, - "optional": true + "dev": true }, "bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "dev": true, - "optional": true, "requires": { "file-uri-to-path": "1.0.0" } @@ -6338,6 +10259,12 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, "body": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", @@ -6350,6 +10277,12 @@ "safe-json-parse": "~1.0.1" } }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -6369,6 +10302,12 @@ "fill-range": "^7.0.1" } }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, "browser-process-hrtime": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", @@ -6398,6 +10337,77 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, "browserslist": { "version": "4.11.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.11.1.tgz", @@ -6419,14 +10429,29 @@ "node-int64": "^0.4.0" } }, + "btoa-lite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", + "integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc=", + "dev": true + }, "buffer": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.5.0.tgz", - "integrity": "sha512-9FTEDjLjwoAkEwyMGDjYJQN2gfRgOKBKRfiglhvibGbpeeU/pQn1bJxQqm32OD/AIeEuHxU9roxXxg34Byp/Ww==", + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", "dev": true, "requires": { "base64-js": "^1.0.2", - "ieee754": "^1.1.4" + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } } }, "buffer-from": { @@ -6435,12 +10460,102 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", + "dev": true + }, + "byline": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", + "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=", + "dev": true + }, + "byte-size": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/byte-size/-/byte-size-5.0.1.tgz", + "integrity": "sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw==", + "dev": true + }, "bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", "dev": true }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + }, + "dependencies": { + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -6628,12 +10743,25 @@ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true }, + "cheerio": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", + "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", + "dev": true, + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.1", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash": "^4.15.0", + "parse5": "^3.0.1" + } + }, "chokidar": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", "dev": true, - "optional": true, "requires": { "anymatch": "^2.0.0", "async-each": "^1.0.1", @@ -6654,7 +10782,6 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, - "optional": true, "requires": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", @@ -6673,7 +10800,6 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, - "optional": true, "requires": { "is-extendable": "^0.1.0" } @@ -6683,7 +10809,6 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, - "optional": true, "requires": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", @@ -6696,7 +10821,6 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, - "optional": true, "requires": { "is-glob": "^3.1.0", "path-dirname": "^1.0.0" @@ -6707,7 +10831,6 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, - "optional": true, "requires": { "is-extglob": "^2.1.0" } @@ -6719,7 +10842,6 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, - "optional": true, "requires": { "kind-of": "^3.0.2" } @@ -6728,17 +10850,41 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "optional": true + "dev": true } } }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, "ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "cjk-regex": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/cjk-regex/-/cjk-regex-1.0.2.tgz", @@ -6789,16 +10935,6 @@ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true }, - "cli": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", - "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", - "dev": true, - "requires": { - "exit": "0.1.2", - "glob": "^7.1.1" - } - }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -6954,6 +11090,12 @@ } } }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, "clone-deep": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", @@ -7045,6 +11187,33 @@ "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", "dev": true }, + "columnify": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz", + "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=", + "dev": true, + "requires": { + "strip-ansi": "^3.0.0", + "wcwidth": "^1.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, "combined-stream": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", @@ -7066,10 +11235,31 @@ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, + "compare-func": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.2.tgz", + "integrity": "sha1-md0LpFfh+bxyKxLAjsM+6rMfpkg=", + "dev": true, + "requires": { + "array-ify": "^1.0.0", + "dot-prop": "^3.0.0" + }, + "dependencies": { + "dot-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz", + "integrity": "sha1-G3CK8JSknJoOfbyteQq6U52sEXc=", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + } + } + }, "compare-versions": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.5.1.tgz", - "integrity": "sha512-9fGPIB7C6AyM18CJJBHt5EnCZDG3oiTJYy0NjfIAGjKpzv0tkxWko7TNQHF5ymqm7IH03tqmeuBxtvD+Izh6mg==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", "dev": true }, "component-emitter": { @@ -7105,27 +11295,904 @@ "json5": "^2.1.1" } }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", "dev": true, "requires": { - "date-now": "^0.1.4" + "ini": "^1.3.4", + "proto-list": "~1.2.1" } }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, "continuable-cache": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", "integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=", "dev": true }, + "conventional-changelog-angular": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.6.tgz", + "integrity": "sha512-QDEmLa+7qdhVIv8sFZfVxU1VSyVvnXPsxq8Vam49mKUcO1Z8VTLEJk9uI21uiJUsnmm0I4Hrsdc9TgkOQo9WSA==", + "dev": true, + "requires": { + "compare-func": "^1.3.1", + "q": "^1.5.1" + } + }, + "conventional-changelog-core": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-3.2.3.tgz", + "integrity": "sha512-LMMX1JlxPIq/Ez5aYAYS5CpuwbOk6QFp8O4HLAcZxe3vxoCtABkhfjetk8IYdRB9CDQGwJFLR3Dr55Za6XKgUQ==", + "dev": true, + "requires": { + "conventional-changelog-writer": "^4.0.6", + "conventional-commits-parser": "^3.0.3", + "dateformat": "^3.0.0", + "get-pkg-repo": "^1.0.0", + "git-raw-commits": "2.0.0", + "git-remote-origin-url": "^2.0.0", + "git-semver-tags": "^2.0.3", + "lodash": "^4.2.1", + "normalize-package-data": "^2.3.5", + "q": "^1.5.1", + "read-pkg": "^3.0.0", + "read-pkg-up": "^3.0.0", + "through2": "^3.0.0" + }, + "dependencies": { + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "through2": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz", + "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==", + "dev": true, + "requires": { + "readable-stream": "2 || 3" + } + } + } + }, + "conventional-changelog-preset-loader": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.0.tgz", + "integrity": "sha512-/rHb32J2EJnEXeK4NpDgMaAVTFZS3o1ExmjKMtYVgIC4MQn0vkNSbYpdGRotkfGGRWiqk3Ri3FBkiZGbAfIfOQ==", + "dev": true + }, + "conventional-changelog-writer": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.0.11.tgz", + "integrity": "sha512-g81GQOR392I+57Cw3IyP1f+f42ME6aEkbR+L7v1FBBWolB0xkjKTeCWVguzRrp6UiT1O6gBpJbEy2eq7AnV1rw==", + "dev": true, + "requires": { + "compare-func": "^1.3.1", + "conventional-commits-filter": "^2.0.2", + "dateformat": "^3.0.0", + "handlebars": "^4.4.0", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.15", + "meow": "^5.0.0", + "semver": "^6.0.0", + "split": "^1.0.0", + "through2": "^3.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" + } + }, + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, + "meow": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", + "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==", + "dev": true, + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0", + "yargs-parser": "^10.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + }, + "through2": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz", + "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==", + "dev": true, + "requires": { + "readable-stream": "2 || 3" + } + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "conventional-commits-filter": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.2.tgz", + "integrity": "sha512-WpGKsMeXfs21m1zIw4s9H5sys2+9JccTzpN6toXtxhpw2VNF2JUXwIakthKBy+LN4DvJm+TzWhxOMWOs1OFCFQ==", + "dev": true, + "requires": { + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.0" + } + }, + "conventional-commits-parser": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.0.8.tgz", + "integrity": "sha512-YcBSGkZbYp7d+Cr3NWUeXbPDFUN6g3SaSIzOybi8bjHL5IJ5225OSCxJJ4LgziyEJ7AaJtE9L2/EU6H7Nt/DDQ==", + "dev": true, + "requires": { + "JSONStream": "^1.0.4", + "is-text-path": "^1.0.1", + "lodash": "^4.17.15", + "meow": "^5.0.0", + "split2": "^2.0.0", + "through2": "^3.0.0", + "trim-off-newlines": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, + "meow": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", + "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==", + "dev": true, + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0", + "yargs-parser": "^10.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + }, + "through2": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz", + "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==", + "dev": true, + "requires": { + "readable-stream": "2 || 3" + } + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "conventional-recommended-bump": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-5.0.1.tgz", + "integrity": "sha512-RVdt0elRcCxL90IrNP0fYCpq1uGt2MALko0eyeQ+zQuDVWtMGAy9ng6yYn3kax42lCj9+XBxQ8ZN6S9bdKxDhQ==", + "dev": true, + "requires": { + "concat-stream": "^2.0.0", + "conventional-changelog-preset-loader": "^2.1.1", + "conventional-commits-filter": "^2.0.2", + "conventional-commits-parser": "^3.0.3", + "git-raw-commits": "2.0.0", + "git-semver-tags": "^2.0.3", + "meow": "^4.0.0", + "q": "^1.5.1" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" + } + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, + "meow": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", + "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==", + "dev": true, + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist": "^1.1.3", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true + } + } + }, "convert-source-map": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", @@ -7135,6 +12202,20 @@ "safe-buffer": "~5.1.1" } }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -7211,6 +12292,43 @@ } } }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "cross-env": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-6.0.3.tgz", @@ -7276,6 +12394,43 @@ "which": "^1.2.9" } }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", + "dev": true + }, "cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -7324,6 +12479,21 @@ "fs-exists-sync": "^0.1.0" } }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true + }, + "dargs": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz", + "integrity": "sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -7356,12 +12526,6 @@ "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", "dev": true }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true - }, "dateformat": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", @@ -7372,6 +12536,16 @@ "meow": "^3.3.0" } }, + "deasync": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.19.tgz", + "integrity": "sha512-oh3MRktfnPlLysCPpBpKZZzb4cUC/p0aA3SyRGp15lN30juJBTo/CiD0d4fR+f1kBtUQoJj1NE9RPNWQ7BQ9Mg==", + "dev": true, + "requires": { + "bindings": "^1.5.0", + "node-addon-api": "^1.7.1" + } + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -7381,6 +12555,12 @@ "ms": "2.0.0" } }, + "debuglog": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", + "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=", + "dev": true + }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -7433,6 +12613,15 @@ "strip-bom": "^2.0.0" } }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -7568,6 +12757,28 @@ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true }, + "deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, "detect-indent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", @@ -7583,6 +12794,16 @@ "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", "dev": true }, + "dezalgo": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "dev": true, + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", @@ -7595,6 +12816,17 @@ "integrity": "sha512-nFIfVk5B/NStCsJ+zaPO4vYuLjlzQ6uFvPxzYyHlejNZ/UGa7G/n7peOXVrVNvRuyfstt+mZQYGpjxg9Z6N8Kw==", "dev": true }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -7612,6 +12844,12 @@ } } }, + "discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=", + "dev": true + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -7639,6 +12877,12 @@ } } }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, "domelementtype": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", @@ -7688,6 +12932,18 @@ "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -7746,12 +13002,33 @@ "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", "dev": true }, + "elliptic": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", + "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.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 }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, "encoding": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", @@ -7770,12 +13047,159 @@ "once": "^1.4.0" } }, + "enhanced-resolve": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz", + "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, "entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", "dev": true }, + "env-paths": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", + "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", + "dev": true + }, + "envinfo": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.5.1.tgz", + "integrity": "sha512-hQBkDf2iO4Nv0CNHpCuSBeaSrveU6nThVxFGTrq/eDlV716UQk09zChaJae4mZRsos1x4YLY2TaH3LHUae3ZmQ==", + "dev": true + }, + "enzyme": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.11.0.tgz", + "integrity": "sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==", + "dev": true, + "requires": { + "array.prototype.flat": "^1.2.3", + "cheerio": "^1.0.0-rc.3", + "enzyme-shallow-equal": "^1.0.1", + "function.prototype.name": "^1.1.2", + "has": "^1.0.3", + "html-element-map": "^1.2.0", + "is-boolean-object": "^1.0.1", + "is-callable": "^1.1.5", + "is-number-object": "^1.0.4", + "is-regex": "^1.0.5", + "is-string": "^1.0.5", + "is-subset": "^0.1.1", + "lodash.escape": "^4.0.1", + "lodash.isequal": "^4.5.0", + "object-inspect": "^1.7.0", + "object-is": "^1.0.2", + "object.assign": "^4.1.0", + "object.entries": "^1.1.1", + "object.values": "^1.1.1", + "raf": "^3.4.1", + "rst-selector-parser": "^2.2.3", + "string.prototype.trim": "^1.2.1" + } + }, + "enzyme-adapter-react-16": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.2.tgz", + "integrity": "sha512-SkvDrb8xU3lSxID8Qic9rB8pvevDbLybxPK6D/vW7PrT0s2Cl/zJYuXvsd1EBTz0q4o3iqG3FJhpYz3nUNpM2Q==", + "dev": true, + "requires": { + "enzyme-adapter-utils": "^1.13.0", + "enzyme-shallow-equal": "^1.0.1", + "has": "^1.0.3", + "object.assign": "^4.1.0", + "object.values": "^1.1.1", + "prop-types": "^15.7.2", + "react-is": "^16.12.0", + "react-test-renderer": "^16.0.0-0", + "semver": "^5.7.0" + } + }, + "enzyme-adapter-utils": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.13.0.tgz", + "integrity": "sha512-YuEtfQp76Lj5TG1NvtP2eGJnFKogk/zT70fyYHXK2j3v6CtuHqc8YmgH/vaiBfL8K1SgVVbQXtTcgQZFwzTVyQ==", + "dev": true, + "requires": { + "airbnb-prop-types": "^2.15.0", + "function.prototype.name": "^1.1.2", + "object.assign": "^4.1.0", + "object.fromentries": "^2.0.2", + "prop-types": "^15.7.2", + "semver": "^5.7.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "enzyme-shallow-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.1.tgz", + "integrity": "sha512-hGA3i1so8OrYOZSM9whlkNmVHOicJpsjgTzC+wn2JMJXhq1oO4kA4bJ5MsfzSIcC71aLDKzJ6gZpIxrqt3QTAQ==", + "dev": true, + "requires": { + "has": "^1.0.3", + "object-is": "^1.0.2" + } + }, + "enzyme-to-json": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/enzyme-to-json/-/enzyme-to-json-3.4.4.tgz", + "integrity": "sha512-50LELP/SCPJJGic5rAARvU7pgE3m1YaNj7JLM+Qkhl5t7PAs6fiyc8xzc50RnkKPFQCv0EeFVjEWdIFRGPWMsA==", + "dev": true, + "requires": { + "lodash": "^4.17.15", + "react-is": "^16.12.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + } + } + }, + "err-code": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", + "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=", + "dev": true + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, "error": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", @@ -8087,6 +13511,22 @@ "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", "dev": true }, + "events": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz", + "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, "exec-sh": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz", @@ -8123,12 +13563,6 @@ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", "dev": true }, - "exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", - "dev": true - }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -8429,6 +13863,12 @@ "pend": "~1.2.0" } }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, "figures": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz", @@ -8457,8 +13897,7 @@ "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, - "optional": true + "dev": true }, "fileset": { "version": "2.0.3", @@ -8672,6 +14111,16 @@ "integrity": "sha1-9uvK5h/6GH5CCZnUDOCoAfObJjU=", "dev": true }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, "follow-redirects": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", @@ -8739,18 +14188,68 @@ "map-cache": "^0.2.2" } }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, "fs-exists-sync": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", "dev": true }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + } + } + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dev": true, + "requires": { + "minipass": "^2.6.0" + } + }, "fs-readdir-recursive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", "dev": true }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -9400,12 +14899,29 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "function.prototype.name": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.2.tgz", + "integrity": "sha512-C8A+LlHBJjB2AdcRPorc5JvJ5VUoWlXdEHLOJdCI7kjHEtGTpHQUiqMvCIKUwIsGwZX2jZJy761AXsn356bJQg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "functions-have-names": "^1.2.0" + } + }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "functions-have-names": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.1.tgz", + "integrity": "sha512-j48B/ZI7VKs3sgeI2cZp7WXWmZXu7Iq5pl5/vptV5N2mq+DGFuS/ulaDjtaoLpYzuD6u8UgrUKHfgo7fDTSiBA==", + "dev": true + }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", @@ -9468,6 +14984,12 @@ "globule": "^1.0.0" } }, + "genfun": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz", + "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==", + "dev": true + }, "gensync": { "version": "1.0.0-beta.1", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", @@ -9492,6 +15014,25 @@ "integrity": "sha512-09/VS4iek66Dh2bctjRkowueRJbY1JDGR1L/zRxO1Qk8Uxs6PnqaNSqalpizPT+CDjre3hnEsuzvhgomz9qYrA==", "dev": true }, + "get-pkg-repo": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz", + "integrity": "sha1-xztInAbYDMVTbCyFP54FIyBWly0=", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "meow": "^3.3.0", + "normalize-package-data": "^2.3.0", + "parse-github-repo-url": "^1.3.0", + "through2": "^2.0.0" + } + }, + "get-port": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-4.2.0.tgz", + "integrity": "sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==", + "dev": true + }, "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", @@ -9538,6 +15079,459 @@ "safe-buffer": "^5.1.1" } }, + "git-raw-commits": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.0.tgz", + "integrity": "sha512-w4jFEJFgKXMQJ0H0ikBk2S+4KP2VEjhCvLCNqbNRQC8BgGWgLKNCO7a9K9LI+TVT7Gfoloje502sEnctibffgg==", + "dev": true, + "requires": { + "dargs": "^4.0.1", + "lodash.template": "^4.0.2", + "meow": "^4.0.0", + "split2": "^2.0.0", + "through2": "^2.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, + "meow": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", + "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==", + "dev": true, + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist": "^1.1.3", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true + } + } + }, + "git-remote-origin-url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", + "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", + "dev": true, + "requires": { + "gitconfiglocal": "^1.0.0", + "pify": "^2.3.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "git-semver-tags": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-2.0.3.tgz", + "integrity": "sha512-tj4FD4ww2RX2ae//jSrXZzrocla9db5h0V7ikPl1P/WwoZar9epdUhwR7XHXSgc+ZkNq72BEEerqQuicoEQfzA==", + "dev": true, + "requires": { + "meow": "^4.0.0", + "semver": "^6.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, + "meow": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", + "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==", + "dev": true, + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist": "^1.1.3", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true + } + } + }, + "git-up": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-4.0.1.tgz", + "integrity": "sha512-LFTZZrBlrCrGCG07/dm1aCjjpL1z9L3+5aEeI9SBhAqSc+kiA9Or1bgZhQFNppJX6h/f5McrvJt1mQXTFm6Qrw==", + "dev": true, + "requires": { + "is-ssh": "^1.3.0", + "parse-url": "^5.0.0" + } + }, + "git-url-parse": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.1.2.tgz", + "integrity": "sha512-gZeLVGY8QVKMIkckncX+iCq2/L8PlwncvDFKiWkBn9EtCfYDbliRTTp6qzyQ1VMdITUfq7293zDzfpjdiGASSQ==", + "dev": true, + "requires": { + "git-up": "^4.0.0" + } + }, + "gitconfiglocal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", + "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", + "dev": true, + "requires": { + "ini": "^1.3.2" + } + }, "github-contributors-list": { "version": "https://github.com/woocommerce/github-contributors-list/tarball/master", "integrity": "sha512-4lJ4ERWmcGlG43jDdIy7shG0v3QsfoSvSrtbdcw/cpqF69WBOoHu1iC8Cb3IQ63WU7KujtR0TEF50CEcebhRCA==", @@ -9910,17 +15904,6 @@ "maxmin": "^2.1.0" } }, - "grunt-contrib-jshint": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-2.1.0.tgz", - "integrity": "sha512-65S2/C/6RfjY/umTxfwXXn+wVvaYmykHkHSsW6Q6rhkbv3oudTEgqnFFZvWzWCoHUb+3GMZLbP3oSrNyvshmIQ==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "hooker": "^0.2.3", - "jshint": "~2.10.2" - } - }, "grunt-contrib-uglify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-4.0.1.tgz", @@ -10038,161 +16021,6 @@ } } }, - "grunt-prompt": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/grunt-prompt/-/grunt-prompt-1.3.3.tgz", - "integrity": "sha1-xbQ77DqimqaWKsZhGolnEvy6Z5E=", - "dev": true, - "requires": { - "inquirer": "^0.11.0", - "lodash": "^3.10.1" - }, - "dependencies": { - "ansi-escapes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, - "requires": { - "restore-cursor": "^1.0.1" - } - }, - "cli-width": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-1.1.1.tgz", - "integrity": "sha1-pNKT72frt7iNSk1CwMzwDE0eNm0=", - "dev": true - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } - }, - "inquirer": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.11.4.tgz", - "integrity": "sha1-geM3ToNhvq/y2XAWIG01nQsy+k0=", - "dev": true, - "requires": { - "ansi-escapes": "^1.1.0", - "ansi-regex": "^2.0.0", - "chalk": "^1.0.0", - "cli-cursor": "^1.0.1", - "cli-width": "^1.0.1", - "figures": "^1.3.5", - "lodash": "^3.3.1", - "readline2": "^1.0.1", - "run-async": "^0.1.0", - "rx-lite": "^3.1.2", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.0", - "through": "^2.3.6" - } - }, - "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" - } - }, - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", - "dev": true - }, - "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, - "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" - } - }, - "run-async": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", - "dev": true, - "requires": { - "once": "^1.3.0" - } - }, - "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" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, "grunt-rtlcss": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/grunt-rtlcss/-/grunt-rtlcss-2.0.2.tgz", @@ -10251,34 +16079,6 @@ "integrity": "sha512-90s27H7FoCDcA8C8+R0GwC+ntYD3lG6S/jqcavWm3bn9RiJTmSfOvfbFa1PXx4NbBWuiGQMLfQTj/JvvqT5w6A==", "dev": true }, - "grunt-shell": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/grunt-shell/-/grunt-shell-3.0.1.tgz", - "integrity": "sha512-C8eR4frw/NmIFIwSvzSLS4wOQBUzC+z6QhrKPzwt/tlaIqlzH35i/O2MggVOBj2Sh1tbaAqpASWxGiGsi4JMIQ==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "npm-run-path": "^2.0.0", - "strip-ansi": "^5.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, "grunt-stylelint": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/grunt-stylelint/-/grunt-stylelint-0.14.0.tgz", @@ -10288,6 +16088,190 @@ "chalk": "^2.4.2" } }, + "gruntify-eslint": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/gruntify-eslint/-/gruntify-eslint-5.0.0.tgz", + "integrity": "sha512-pa2sXHK9+U4dCGdGSIMkpJARNwRStdLBsddNxmSHSSWROUdhWMrXvFWm6pj48zJhyV3Qy068VIuF1seYIvc0cw==", + "dev": true, + "requires": { + "eslint": "^5.0.0" + }, + "dependencies": { + "acorn": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.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" + } + }, + "eslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + } + } + }, "gzip-size": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz", @@ -10429,12 +16413,43 @@ } } }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, "homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", @@ -10456,6 +16471,15 @@ "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, + "html-element-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.2.0.tgz", + "integrity": "sha512-0uXq8HsuG1v2TmQ8QkIhzbrqeskE4kn52Q18QJ9iAA/SnHoEKXWiUxHQtclRsCFWEUD2So34X+0+pZZu862nnw==", + "dev": true, + "requires": { + "array-filter": "^1.0.0" + } + }, "html-encoding-sniffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", @@ -10478,44 +16502,65 @@ "dev": true }, "htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", "dev": true, "requires": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" + "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" }, "dependencies": { "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "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 } } }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "dev": true + }, "http-parser-js": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz", "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==", "dev": true }, + "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", @@ -10527,6 +16572,12 @@ "sshpk": "^1.7.0" } }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, "https-proxy-agent": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz", @@ -10560,15 +16611,24 @@ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true }, - "husky": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/husky/-/husky-4.2.1.tgz", - "integrity": "sha512-Qa0lRreeIf4Tl92sSs42ER6qc3hzoyQPPorzOrFWfPEVbdi6LuvJEqWKPk905fOWIR76iBpp7ECZNIwk+a8xuQ==", + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", "dev": true, "requires": { - "chalk": "^3.0.0", + "ms": "^2.0.0" + } + }, + "husky": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.2.5.tgz", + "integrity": "sha512-SYZ95AjKcX7goYVZtVZF2i6XiZcHknw50iXvY7b0MiGoj5RwdgRQNEHdb+gPDPCXKlzwrybjFjkL6FOj8uRhZQ==", + "dev": true, + "requires": { + "chalk": "^4.0.0", "ci-info": "^2.0.0", - "compare-versions": "^3.5.1", + "compare-versions": "^3.6.0", "cosmiconfig": "^6.0.0", "find-versions": "^3.2.0", "opencollective-postinstall": "^2.0.2", @@ -10589,9 +16649,9 @@ } }, "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", + "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -10676,12 +16736,27 @@ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "dev": true }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, "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-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, "import-fresh": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", @@ -10735,6 +16810,12 @@ "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", "dev": true }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -10757,6 +16838,22 @@ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true }, + "init-package-json": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-1.10.3.tgz", + "integrity": "sha512-zKSiXKhQveNteyhcj1CoOP8tqp1QuxPIPBl8Bid99DGLFqA1p87M6lNgfjJHSBoWJJlidGOv5rWjyYKEB3g2Jw==", + "dev": true, + "requires": { + "glob": "^7.1.1", + "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0", + "promzard": "^0.3.0", + "read": "~1.0.1", + "read-package-json": "1 || 2", + "semver": "2.x || 3.x || 4 || 5", + "validate-npm-package-license": "^3.0.1", + "validate-npm-package-name": "^3.0.0" + } + }, "inquirer": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.1.tgz", @@ -10852,6 +16949,12 @@ } } }, + "interpret": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "dev": true + }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -10861,6 +16964,18 @@ "loose-envify": "^1.0.0" } }, + "invert-kv": { + "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": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, "ip-regex": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", @@ -10909,11 +17024,16 @@ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, - "optional": true, "requires": { "binary-extensions": "^1.0.0" } }, + "is-boolean-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.1.tgz", + "integrity": "sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ==", + "dev": true + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -11035,6 +17155,12 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true + }, "is-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", @@ -11106,12 +17232,33 @@ "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", "dev": true }, + "is-ssh": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.1.tgz", + "integrity": "sha512-0eRIASHZt1E68/ixClI8bp2YK2wmBPVWEismTs6M+M099jKgrzl/3E976zIbImSIob48N2/XGe9y7ZiYdImSlg==", + "dev": true, + "requires": { + "protocols": "^1.1.0" + } + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-subset": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", + "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", + "dev": true + }, "is-symbol": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", @@ -11121,6 +17268,15 @@ "has-symbols": "^1.0.0" } }, + "is-text-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", + "dev": true, + "requires": { + "text-extensions": "^1.0.0" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -11158,12 +17314,6 @@ "dev": true, "optional": true }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -13361,30 +19511,6 @@ "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", "dev": true }, - "jshint": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.10.2.tgz", - "integrity": "sha512-e7KZgCSXMJxznE/4WULzybCMNXNAd/bf5TSrvVEq78Q/K8ZwFpmBqQeDtNiHc3l49nV4E/+YeHU/JZjSUIrLAA==", - "dev": true, - "requires": { - "cli": "~1.0.0", - "console-browserify": "1.1.x", - "exit": "0.1.x", - "htmlparser2": "3.8.x", - "lodash": "~4.17.11", - "minimatch": "~3.0.2", - "shelljs": "0.3.x", - "strip-json-comments": "1.0.x" - }, - "dependencies": { - "strip-json-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", - "dev": true - } - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -13432,6 +19558,21 @@ } } }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -13471,12 +19612,92 @@ "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", "dev": true }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, "left-pad": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", "dev": true }, + "lerna": { + "version": "3.20.2", + "resolved": "https://registry.npmjs.org/lerna/-/lerna-3.20.2.tgz", + "integrity": "sha512-bjdL7hPLpU3Y8CBnw/1ys3ynQMUjiK6l9iDWnEGwFtDy48Xh5JboR9ZJwmKGCz9A/sarVVIGwf1tlRNKUG9etA==", + "dev": true, + "requires": { + "@lerna/add": "3.20.0", + "@lerna/bootstrap": "3.20.0", + "@lerna/changed": "3.20.0", + "@lerna/clean": "3.20.0", + "@lerna/cli": "3.18.5", + "@lerna/create": "3.18.5", + "@lerna/diff": "3.18.5", + "@lerna/exec": "3.20.0", + "@lerna/import": "3.18.5", + "@lerna/info": "3.20.0", + "@lerna/init": "3.18.5", + "@lerna/link": "3.18.5", + "@lerna/list": "3.20.0", + "@lerna/publish": "3.20.2", + "@lerna/run": "3.20.0", + "@lerna/version": "3.20.2", + "import-local": "^2.0.0", + "npmlog": "^4.1.2" + }, + "dependencies": { + "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" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, "leven": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", @@ -13847,6 +20068,40 @@ } } }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + } + } + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -13871,12 +20126,54 @@ "integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==", "dev": true }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "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.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": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "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.isboolean": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", "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.ismatch": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", + "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", + "dev": true + }, "lodash.isregexp": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isregexp/-/lodash.isregexp-4.0.1.tgz", @@ -13889,18 +20186,49 @@ "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", "dev": true }, + "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", "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + }, "lodash.unescape": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=", "dev": true }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, "log-symbols": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", @@ -13995,6 +20323,12 @@ "yallist": "^2.1.2" } }, + "macos-release": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.3.0.tgz", + "integrity": "sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA==", + "dev": true + }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -14005,6 +20339,67 @@ "semver": "^5.6.0" } }, + "make-fetch-happen": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz", + "integrity": "sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag==", + "dev": true, + "requires": { + "agentkeepalive": "^3.4.1", + "cacache": "^12.0.0", + "http-cache-semantics": "^3.8.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "node-fetch-npm": "^2.0.2", + "promise-retry": "^1.1.1", + "socks-proxy-agent": "^4.0.0", + "ssri": "^6.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" + } + }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, "makeerror": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", @@ -14014,6 +20409,21 @@ "tmpl": "1.0.x" } }, + "mamacro": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", + "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", @@ -14123,6 +20533,17 @@ } } }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, "mdast-util-compact": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.4.tgz", @@ -14147,6 +20568,16 @@ "integrity": "sha512-Dm8Jhb5kiC4+ynYsVR4QDXKt+o2dfqGuY4hE2x+XlXZkdndlT80bJxfcMv5QGp/FCy6MhG7f5ElpmKPFKOSEpg==", "dev": true }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, "meow": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", @@ -14212,6 +20643,16 @@ "picomatch": "^2.0.5" } }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, "mime": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", @@ -14239,6 +20680,18 @@ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -14264,6 +20717,51 @@ "is-plain-obj": "^1.1.0" } }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + }, + "dependencies": { + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dev": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, "mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", @@ -14312,6 +20810,15 @@ "minimist": "0.0.8" } }, + "mkdirp-promise": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", + "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=", + "dev": true, + "requires": { + "mkdirp": "*" + } + }, "mocha": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.0.1.tgz", @@ -14451,24 +20958,73 @@ } } }, + "modify-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", + "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", + "dev": true + }, "moment": { "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 }, + "moo": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", + "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==", + "dev": true + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, + "multimatch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-3.0.0.tgz", + "integrity": "sha512-22foS/gqQfANZ3o+W7ST2x25ueHDVNWl/b9OlGcLpy/iKxjCpvcNCM51YCenUi7Mt/jAjjqv8JwZRs8YP5sRjA==", + "dev": true, + "requires": { + "array-differ": "^2.0.3", + "array-union": "^1.0.2", + "arrify": "^1.0.1", + "minimatch": "^3.0.4" + } + }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "nan": { "version": "2.13.2", "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", @@ -14520,6 +21076,27 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "nearley": { + "version": "2.19.3", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.19.3.tgz", + "integrity": "sha512-FpAy1PmTsUpOtgxr23g4jRNvJHYzZEW2PixXeSzksLR/ykPfwKhAodc2+9wQhY+JneWLcvkDw6q7FJIsIdF/aQ==", + "dev": true, + "requires": { + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6", + "semver": "^5.4.1" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, "neo-async": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", @@ -14532,6 +21109,12 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node-addon-api": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.1.tgz", + "integrity": "sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ==", + "dev": true + }, "node-environment-flags": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", @@ -14552,6 +21135,17 @@ "is-stream": "^1.0.1" } }, + "node-fetch-npm": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz", + "integrity": "sha512-iOuIQDWDyjhv9qSDrj9aq/klt6F9z1p2otB3AV7v3zBDcL/x+OfGsvGQZZCcMZbUf4Ujw1xGNQkjvGnVT22cKg==", + "dev": true, + "requires": { + "encoding": "^0.1.11", + "json-parse-better-errors": "^1.0.0", + "safe-buffer": "^5.1.1" + } + }, "node-gyp": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", @@ -14586,6 +21180,45 @@ "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", "dev": true }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, "node-modules-regexp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", @@ -14746,6 +21379,157 @@ "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=", "dev": true }, + "normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "dev": true + }, + "npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "dev": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-lifecycle": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/npm-lifecycle/-/npm-lifecycle-3.1.5.tgz", + "integrity": "sha512-lDLVkjfZmvmfvpvBzA4vzee9cn+Me4orq0QF8glbswJVEbIcSNWib7qGOffolysc3teCqbbPZZkzbr3GQZTL1g==", + "dev": true, + "requires": { + "byline": "^5.0.0", + "graceful-fs": "^4.1.15", + "node-gyp": "^5.0.2", + "resolve-from": "^4.0.0", + "slide": "^1.1.6", + "uid-number": "0.0.6", + "umask": "^1.1.0", + "which": "^1.3.1" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "node-gyp": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-5.1.0.tgz", + "integrity": "sha512-OUTryc5bt/P8zVgNUmC6xdXiDJxLMAW8cF5tLQOT9E5sOQj+UeQxnnPy74K3CLCa/SOjjBlbuzDLR8ANwA+wmw==", + "dev": true, + "requires": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.2", + "mkdirp": "^0.5.1", + "nopt": "^4.0.1", + "npmlog": "^4.1.2", + "request": "^2.88.0", + "rimraf": "^2.6.3", + "semver": "^5.7.1", + "tar": "^4.4.12", + "which": "^1.3.1" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + } + } + }, + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "dev": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true + }, + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "dev": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-pick-manifest": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz", + "integrity": "sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1", + "npm-package-arg": "^6.0.0", + "semver": "^5.4.1" + } + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -14767,6 +21551,15 @@ "set-blocking": "~2.0.0" } }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, "num2fraction": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", @@ -14825,6 +21618,43 @@ "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", "dev": true }, + "object-is": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz", + "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + } + } + }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -14860,6 +21690,30 @@ "object-keys": "^1.0.11" } }, + "object.entries": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.1.tgz", + "integrity": "sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "object.fromentries": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", + "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, "object.getownpropertydescriptors": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", @@ -14887,6 +21741,24 @@ } } }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "octokit-pagination-methods": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz", + "integrity": "sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==", + "dev": true + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -14951,12 +21823,58 @@ "word-wrap": "~1.2.3" } }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, + "os-locale": { + "version": "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": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + }, + "dependencies": { + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + } + } + }, + "os-name": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz", + "integrity": "sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==", + "dev": true, + "requires": { + "macos-release": "^2.2.0", + "windows-release": "^3.1.0" + } + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -14973,6 +21891,12 @@ "os-tmpdir": "^1.0.0" } }, + "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-each-series": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.1.0.tgz", @@ -14985,6 +21909,12 @@ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true + }, "p-limit": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", @@ -15012,6 +21942,21 @@ "aggregate-error": "^3.0.0" } }, + "p-map-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-map-series/-/p-map-series-1.0.0.tgz", + "integrity": "sha1-v5j+V1cFZYqeE1G++4WuTB8Hvco=", + "dev": true, + "requires": { + "p-reduce": "^1.0.0" + } + }, + "p-pipe": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-1.2.0.tgz", + "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=", + "dev": true + }, "p-queue": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-2.4.2.tgz", @@ -15040,6 +21985,32 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "p-waterfall": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-waterfall/-/p-waterfall-1.0.0.tgz", + "integrity": "sha1-ftlLPOszMngjU69qrhGqn8I1uwA=", + "dev": true, + "requires": { + "p-reduce": "^1.0.0" + } + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -15049,6 +22020,20 @@ "callsites": "^3.0.0" } }, + "parse-asn1": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", + "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, "parse-entities": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.1.tgz", @@ -15063,6 +22048,12 @@ "is-hexadecimal": "^1.0.0" } }, + "parse-github-repo-url": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz", + "integrity": "sha1-nn2LslKmy2ukJZUGC3v23z28H1A=", + "dev": true + }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -15078,6 +22069,28 @@ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, + "parse-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.1.tgz", + "integrity": "sha512-d7yhga0Oc+PwNXDvQ0Jv1BuWkLVPXcAoQ/WREgd6vNNoKYaW52KI+RdOFjI63wjkmps9yUE8VS4veP+AgpQ/hA==", + "dev": true, + "requires": { + "is-ssh": "^1.3.0", + "protocols": "^1.4.0" + } + }, + "parse-url": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-5.0.1.tgz", + "integrity": "sha512-flNUPP27r3vJpROi0/R3/2efgKkyXqnXwyP1KQ2U0SfFRgdizOdWfvrrvJg1LuOoxs7GQhmxJlq23IpQ/BkByg==", + "dev": true, + "requires": { + "is-ssh": "^1.3.0", + "normalize-url": "^3.3.0", + "parse-path": "^4.0.0", + "protocols": "^1.4.0" + } + }, "parse5": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", @@ -15093,6 +22106,12 @@ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, "path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", @@ -15114,6 +22133,12 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", @@ -15166,6 +22191,19 @@ "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", "dev": true }, + "pbkdf2": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -15814,6 +22852,12 @@ "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", "dev": true }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", @@ -15826,6 +22870,30 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "promise-retry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz", + "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", + "dev": true, + "requires": { + "err-code": "^1.0.0", + "retry": "^0.10.0" + }, + "dependencies": { + "retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", + "dev": true + } + } + }, "prompts": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.0.tgz", @@ -15836,12 +22904,70 @@ "sisteransi": "^1.0.3" } }, + "promzard": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz", + "integrity": "sha1-JqXW7ox97kyxIggwWs+5O6OCqe4=", + "dev": true, + "requires": { + "read": "1" + } + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "prop-types-exact": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prop-types-exact/-/prop-types-exact-1.2.0.tgz", + "integrity": "sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==", + "dev": true, + "requires": { + "has": "^1.0.3", + "object.assign": "^4.1.0", + "reflect.ownkeys": "^0.2.0" + } + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true + }, + "protocols": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.7.tgz", + "integrity": "sha512-Fx65lf9/YDn3hUX08XUc0J8rSux36rEsyiv21ZGUC1mOyeM3lTRpZLcrm8aAolzS4itwVfm7TAPyxC2E5zd6xg==", + "dev": true + }, + "protoduck": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz", + "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==", + "dev": true, + "requires": { + "genfun": "^5.0.0" + } + }, "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", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -15854,6 +22980,20 @@ "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", "dev": true }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -15864,6 +23004,29 @@ "once": "^1.3.1" } }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -17162,12 +24325,68 @@ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", "dev": true }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, "quick-lru": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", "dev": true }, + "raf": { + "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" + } + }, + "railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=", + "dev": true + }, + "randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "dev": true, + "requires": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" + } + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, "raw-body": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", @@ -17200,6 +24419,72 @@ "requires": { "buffer": "^5.4.3", "whatwg-url-without-unicode": "8.0.0-1" + }, + "dependencies": { + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + } + } + }, + "react-test-renderer": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.13.1.tgz", + "integrity": "sha512-Sn2VRyOK2YJJldOqoh8Tn/lWQ+ZiKhyZTPtaO0Q6yNj+QDbmRkVFap6pZPy3YQk8DScRDfyqm/KxKYP9gCMRiQ==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "react-is": "^16.8.6", + "scheduler": "^0.19.1" + } + }, + "read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "dev": true, + "requires": { + "mute-stream": "~0.0.4" + } + }, + "read-cmd-shim": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz", + "integrity": "sha512-v5yCqQ/7okKoZZkBQUAfTsQ3sVJtXdNfbPnI5cceppoxEVLYA3k+VtV2omkeo8MS94JCy4fSiUwlRBAwCVRPUA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2" + } + }, + "read-package-json": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.1.tgz", + "integrity": "sha512-dAiqGtVc/q5doFz6096CcnXhpYk0ZN8dEKVkGLU0CsASt8SrgF6SF7OTKAYubfvFhWaqofl+Y8HK19GR8jwW+A==", + "dev": true, + "requires": { + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "json-parse-better-errors": "^1.0.1", + "normalize-package-data": "^2.0.0", + "npm-normalize-package-bin": "^1.0.0" + } + }, + "read-package-tree": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/read-package-tree/-/read-package-tree-5.3.1.tgz", + "integrity": "sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==", + "dev": true, + "requires": { + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0", + "util-promisify": "^2.1.0" } }, "read-pkg": { @@ -17246,12 +24531,23 @@ } } }, + "readdir-scoped-modules": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", + "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", + "dev": true, + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, "readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, - "optional": true, "requires": { "graceful-fs": "^4.1.11", "micromatch": "^3.1.10", @@ -17263,7 +24559,6 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, - "optional": true, "requires": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", @@ -17282,7 +24577,6 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, - "optional": true, "requires": { "is-extendable": "^0.1.0" } @@ -17294,7 +24588,6 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, - "optional": true, "requires": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", @@ -17307,7 +24600,6 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, - "optional": true, "requires": { "is-extendable": "^0.1.0" } @@ -17319,7 +24611,6 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, - "optional": true, "requires": { "kind-of": "^3.0.2" }, @@ -17329,7 +24620,6 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, - "optional": true, "requires": { "is-buffer": "^1.1.5" } @@ -17340,15 +24630,13 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "optional": true + "dev": true }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, - "optional": true, "requires": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -17367,34 +24655,6 @@ } } }, - "readline2": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", - "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "mute-stream": "0.0.5" - }, - "dependencies": { - "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" - } - }, - "mute-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", - "dev": true - } - } - }, "realpath-native": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", @@ -17414,6 +24674,12 @@ "strip-indent": "^1.0.1" } }, + "reflect.ownkeys": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz", + "integrity": "sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=", + "dev": true + }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", @@ -17870,6 +25136,26 @@ "glob": "^7.1.3" } }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rst-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", + "integrity": "sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=", + "dev": true, + "requires": { + "lodash.flattendeep": "^4.4.0", + "nearley": "^2.7.10" + } + }, "rsvp": { "version": "4.8.5", "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", @@ -17926,18 +25212,21 @@ "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", "dev": true }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, "rx": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=", "dev": true }, - "rx-lite": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", - "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", - "dev": true - }, "rxjs": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", @@ -18267,6 +25556,27 @@ "xmlchars": "^2.1.1" } }, + "scheduler": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, "scss-tokenizer": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", @@ -18306,6 +25616,12 @@ "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", "dev": true }, + "serialize-javascript": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", + "dev": true + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -18335,6 +25651,22 @@ } } }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "shallow-clone": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", @@ -18379,12 +25711,6 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, - "shelljs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", - "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", - "dev": true - }, "shellwords": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", @@ -18426,6 +25752,18 @@ "is-fullwidth-code-point": "^2.0.0" } }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", + "dev": true + }, + "smart-buffer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==", + "dev": true + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -18540,6 +25878,52 @@ "kind-of": "^3.2.0" } }, + "socks": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz", + "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", + "dev": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "^4.1.0" + } + }, + "socks-proxy-agent": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", + "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", + "dev": true, + "requires": { + "agent-base": "~4.2.1", + "socks": "~2.3.2" + }, + "dependencies": { + "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" + } + } + } + }, + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -18625,6 +26009,15 @@ "integrity": "sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==", "dev": true }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "requires": { + "through": "2" + } + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -18634,6 +26027,15 @@ "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.1.2", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", @@ -18657,6 +26059,15 @@ "tweetnacl": "~0.14.0" } }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, "stack-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", @@ -18705,6 +26116,45 @@ "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", "dev": true }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, "string-argv": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", @@ -18771,6 +26221,17 @@ } } }, + "string.prototype.trim": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.1.tgz", + "integrity": "sha512-MjGFEeqixw47dAMFMtgUro/I0+wNqZB5GKXGt1fFr24u3TzDXCPu7J9Buppzoe3r/LqkSDLDDJzE15RGWDGAVw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1" + } + }, "string.prototype.trimleft": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", @@ -18868,6 +26329,25 @@ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, + "strong-log-transformer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", + "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", + "dev": true, + "requires": { + "duplexer": "^0.1.1", + "minimist": "^1.2.0", + "through": "^2.3.4" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + } + } + }, "style-search": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", @@ -19719,6 +27199,12 @@ "@tannin/plural-forms": "^1.0.4" } }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, "tar": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", @@ -19730,6 +27216,43 @@ "inherits": "2" } }, + "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 + }, + "temp-write": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-write/-/temp-write-3.4.0.tgz", + "integrity": "sha1-jP9jD7fp2gXwR8dM5M5NaFRX1JI=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "is-stream": "^1.1.0", + "make-dir": "^1.0.0", + "pify": "^3.0.0", + "temp-dir": "^1.0.0", + "uuid": "^3.0.1" + }, + "dependencies": { + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, "terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -19751,6 +27274,50 @@ } } }, + "terser": { + "version": "4.6.10", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.10.tgz", + "integrity": "sha512-qbF/3UOo11Hggsbsqm2hPa6+L4w7bkr+09FNseEe8xrcVD3APGLFqE+Oz1ZKAxjYnFsj80rLOfgAtJ0LNJjtTA==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz", + "integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^2.1.2", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + } + } + }, "test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -19778,12 +27345,36 @@ } } }, + "text-extensions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", + "dev": true + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "thenify": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", + "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", + "dev": true, + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "dev": true, + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, "throat": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", @@ -19796,6 +27387,25 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "timers-browserify": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", + "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, "tiny-lr": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", @@ -19842,6 +27452,12 @@ "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", "dev": true }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, "to-fast-properties": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", @@ -19935,6 +27551,12 @@ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true }, + "trim-off-newlines": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz", + "integrity": "sha1-n5up2e+odkw4dpi8v+sshI8RrbM=", + "dev": true + }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", @@ -19977,6 +27599,12 @@ "tslib": "^1.8.1" } }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -20070,6 +27698,18 @@ } } }, + "uid-number": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", + "dev": true + }, + "umask": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/umask/-/umask-1.1.0.tgz", + "integrity": "sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=", + "dev": true + }, "underscore.string": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz", @@ -20157,6 +27797,24 @@ "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", "dev": true }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, "unist-util-find-all-after": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/unist-util-find-all-after/-/unist-util-find-all-after-1.0.5.tgz", @@ -20213,6 +27871,21 @@ "unist-util-is": "^2.1.2" } }, + "universal-user-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-4.0.1.tgz", + "integrity": "sha512-LnST3ebHwVL2aNe4mejI9IQh2HfZ1RLo8Io2HugSif8ekzD1TlWpHpColOB/eh8JHMLkGH3Akqf040I+4ylNxg==", + "dev": true, + "requires": { + "os-name": "^3.1.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -20269,8 +27942,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true, - "optional": true + "dev": true }, "uri-js": { "version": "4.2.2", @@ -20293,18 +27965,54 @@ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", "dev": true }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "util-promisify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/util-promisify/-/util-promisify-2.1.0.tgz", + "integrity": "sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3" + } + }, "util.promisify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", @@ -20421,6 +28129,15 @@ "spdx-expression-parse": "^3.0.0" } }, + "validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "dev": true, + "requires": { + "builtins": "^1.0.3" + } + }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -20459,6 +28176,12 @@ "unist-util-stringify-position": "^1.1.1" } }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, "w3c-hr-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", @@ -20549,12 +28272,550 @@ "makeerror": "1.0.x" } }, + "watchpack": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.1.tgz", + "integrity": "sha512-+IF9hfUFOrYOOaKyfaI7h7dquUIOgyEMoQMLA7OP5FxegKA2+XdXThAZ9TU2kucfhDH7rfMHs1oPYziVGWRnZA==", + "dev": true, + "requires": { + "chokidar": "^2.1.8", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, "webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", "dev": true }, + "webpack": { + "version": "4.41.6", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.6.tgz", + "integrity": "sha512-yxXfV0Zv9WMGRD+QexkZzmGIh54bsvEs+9aRWxnN8erLWEOehAKUTeNBoUbA6HPEZPlRo7KDi2ZcNveoZgK9MA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/wasm-edit": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "acorn": "^6.2.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.6.0", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", + "dev": true + }, + "ajv": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", + "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "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" + } + } + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "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" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "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" + } + } + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "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" + } + }, + "neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "dev": true + } + } + }, + "webpack-cli": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.11.tgz", + "integrity": "sha512-dXlfuml7xvAFwYUPsrtQAA9e4DOe58gnzSxhgrO/ZM/gyXTBowrsYeubyN4mqGhYdpXMFNyQ6emjJS9M7OBd4g==", + "dev": true, + "requires": { + "chalk": "2.4.2", + "cross-spawn": "6.0.5", + "enhanced-resolve": "4.1.0", + "findup-sync": "3.0.0", + "global-modules": "2.0.0", + "import-local": "2.0.0", + "interpret": "1.2.0", + "loader-utils": "1.2.3", + "supports-color": "6.1.0", + "v8-compile-cache": "2.0.3", + "yargs": "13.2.4" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "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" + } + } + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "enhanced-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "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" + } + } + } + }, + "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" + } + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "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" + } + } + } + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + } + }, + "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" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "dependencies": { + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + } + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "v8-compile-cache": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz", + "integrity": "sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==", + "dev": true + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "13.2.4", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz", + "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.0" + } + } + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, "websocket-driver": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", @@ -20644,6 +28905,15 @@ "string-width": "^1.0.2 || 2" } }, + "windows-release": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.3.0.tgz", + "integrity": "sha512-2HetyTg1Y+R+rUgrKeUEhAG/ZuOmTrI1NBb3ZyAGQMYmOJjBBPe4MTodghRkmLJZHwkuPi02anbeGP+Zf401LQ==", + "dev": true, + "requires": { + "execa": "^1.0.0" + } + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -20656,6 +28926,15 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, "wp-textdomain": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wp-textdomain/-/wp-textdomain-1.0.1.tgz", @@ -20706,6 +28985,97 @@ "typedarray-to-buffer": "^3.1.5" } }, + "write-json-file": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz", + "integrity": "sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==", + "dev": true, + "requires": { + "detect-indent": "^5.0.0", + "graceful-fs": "^4.1.15", + "make-dir": "^2.1.0", + "pify": "^4.0.1", + "sort-keys": "^2.0.0", + "write-file-atomic": "^2.4.2" + }, + "dependencies": { + "detect-indent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", + "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=", + "dev": true + }, + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + } + } + }, + "write-pkg": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-3.2.0.tgz", + "integrity": "sha512-tX2ifZ0YqEFOF1wjRW2Pk93NLsj02+n1UP5RvO6rCs0K6R2g1padvf006cY74PQJKMGS2r42NK7FD0dG6Y6paw==", + "dev": true, + "requires": { + "sort-keys": "^2.0.0", + "write-json-file": "^2.2.0" + }, + "dependencies": { + "detect-indent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", + "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=", + "dev": true + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "write-json-file": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-2.3.0.tgz", + "integrity": "sha1-K2TIozAE1UuGmMdtWFp3zrYdoy8=", + "dev": true, + "requires": { + "detect-indent": "^5.0.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "pify": "^3.0.0", + "sort-keys": "^2.0.0", + "write-file-atomic": "^2.0.0" + } + } + } + }, "ws": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", diff --git a/package.json b/package.json index 185f847fcf2..19079f9a231 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "woocommerce", "title": "WooCommerce", - "version": "4.1.0", + "version": "4.3.0", "homepage": "https://woocommerce.com/", "repository": { "type": "git", @@ -12,11 +12,16 @@ "scripts": { "build": "grunt && npm run makepot", "build-watch": "grunt watch", + "build:packages": "node ./tests/e2e/bin/build.js", + "build:zip": "./bin/build-zip.sh", "lint:js": "eslint assets/js --ext=js", - "test:e2e": "./tests/bin/e2e-test-integration.js", - "test:e2e-dev": "./tests/bin/e2e-test-integration.js --dev", + "docker:up": "npm explore @woocommerce/e2e-environment -- npm run docker:up", + "docker:down": "npm explore @woocommerce/e2e-environment -- npm run docker:down", + "test:e2e": "npm explore @woocommerce/e2e-environment -- npm run test:e2e", + "test:e2e-dev": "npm explore @woocommerce/e2e-environment -- npm run test:e2e-dev", "makepot": "composer run-script makepot", "packages:fix:textdomain": "node ./bin/package-update-textdomain.js", + "publish-packages": "npm run build:packages && lerna publish from-package", "git:update-hooks": "rm -r .git/hooks && mkdir -p .git/hooks && node ./node_modules/husky/husky.js install" }, "devDependencies": { @@ -26,7 +31,10 @@ "@babel/preset-env": "7.9.0", "@babel/register": "7.9.0", "@jest/test-sequencer": "^25.0.0", - "@wordpress/e2e-test-utils": "4.3.1", + "@woocommerce/e2e-environment": "file:tests/e2e/env", + "@wordpress/babel-plugin-import-jsx-pragma": "1.1.3", + "@wordpress/babel-preset-default": "3.0.2", + "@wordpress/e2e-test-utils": "4.6.0", "autoprefixer": "9.7.5", "babel-eslint": "10.1.0", "chai": "4.2.0", @@ -34,6 +42,7 @@ "commander": "4.1.1", "config": "3.3.1", "cross-env": "6.0.3", + "deasync": "0.1.19", "eslint": "6.8.0", "eslint-config-wpcalypso": "5.0.0", "eslint-plugin-jest": "23.8.2", @@ -43,20 +52,19 @@ "grunt-contrib-concat": "1.0.1", "grunt-contrib-copy": "1.0.0", "grunt-contrib-cssmin": "3.0.0", - "grunt-contrib-jshint": "2.1.0", "grunt-contrib-uglify": "4.0.1", "grunt-contrib-watch": "1.1.0", "grunt-phpcs": "0.4.0", "grunt-postcss": "0.9.0", - "grunt-prompt": "1.3.3", "grunt-rtlcss": "2.0.2", "grunt-sass": "3.1.0", - "grunt-shell": "3.0.1", "grunt-stylelint": "0.14.0", - "husky": "4.2.1", + "gruntify-eslint": "5.0.0", + "husky": "4.2.5", "istanbul": "1.0.0-alpha.2", "jest": "25.1.0", "jest-puppeteer": "4.4.0", + "lerna": "3.20.2", "lint-staged": "9.5.0", "mocha": "7.0.1", "node-sass": "4.13.0", @@ -65,6 +73,8 @@ "puppeteer-utils": "github:Automattic/puppeteer-utils#0f3ec50", "stylelint": "12.0.1", "stylelint-config-wordpress": "16.0.0", + "webpack": "4.41.6", + "webpack-cli": "3.3.11", "wp-textdomain": "^1.0.1" }, "engines": { @@ -73,8 +83,9 @@ }, "husky": { "hooks": { + "post-merge": "./bin/post-merge.sh", "pre-commit": "lint-staged", - "post-merge": "./bin/post-merge.sh" + "pre-push": "./bin/pre-push.sh" } }, "lint-staged": { diff --git a/phpcs.xml b/phpcs.xml index c8196e3167e..8075b9d8ccc 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -58,5 +58,7 @@ i18n/ src/ + tests/php + tests/Tools/ diff --git a/phpunit.xml b/phpunit.xml index d8b796394e8..94156de9541 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,6 +1,6 @@ - ./tests/unit-tests + ./tests/legacy/unit-tests + ./tests/php @@ -46,6 +47,9 @@ - + + + + diff --git a/readme.txt b/readme.txt index 8255ebeb860..9eeeef44559 100644 --- a/readme.txt +++ b/readme.txt @@ -1,10 +1,10 @@ === WooCommerce === Contributors: automattic, mikejolley, jameskoster, claudiosanches, kloon, rodrigosprimo, peterfabian1000, vedjain, jamosova, obliviousharmony Tags: e-commerce, store, sales, sell, woo, shop, cart, checkout, downloadable, downloads, payments, paypal, storefront, stripe, woo commerce -Requires at least: 5.0 +Requires at least: 5.2 Tested up to: 5.4 Requires PHP: 7.0 -Stable tag: 4.0.1 +Stable tag: 4.1.1 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html @@ -179,48 +179,7 @@ INTERESTED IN DEVELOPMENT? == Changelog == -= 4.1.0 - 2020-05-05 = - -**WooCommerce** -* Enhancement - Update dependency woocommerce/woocommerce-admin to v1.1.0 #26057 -* Enhancement - Updated jetpack-autoloader to 1.6 and woocommerce-blocks to 2.5.16. #26099 -* Enhancement - Added option to ignore discounts from cart's total amount to enable free shipping. #24776 -* Enhancement - Changed show password icon color to a darker grey hue. #25625 -* Enhancement - Use new Setup Wizard for all users. #26016 -* Tweak - Show notice for WP min version to WP 5.2. #26094 -* Tweak - Improve the string for untested WooCommerce extensions in the system status page to avoid confusion. #25904 -* Tweak - Updated KZT (₸) symbol. #25609 -* Tweak - Trim whitespaces and strip slashes from MaxMind License Key. #25466 -* Tweak - Updated "Help" tabs documentation. #25826 -* Tweak - Update serbian currency symbol to рсд from дин. #25885 -* Fix - Password visibility toggle to hide password again from text. #25627 -* Fix - Undefined property error when attempting to modify the coupon post meta. #25755 -* Fix - Remove some of the individual rounding logic to make sure we round at certain places only. #25800 -* Fix - Order totals calculation if the order contains taxable and non-taxable products and percentage coupons. #25092 -* Fix - Wording for cancelled order email. #25316 -* Fix - Removed guided tour videos link on setup wizard (since current link only redirects to the docs). #25823 -* Fix - Add RTL style to the onboarding wizard. #25835 -* Fix - Trigger change and set val to qty on the frontend so that it properly updates event handlers. #25903 -* Fix - Corrected the way percent coupons apply remainders across the order. #25943 -* Fix - Clarified the error messaging for WooCommerce.com package update failures. #26034 -* Fix - Enforce per user usage limit check for a coupon on guest users based on email. #26066 -* Fix - Remove elements with style=display:none explicitly to address a regression causing broken email html. #26075 -* Dev - Added woocommerce_can_restock_refunded_items filter. #25728 -* Dev - Added woocommerce_order_get_tax_location filter. #25727 -* Dev - Updated stock handling to prevent race conditions when orders come in at the same time. #25708 -* Dev - Updated /myaccount/form-login.php to use consistent kebab-case class names for woocommerce-form-row. #25668 -* Dev - Add filter woocommerce_product_upsells_products_heading to allow heading modification without having to override the template file. #25628 -* Dev - Added woocommerce_order_get_tax_location filter. #25727 -* Dev - Added the get_woocommerce_currency_symbols function to allow develops to get an array of all the currency symbol registered with WooCommerce. #25733 -* Dev - Changed string typed label_class to array in checkout fields. -* Dev - Added "woocommerce_emogrifier" action before the content of the emails is "emogrified". #25801 -* Dev - Add Ability to Filter Event Props. #25851 -* Dev - Updated the unit test install script to support paths to MySQL sockets that contain spaces. #25923 -* Dev - Made the default test source folders support the system tmp folder. #25923 -* Dev - Add cart & checkout block/shortcode info to tracker data. #25932 -* Dev - Make WC_Product_Data_Store_CPT::update_product_stock operations atomic. #26039 -* Dev - Adds usage data for the of cart & checkout blocks (currently in development in WooCommmerce Blocks plugin) to the WC Tracker snapshot. #26084 -* Dev - Implement some additional tracks for coupons, orders, and products. #26085 += 4.3.0 - 2020-07-07 = [See changelog for all versions](https://raw.githubusercontent.com/woocommerce/woocommerce/master/CHANGELOG.txt). diff --git a/renovate.json b/renovate.json index 40aaeb69687..e119457e471 100644 --- a/renovate.json +++ b/renovate.json @@ -11,5 +11,11 @@ "depTypeList": ["devDependencies"], "extends": ["schedule:monthly"] } + ], + "ignoreDeps": [ + "woocommerce/action-scheduler", + "woocommerce/woocommerce-admin", + "woocommerce/woocommerce-blocks", + "woocommerce/woocommerce-rest-api" ] } diff --git a/src/Admin/.gitignore b/src/Admin/.gitignore new file mode 100644 index 00000000000..ee8d4ea0dd0 --- /dev/null +++ b/src/Admin/.gitignore @@ -0,0 +1,5 @@ +# Prevent anyone from accidentally adding code to these directories. +# This will break any PRs that do, revealing ths mistake they made. +* +!.gitignore +!README.md diff --git a/src/Admin/README.md b/src/Admin/README.md new file mode 100644 index 00000000000..3251e1f9956 --- /dev/null +++ b/src/Admin/README.md @@ -0,0 +1,3 @@ +# WARNING + +The namespace of this folder belongs to the [WC-Admin Plugin](https://github.com/woocommerce/woocommerce-admin) that is included in Core via composer. Any contributions to this namespace should be made in the corresponding repository to prevent conflicts. diff --git a/src/Blocks/.gitignore b/src/Blocks/.gitignore new file mode 100644 index 00000000000..ee8d4ea0dd0 --- /dev/null +++ b/src/Blocks/.gitignore @@ -0,0 +1,5 @@ +# Prevent anyone from accidentally adding code to these directories. +# This will break any PRs that do, revealing ths mistake they made. +* +!.gitignore +!README.md diff --git a/src/Blocks/README.md b/src/Blocks/README.md new file mode 100644 index 00000000000..95e6021eb15 --- /dev/null +++ b/src/Blocks/README.md @@ -0,0 +1,3 @@ +# WARNING + +The namespace of this folder belongs to the [Product Blocks Plugin](https://github.com/woocommerce/woocommerce-gutenberg-products-block) that is included in Core via composer. Any contributions to this namespace should be made in the corresponding repository to prevent conflicts. diff --git a/src/Checkout/Helpers/ReserveStock.php b/src/Checkout/Helpers/ReserveStock.php new file mode 100644 index 00000000000..ae01823a0c4 --- /dev/null +++ b/src/Checkout/Helpers/ReserveStock.php @@ -0,0 +1,210 @@ +enabled = get_option( 'woocommerce_schema_version', 0 ) >= 430; + } + + /** + * Is stock reservation enabled? + * + * @return boolean + */ + protected function is_enabled() { + return $this->enabled; + } + + /** + * Query for any existing holds on stock for this item. + * + * @param \WC_Product $product Product to get reserved stock for. + * @param integer $exclude_order_id Optional order to exclude from the results. + * + * @return integer Amount of stock already reserved. + */ + public function get_reserved_stock( \WC_Product $product, $exclude_order_id = 0 ) { + global $wpdb; + + if ( ! $this->is_enabled() ) { + return 0; + } + + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared + return (int) $wpdb->get_var( $this->get_query_for_reserved_stock( $product->get_stock_managed_by_id(), $exclude_order_id ) ); + } + + /** + * Put a temporary hold on stock for an order if enough is available. + * + * @throws ReserveStockException If stock cannot be reserved. + * + * @param \WC_Order $order Order object. + * @param int $minutes How long to reserve stock in minutes. Defaults to woocommerce_hold_stock_minutes. + */ + public function reserve_stock_for_order( \WC_Order $order, $minutes = 0 ) { + $minutes = $minutes ? $minutes : (int) get_option( 'woocommerce_hold_stock_minutes', 60 ); + + if ( ! $minutes || ! $this->is_enabled() ) { + return; + } + + try { + $items = array_filter( + $order->get_items(), + function( $item ) { + return $item->is_type( 'line_item' ) && $item->get_product() instanceof \WC_Product && $item->get_quantity() > 0; + } + ); + $rows = array(); + + foreach ( $items as $item ) { + $product = $item->get_product(); + + if ( ! $product->is_in_stock() ) { + throw new ReserveStockException( + 'woocommerce_product_out_of_stock', + sprintf( + /* translators: %s: product name */ + __( '"%s" is out of stock and cannot be purchased.', 'woocommerce' ), + $product->get_name() + ), + 403 + ); + } + + // If stock management is off, no need to reserve any stock here. + if ( ! $product->managing_stock() || $product->backorders_allowed() ) { + continue; + } + + $managed_by_id = $product->get_stock_managed_by_id(); + $rows[ $managed_by_id ] = isset( $rows[ $managed_by_id ] ) ? $rows[ $managed_by_id ] + $item->get_quantity() : $item->get_quantity(); + } + + if ( ! empty( $rows ) ) { + foreach ( $rows as $product_id => $quantity ) { + $this->reserve_stock_for_product( $product_id, $quantity, $order, $minutes ); + } + } + } catch ( ReserveStockException $e ) { + $this->release_stock_for_order( $order ); + throw $e; + } + } + + /** + * Release a temporary hold on stock for an order. + * + * @param \WC_Order $order Order object. + */ + public function release_stock_for_order( \WC_Order $order ) { + global $wpdb; + + if ( ! $this->is_enabled() ) { + return; + } + + $wpdb->delete( + $wpdb->wc_reserved_stock, + array( + 'order_id' => $order->get_id(), + ) + ); + } + + /** + * Reserve stock for a product by inserting rows into the DB. + * + * @throws ReserveStockException If a row cannot be inserted. + * + * @param int $product_id Product ID which is having stock reserved. + * @param int $stock_quantity Stock amount to reserve. + * @param \WC_Order $order Order object which contains the product. + * @param int $minutes How long to reserve stock in minutes. + */ + private function reserve_stock_for_product( $product_id, $stock_quantity, \WC_Order $order, $minutes ) { + global $wpdb; + + $product_data_store = \WC_Data_Store::load( 'product' ); + $query_for_stock = $product_data_store->get_query_for_stock( $product_id ); + $query_for_reserved_stock = $this->get_query_for_reserved_stock( $product_id, $order->get_id() ); + + // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared + $result = $wpdb->query( + $wpdb->prepare( + " + INSERT INTO {$wpdb->wc_reserved_stock} ( `order_id`, `product_id`, `stock_quantity`, `timestamp`, `expires` ) + SELECT %d, %d, %d, NOW(), ( NOW() + INTERVAL %d MINUTE ) FROM DUAL + WHERE ( $query_for_stock FOR UPDATE ) - ( $query_for_reserved_stock FOR UPDATE ) >= %d + ON DUPLICATE KEY UPDATE `expires` = VALUES( `expires` ), `stock_quantity` = VALUES( `stock_quantity` ) + ", + $order->get_id(), + $product_id, + $stock_quantity, + $minutes, + $stock_quantity + ) + ); + // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared + + if ( ! $result ) { + $product = wc_get_product( $product_id ); + throw new ReserveStockException( + 'woocommerce_product_not_enough_stock', + sprintf( + /* translators: %s: product name */ + __( 'Not enough units of %s are available in stock to fulfil this order.', 'woocommerce' ), + $product ? $product->get_name() : '#' . $product_id + ), + 403 + ); + } + } + + /** + * Returns query statement for getting reserved stock of a product. + * + * @param int $product_id Product ID. + * @param integer $exclude_order_id Optional order to exclude from the results. + * @return string|void Query statement. + */ + private function get_query_for_reserved_stock( $product_id, $exclude_order_id = 0 ) { + global $wpdb; + return $wpdb->prepare( + " + SELECT COALESCE( SUM( stock_table.`stock_quantity` ), 0 ) FROM $wpdb->wc_reserved_stock stock_table + LEFT JOIN $wpdb->posts posts ON stock_table.`order_id` = posts.ID + WHERE posts.post_status IN ( 'wc-checkout-draft', 'wc-pending' ) + AND stock_table.`expires` > NOW() + AND stock_table.`product_id` = %d + AND stock_table.`order_id` != %d + ", + $product_id, + $exclude_order_id + ); + } +} diff --git a/src/Checkout/Helpers/ReserveStockException.php b/src/Checkout/Helpers/ReserveStockException.php new file mode 100644 index 00000000000..e84409b5f1d --- /dev/null +++ b/src/Checkout/Helpers/ReserveStockException.php @@ -0,0 +1,62 @@ +error_code = $code; + $this->error_data = $data; + + parent::__construct( $message, $http_status_code ); + } + + /** + * Returns the error code. + * + * @return string + */ + public function getErrorCode() { + return $this->error_code; + } + + /** + * Returns error data. + * + * @return array + */ + public function getErrorData() { + return $this->error_data; + } +} diff --git a/templates/auth/form-grant-access.php b/templates/auth/form-grant-access.php index f5ee952ffcf..ecaee458f22 100644 --- a/templates/auth/form-grant-access.php +++ b/templates/auth/form-grant-access.php @@ -50,6 +50,7 @@ defined( 'ABSPATH' ) || exit; printf( esc_html__( 'Logged in as %s', 'woocommerce' ), esc_html( $user->display_name ) ); ?> +

          diff --git a/templates/content-single-product.php b/templates/content-single-product.php index 04879593889..edcd3d19741 100644 --- a/templates/content-single-product.php +++ b/templates/content-single-product.php @@ -22,7 +22,7 @@ global $product; /** * Hook: woocommerce_before_single_product. * - * @hooked wc_print_notices - 10 + * @hooked woocommerce_output_all_notices - 10 */ do_action( 'woocommerce_before_single_product' ); diff --git a/templates/emails/plain/email-customer-details.php b/templates/emails/plain/email-customer-details.php index d9f9672b729..f5b0ebf91f0 100644 --- a/templates/emails/plain/email-customer-details.php +++ b/templates/emails/plain/email-customer-details.php @@ -4,7 +4,7 @@ * * This is extra customer data which can be filtered by plugins. It outputs below the order item table. * - * This template can be overridden by copying it to yourtheme/woocommerce/emails/plain/email-addresses.php. + * This template can be overridden by copying it to yourtheme/woocommerce/emails/plain/email-customer-details.php. * * HOWEVER, on occasion WooCommerce will need to update template files and you * (the theme developer) will need to copy the new files to your theme to diff --git a/templates/myaccount/form-add-payment-method.php b/templates/myaccount/form-add-payment-method.php index 20a4de2ffdb..2e2b8ca637c 100644 --- a/templates/myaccount/form-add-payment-method.php +++ b/templates/myaccount/form-add-payment-method.php @@ -47,6 +47,8 @@ if ( $available_gateways ) : ?> ?> + +

          diff --git a/templates/single-product-reviews.php b/templates/single-product-reviews.php index ecde5dbc72a..5fa9279b8ee 100644 --- a/templates/single-product-reviews.php +++ b/templates/single-product-reviews.php @@ -121,7 +121,7 @@ if ( ! comments_open() ) { } if ( wc_review_ratings_enabled() ) { - $comment_form['comment_field'] = '
          diff --git a/tests/README.md b/tests/README.md index 4c0ec2b0746..9a75383a984 100644 --- a/tests/README.md +++ b/tests/README.md @@ -46,7 +46,7 @@ The tests will execute and you'll be presented with a summary. You can run specific tests by providing the path and filename to the test class: - $ vendor/bin/phpunit tests/unit-tests/importer/product.php + $ vendor/bin/phpunit tests/legacy/unit-tests/importer/product.php A text code coverage summary can be displayed using the `--coverage-text` option: @@ -54,6 +54,7 @@ A text code coverage summary can be displayed using the `--coverage-text` option ### Writing Tests +* There are two different PHPUnit directories, `tests/legacy` and `tests/php`. The `tests/legacy` directory contains all of the tests for code in the `includes` directory, and the `tests/php` directory is a PSR-4 namespaced directory for tests of code in the `src` directory. * Each test file should roughly correspond to an associated source file, e.g. the `formatting/functions.php` test file covers code in the `wc-formatting-functions.php` file * Each test method should cover a single method or function with one or more assertions * A single method or function can have multiple associated test methods if it's a large or complex method @@ -75,4 +76,4 @@ Code coverage is available on [Codecov](https://codecov.io/gh/woocommerce/woocom ## WooCommerce E2E Tests -See [e2e-tests README](https://github.com/woocommerce/woocommerce/tree/master/tests/e2e-tests) to learn how to setup testing environment for running e2e tests and run them. +See [e2e README](https://github.com/woocommerce/woocommerce/tree/master/tests/e2e) to learn how to setup testing environment for running e2e tests and run them. diff --git a/tests/Tools/CodeHacking/CodeHacker.php b/tests/Tools/CodeHacking/CodeHacker.php new file mode 100644 index 00000000000..a22650e20e8 --- /dev/null +++ b/tests/Tools/CodeHacking/CodeHacker.php @@ -0,0 +1,511 @@ +getMethod( 'hack' ); + $has_valid_hack_method = $rm->isPublic() && ! $rm->isStatic() && 2 === $rm->getNumberOfRequiredParameters(); + + $rm = $ro->getMethod( 'reset' ); + $has_valid_reset_method = $rm->isPublic() && ! $rm->isStatic() && 0 === $rm->getNumberOfRequiredParameters(); + + return $has_valid_hack_method && $has_valid_reset_method; + } catch ( ReflectionException $exception ) { + return false; + } + } + + /** + * Initialize the code hacker. + * + * @param array $paths Paths of the directories containing the files to hack. + * @throws \Exception Invalid input. + */ + public static function initialize( array $paths ) { + if ( ! is_array( $paths ) || empty( $paths ) ) { + throw new \Exception( 'CodeHacker::initialize - $paths must be a non-empty array with the directories containing the files to be hacked.' ); + } + self::$paths_with_files_to_hack = array_map( + function( $path ) { + return realpath( $path ); + }, + $paths + ); + } + + /** + * Close directory handle. + */ + public function dir_closedir() { + closedir( $this->handle ); + } + + /** + * Open directory handle. + * + * @param string $path Specifies the URL that was passed to opendir(). + * @param int $options Whether or not to enforce safe_mode (0x04). + * + * @return bool TRUE on success or FALSE on failure. + */ + public function dir_opendir( $path, $options ) { + $this->handle = $this->context + ? $this->native( 'opendir', $path, $this->context ) + : $this->native( 'opendir', $path ); + return (bool) $this->handle; + } + + /** + * Read entry from directory handle. + * + * @return false|string string representing the next filename, or FALSE if there is no next file. + */ + public function dir_readdir() { + return readdir( $this->handle ); + } + + /** + * Rewind directory handle. + * + * @return TRUE on success or FALSE on failure. + */ + public function dir_rewinddir() { + return rewinddir( $this->handle ); + } + + /** + * Create a directory. + * + * @param string $path Directory which should be created. + * @param int $mode The value passed to mkdir(). + * @param int $options A bitwise mask of values, such as STREAM_MKDIR_RECURSIVE. + * + * @return bool TRUE on success or FALSE on failure. + */ + public function mkdir( $path, $mode, $options ) { + $recursive = (bool) ( $options & STREAM_MKDIR_RECURSIVE ); + return $this->native( 'mkdir', $path, $mode, $recursive, $this->context ); + } + + /** + * Renames a file or directory. + * + * @param string $path_from The URL to the current file. + * @param string $path_to The URL which the path_from should be renamed to. + * + * @return bool TRUE on success or FALSE on failure. + */ + public function rename( $path_from, $path_to ) { + return $this->native( 'rename', $path_from, $path_to, $this->context ); + } + + /** + * Removes a directory. + * + * @param string $path The directory URL which should be removed. + * @param int $options A bitwise mask of values, such as STREAM_MKDIR_RECURSIVE. + * + * @return bool TRUE on success or FALSE on failure. + */ + public function rmdir( $path, $options ) { + return $this->native( 'rmdir', $path, $this->context ); + } + + /** + * Retrieve the underlying resource. + * + * @param mixed $cast_as Can be STREAM_CAST_FOR_SELECT when stream_select() is calling stream_cast() or STREAM_CAST_AS_STREAM when stream_cast() is called for other uses. + * + * @return mixed The underlying stream resource used by the wrapper, or FALSE. + */ + public function stream_cast( $cast_as ) { + return $this->handle; + } + + /** + * Close a resource. + */ + public function stream_close() { + fclose( $this->handle ); + } + + /** + * Tests for end-of-file on a file pointer. + * + * @return bool TRUE if the read/write position is at the end of the stream and if no more data is available to be read, or FALSE otherwise. + */ + public function stream_eof() { + return feof( $this->handle ); + } + + /** + * Flushes the output. + * + * @return bool TRUE if the cached data was successfully stored (or if there was no data to store), or FALSE if the data could not be stored. + */ + public function stream_flush() { + return fflush( $this->handle ); + } + + /** + * Advisory file locking. + * + * @param int $operation LOCK_SH, LOCK_EX, LOCK_UN, or LOCK_NB. + * + * @return bool TRUE on success or FALSE on failure. + */ + public function stream_lock( $operation ) { + return $operation + ? flock( $this->handle, $operation ) + : true; + } + + /** + * Change stream metadata. + * + * @param string $path The file path or URL to set metadata. Note that in the case of a URL, it must be a :// delimited URL. Other URL forms are not supported. + * @param int $option STREAM_META_TOUCH, STREAM_META_OWNER_NAME, STREAM_META_OWNER, STREAM_META_GROUP_NAME, STREAM_META_GROUP, or STREAM_META_ACCESS. + * @param mixed $value Depends on $option. + * + * @return bool TRUE on success or FALSE on failure. If option is not implemented, FALSE should be returned. + */ + public function stream_metadata( $path, $option, $value ) { + switch ( $option ) { + case STREAM_META_TOUCH: + $value += array( null, null ); + return $this->native( 'touch', $path, $value[0], $value[1] ); + case STREAM_META_OWNER_NAME: + case STREAM_META_OWNER: + return $this->native( 'chown', $path, $value ); + case STREAM_META_GROUP_NAME: + case STREAM_META_GROUP: + return $this->native( 'chgrp', $path, $value ); + case STREAM_META_ACCESS: + return $this->native( 'chmod', $path, $value ); + } + } + + /** + * Opens file or URL. Note that this is where the hacking actually happens. + * + * @param string $path Specifies the URL that was passed to the original function. + * @param string $mode The mode used to open the file, as detailed for fopen(). + * @param int $options Holds additional flags set by the streams API: STREAM_USE_PATH, STREAM_REPORT_ERRORS. + * @param string $opened_path If the path is opened successfully, and STREAM_USE_PATH is set in options, opened_path should be set to the full path of the file/resource that was actually opened. + * + * @return bool TRUE on success or FALSE on failure. + */ + public function stream_open( $path, $mode, $options, &$opened_path ) { + $use_path = (bool) ( $options & STREAM_USE_PATH ); + if ( 'rb' === $mode && self::path_in_list_of_paths_to_hack( $path ) && 'php' === pathinfo( $path, PATHINFO_EXTENSION ) ) { + $content = $this->native( 'file_get_contents', $path, $use_path, $this->context ); + if ( false === $content ) { + return false; + } + $modified = self::hack( $content, $path ); + if ( $modified !== $content ) { + $this->handle = tmpfile(); + $this->native( 'fwrite', $this->handle, $modified ); + $this->native( 'fseek', $this->handle, 0 ); + return true; + } + } + $this->handle = $this->context + ? $this->native( 'fopen', $path, $mode, $use_path, $this->context ) + : $this->native( 'fopen', $path, $mode, $use_path ); + return (bool) $this->handle; + } + + /** + * Read from stream. + * + * @param int $count How many bytes of data from the current position should be returned. + * + * @return false|string If there are less than count bytes available, return as many as are available. If no more data is available, return either FALSE or an empty string. + */ + public function stream_read( $count ) { + return fread( $this->handle, $count ); + } + + /** + * Seeks to specific location in a stream. + * + * @param int $offset The stream offset to seek to. + * @param int $whence SEEK_SET, SEEK_CUR, or SEEK_END. + * + * @return bool TRUE if the position was updated, FALSE otherwise. + */ + public function stream_seek( $offset, $whence = SEEK_SET ) { + return fseek( $this->handle, $offset, $whence ) === 0; + } + + /** + * Change stream options. + * + * @param int $option STREAM_OPTION_BLOCKING, STREAM_OPTION_READ_TIMEOUT, or STREAM_OPTION_WRITE_BUFFER. + * @param int $arg1 Depends on $option. + * @param int $arg2 Depends on $option. + */ + public function stream_set_option( $option, $arg1, $arg2 ) { + } + + /** + * Retrieve information about a file resource. + * + * @return array See stat(). + */ + public function stream_stat() { + return fstat( $this->handle ); + } + + /** + * Retrieve the current position of a stream. + * + * @return false|int The current position of the stream. + */ + public function stream_tell() { + return ftell( $this->handle ); + } + + /** + * Truncate stream. + * + * @param int $new_size The new size. + * + * @return bool TRUE on success or FALSE on failure. + */ + public function stream_truncate( $new_size ) { + return ftruncate( $this->handle, $new_size ); + } + + /** + * Write to stream. + * + * @param string $data Should be stored into the underlying stream. + * + * @return false|int The number of bytes that were successfully stored, or 0 if none could be stored. + */ + public function stream_write( $data ) { + return fwrite( $this->handle, $data ); + } + + /** + * Delete a file. + * + * @param string $path The file URL which should be deleted. + * + * @return bool TRUE on success or FALSE on failure. + */ + public function unlink( $path ) { + return $this->native( 'unlink', $path ); + } + + /** + * Retrieve information about a file. + * + * @param string $path The file path or URL to stat. Note that in the case of a URL, it must be a :// delimited URL. Other URL forms are not supported. + * @param int $flags Holds additional flags set by the streams API. It can hold one or more of the following values OR'd together. + * + * @return mixed Should return as many elements as stat() does. Unknown or unavailable values should be set to a rational value (usually 0). Pay special attention to mode as documented under stat(). + */ + public function url_stat( $path, $flags ) { + $func = $flags & STREAM_URL_STAT_LINK ? 'lstat' : 'stat'; + return $flags & STREAM_URL_STAT_QUIET + ? @$this->native( $func, $path ) + : $this->native( $func, $path ); + } + + /** + * Executes a native PHP function. + * + * @param string $func Name of the function to execute. Pass the arguments for the PHP function after this one. + * + * @return mixed Return value from the native PHP function. + */ + private function native( $func ) { + stream_wrapper_restore( self::PROTOCOL ); + $res = call_user_func_array( $func, array_slice( func_get_args(), 1 ) ); + stream_wrapper_unregister( self::PROTOCOL ); + stream_wrapper_register( self::PROTOCOL, __CLASS__ ); + return $res; + } + + /** + * Apply the reigstered hacks to the contents of a file. + * + * @param string $code Code content to hack. + * @param string $path Path of the file being hacked. + * + * @return string The code after applying all the registered hacks. + */ + private static function hack( $code, $path ) { + foreach ( self::$hacks as $hack ) { + if ( is_callable( $hack ) ) { + $code = call_user_func( $hack, $code, $path ); + } else { + $code = $hack->hack( $code, $path ); + } + } + + return $code; + } + + /** + * Check if a file path is in the white list. + * + * @param string $path File path to check. + * + * @return bool TRUE if there's an entry in the white list that ends with $path, FALSE otherwise. + * + * @throws \Exception The class is not initialized. + */ + private static function path_in_list_of_paths_to_hack( $path ) { + if ( empty( self::$paths_with_files_to_hack ) ) { + throw new \Exception( "CodeHacker is not initialized, it must initialized by invoking 'initialize'" ); + } + foreach ( self::$paths_with_files_to_hack as $white_list_item ) { + if ( substr( $path, 0, strlen( $white_list_item ) ) === $white_list_item ) { + return true; + } + } + return false; + } +} + +//phpcs:enable WordPress.WP.AlternativeFunctions, WordPress.PHP.NoSilencedErrors.Discouraged + diff --git a/tests/Tools/CodeHacking/CodeHackerTestHook.php b/tests/Tools/CodeHacking/CodeHackerTestHook.php new file mode 100644 index 00000000000..18b0c9aafb6 --- /dev/null +++ b/tests/Tools/CodeHacking/CodeHackerTestHook.php @@ -0,0 +1,32 @@ + + * + * + */ +final class CodeHackerTestHook implements BeforeTestHook { + + /** + * Runs before each test. + * + * @param string $test "TestClass::TestMethod". + * + * @throws \ReflectionException Thrown by execute_before_methods. + */ + public function executeBeforeTest( string $test ): void { + CodeHacker::reset_hacks(); + } +} + diff --git a/tests/Tools/CodeHacking/Hacks/BypassFinalsHack.php b/tests/Tools/CodeHacking/Hacks/BypassFinalsHack.php new file mode 100644 index 00000000000..0d5f0b4e2fb --- /dev/null +++ b/tests/Tools/CodeHacking/Hacks/BypassFinalsHack.php @@ -0,0 +1,42 @@ +tokenize( $code ); + $code = ''; + foreach ( $tokens as $token ) { + $code .= $this->is_token_of_type( $token, T_FINAL ) ? '' : $this->token_to_string( $token ); + } + } + + return $code; + } + + /** + * Revert the hack to its initial state - nothing to do since finals can't be reverted. + */ + public function reset() { + } +} + diff --git a/tests/Tools/CodeHacking/Hacks/CodeHack.php b/tests/Tools/CodeHacking/Hacks/CodeHack.php new file mode 100644 index 00000000000..5f79b652558 --- /dev/null +++ b/tests/Tools/CodeHacking/Hacks/CodeHack.php @@ -0,0 +1,94 @@ + function($name, $default) { + * return 'foo' === $name ? 'bar' : get_option($name, $default); + * } + * ]); + * + * 1 and 2 must be done during the unit testing bootstrap process. + * + * Note that unless the tests directory is included in the hacking via 'CodeHacker::initialize' + * (and they shouldn't!), test code files aren't hacked, therefore the original functions are always + * executed inside tests (and thus the above example won't stack-overflow). + */ +final class FunctionsMockerHack extends CodeHack { + /** + * Tokens that precede a non-standalone-function identifier. + * + * @var array + */ + private static $non_global_function_tokens = array( + T_PAAMAYIM_NEKUDOTAYIM, + T_DOUBLE_COLON, + T_OBJECT_OPERATOR, + T_FUNCTION, + T_CLASS, + T_EXTENDS, + ); + + /** + * @var FunctionsMockerHack Holds the only existing instance of the class. + */ + private static $instance; + + /** + * Initializes the class. + * + * @param array $mockable_functions An array containing the names of the functions that will become mockable. + * + * @throws \Exception $mockable_functions is not an array or is empty. + */ + public static function initialize( $mockable_functions ) { + if ( ! is_array( $mockable_functions ) || empty( $mockable_functions ) ) { + throw new \Exception( 'FunctionsMockeHack::initialize: $mockable_functions must be a non-empty array of function names.' ); + } + + self::$instance = new FunctionsMockerHack( $mockable_functions ); + } + + /** + * FunctionsMockerHack constructor. + * + * @param array $mockable_functions An array containing the names of the functions that will become mockable. + */ + private function __construct( $mockable_functions ) { + $this->mockable_functions = $mockable_functions; + } + + /** + * Hacks code by replacing elegible function invocations with an invocation to this class' static method with the same name. + * + * @param string $code The code to hack. + * @param string $path The path of the file containing the code to hack. + * @return string The hacked code. + */ + public function hack( $code, $path ) { + $tokens = $this->tokenize( $code ); + $code = ''; + $previous_token_is_non_global_function_qualifier = false; + + foreach ( $tokens as $token ) { + $token_type = $this->token_type_of( $token ); + if ( T_WHITESPACE === $token_type ) { + $code .= $this->token_to_string( $token ); + } elseif ( T_STRING === $token_type && ! $previous_token_is_non_global_function_qualifier && in_array( $token[1], $this->mockable_functions, true ) ) { + $code .= __CLASS__ . "::{$token[1]}"; + $previous_token_is_non_global_function_qualifier = false; + } else { + $code .= $this->token_to_string( $token ); + $previous_token_is_non_global_function_qualifier = in_array( $token_type, self::$non_global_function_tokens, true ); + } + } + + return $code; + } + + /** + * @var array Functions that can be mocked, associative array of function name => callback. + */ + private $function_mocks = array(); + + /** + * Register function mocks. + * + * @param array $mocks Mocks as an associative array of function name => mock function with the same arguments as the original function. + * + * @throws \Exception Invalid input. + */ + public function register_function_mocks( $mocks ) { + if ( ! is_array( $mocks ) ) { + throw new \Exception( 'FunctionsMockerHack::add_function_mocks: $mocks must be an associative array of function name => callable.' ); + } + + foreach ( $mocks as $function_name => $mock ) { + if ( ! in_array( $function_name, $this->mockable_functions, true ) ) { + throw new \Exception( "FunctionsMockerHack::add_function_mocks: Can't mock '$function_name' since it isn't in the list of mockable functions supplied to 'initialize'." ); + } + if ( ! is_callable( $mock ) ) { + throw new \Exception( "FunctionsMockerHack::add_function_mocks: The mock supplied for '$function_name' isn't callable." ); + } + } + + $this->function_mocks = array_merge( $this->function_mocks, $mocks ); + } + + /** + * Register function mocks. + * + * @param array $mocks Mocks as an associative array of function name => mock function with the same arguments as the original function. + * + * @throws \Exception Invalid input. + */ + public static function add_function_mocks( $mocks ) { + self::$instance->register_function_mocks( $mocks ); + } + + /** + * Unregister all the registered function mocks. + */ + public function reset() { + $this->function_mocks = array(); + } + + /** + * Handler for undefined static methods on this class, it invokes the mock for the function if registered or the original function if not. + * + * @param string $name Name of the function. + * @param array $arguments Arguments for the function. + * + * @return mixed The return value from the invoked callback or function. + */ + public static function __callStatic( $name, $arguments ) { + if ( array_key_exists( $name, self::$instance->function_mocks ) ) { + return call_user_func_array( self::$instance->function_mocks[ $name ], $arguments ); + } else { + return call_user_func_array( $name, $arguments ); + } + } + + /** + * Get the only existing instance of this class. 'get_instance' is not used to avoid conflicts since that's a widely used method name. + * + * @return FunctionsMockerHack The only existing instance of this class. + */ + public static function get_hack_instance() { + return self::$instance; + } +} diff --git a/tests/Tools/CodeHacking/Hacks/StaticMockerHack.php b/tests/Tools/CodeHacking/Hacks/StaticMockerHack.php new file mode 100644 index 00000000000..9d1709c3b1f --- /dev/null +++ b/tests/Tools/CodeHacking/Hacks/StaticMockerHack.php @@ -0,0 +1,193 @@ + [ + * 'some_method' => function($some_arg) { + * return 'foo' === $some_arg ? 'bar' : SomeClass::some_method($some_arg); + * } + * ] + * ]); + * + * 1 and 2 must be done during the unit testing bootstrap process. + * + * Note that unless the tests directory is included in the hacking via 'CodeHacker::initialize' + * (and they shouldn't!), test code files aren't hacked, therefore the original functions are always + * executed inside tests (and thus the above example won't stack-overflow). + */ +final class StaticMockerHack extends CodeHack { + + /** + * @var StaticMockerHack Holds the only existing instance of the class. + */ + private static $instance; + + /** + * Initializes the class. + * + * @param array $mockable_classes An associative array of class name => array of class methods. + * + * @throws \Exception $mockable_functions is not an array or is empty. + */ + public static function initialize( $mockable_classes ) { + if ( ! is_array( $mockable_classes ) || empty( $mockable_classes ) ) { + throw new \Exception( 'StaticMockerHack::initialize:: $mockable_classes must be a non-empty associative array of class name => array of class methods.' ); + } + + self::$instance = new StaticMockerHack( $mockable_classes ); + } + + /** + * StaticMockerHack constructor. + * + * @param array $mockable_classes An associative array of class name => array of class methods. + */ + private function __construct( $mockable_classes ) { + $this->mockable_classes = $mockable_classes; + } + + /** + * Hacks code by replacing elegible method invocations with an invocation a static method on this class composed from the class and the method names. + * + * @param string $code The code to hack. + * @param string $path The path of the file containing the code to hack. + * @return string The hacked code. + * + */ + public function hack( $code, $path ) { + $last_item = null; + + $tokens = $this->tokenize( $code ); + $code = ''; + $current_token = null; + + // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition + while ( $current_token = current( $tokens ) ) { + if ( $this->is_token_of_type( $current_token, T_STRING ) && in_array( $current_token[1], $this->mockable_classes, true ) ) { + $class_name = $current_token[1]; + $next_token = next( $tokens ); + if ( $this->is_token_of_type( $next_token, T_DOUBLE_COLON ) ) { + $called_member = next( $tokens )[1]; + $code .= __CLASS__ . "::invoke__{$called_member}__for__{$class_name}"; + } else { + // Reference to source class, but not followed by '::'. + $code .= $this->token_to_string( $current_token ) . $this->token_to_string( $next_token ); + } + } else { + // Not a reference to source class. + $code .= $this->token_to_string( $current_token ); + } + next( $tokens ); + } + + return $code; + } + + /** + * @var array Associative array of class name => associative array of method name => callback. + */ + private $method_mocks = array(); + + /** + * Register method mocks. + * + * @param array $mocks Mocks as an associative array of class name => associative array of method name => mock method with the same arguments as the original method. + * + * @throws \Exception Invalid input. + */ + public function register_method_mocks( $mocks ) { + $exception_text = 'StaticMockerHack::register_method_mocks: $mocks must be an associative array of class name => associative array of method name => callable.'; + + if ( ! is_array( $mocks ) ) { + throw new \Exception( $exception_text ); + } + + foreach ( $mocks as $class_name => $class_mocks ) { + if ( ! is_string( $class_name ) || ! is_array( $class_mocks ) ) { + throw new \Exception( $exception_text ); + } + foreach ( $class_mocks as $method_name => $method_mock ) { + if ( ! is_string( $method_name ) || ! is_callable( $method_mock ) ) { + throw new \Exception( $exception_text ); + } + if ( ! in_array( $class_name, $this->mockable_classes, true ) ) { + throw new \Exception( "FunctionsMockerHack::add_function_mocks: Can't mock methods of the '$class_name' class since it isn't in the list of mockable classes supplied to 'initialize'." ); + } + } + } + + $this->method_mocks = array_merge_recursive( $this->method_mocks, $mocks ); + } + + /** + * Register method mocks. + * + * @param array $mocks Mocks as an associative array of class name => associative array of method name => mock method with the same arguments as the original method. + * + * @throws \Exception Invalid input. + */ + public static function add_method_mocks( $mocks ) { + self::$instance->register_method_mocks( $mocks ); + } + + /** + * Unregister all the registered method mocks. + */ + public function reset() { + $this->method_mocks = array(); + } + + /** + * Handler for undefined static methods on this class, it invokes the mock for the method if both the class and the method are registered, or the original method in the original class if not. + * + * @param string $name Name of the method. + * @param array $arguments Arguments for the function. + * + * @return mixed The return value from the invoked callback or method. + * + * @throws \Exception Invalid method name. + */ + public static function __callStatic( $name, $arguments ) { + preg_match( '/invoke__(.+)__for__(.+)/', $name, $matches ); + if ( empty( $matches ) ) { + throw new \Exception( 'Invalid method ' . __CLASS__ . "::{$name}" ); + } + + $class_name = $matches[2]; + $method_name = $matches[1]; + + if ( array_key_exists( $class_name, self::$instance->method_mocks ) && array_key_exists( $method_name, self::$instance->method_mocks[ $class_name ] ) ) { + return call_user_func_array( self::$instance->method_mocks[ $class_name ][ $method_name ], $arguments ); + } else { + return call_user_func_array( "{$class_name}::{$method_name}", $arguments ); + } + } + + /** + * Get the only existing instance of this class. 'get_instance' is not used to avoid conflicts since that's a widely used method name. + * + * @return StaticMockerHack The only existing instance of this class. + */ + public static function get_hack_instance() { + return self::$instance; + } +} diff --git a/tests/Tools/CodeHacking/README.md b/tests/Tools/CodeHacking/README.md new file mode 100644 index 00000000000..5bd143e14dd --- /dev/null +++ b/tests/Tools/CodeHacking/README.md @@ -0,0 +1,156 @@ +# Code Hacking + +Code hacking is a mechanism that modifies PHP code files while they are loaded. It's intended to ease unit testing code that would otherwise be very difficult or impossible to test (and **only** for this - see [An important note](#an-important-note) about that). + +Currently, the code hacker allows to do the following inside unit tests: + +* Replace standalone functions with custom callbacks. +* Replace invocations to public static methods with custom callbacks. +* Create subclasses of `final` classes. + +## How to use + +Let's go through an example. + +First, create a file named `class-wc-admin-foobar.php` in `includes/admin` with the following code: + +``` + function( $name, $default = false ) { + return "Mocked get_option invoked for '$name'"; + } + ]); + + $expected = "The option returns: Mocked get_option invoked for 'some_option'"; + $actual = $tested->do_something_that_depends_on_an_option(); + $this->assertEquals( $expected, $actual ); + } + + public function test_static_method_mocking() { + $tested = new WC_Admin_Foobar(); + + StaticMockerHack::add_method_mocks([ + 'WC_Some_Legacy_Service' => [ + 'do_something' => function( $what ) { + return "MOCKED do_something invoked for '$what'"; + } + ] + ]); + + $expected = "The legacy service returns: MOCKED do_something invoked for 'foobar'"; + $actual = $tested->do_something_that_depends_on_the_legacy_service( 'foobar' ); + $this->assertEquals( $expected, $actual ); + } +} +``` + +Then run `vendor/bin/phpunit tests/legacy/unit-tests/admin/class-wc-tests-admin-foobar.php` and see the magic happen. + +### Mocking functions + +For a function to be mockable its name needs to be included in the array returned by `tests/legacy/mockable-functions.php`, so if you need to mock a function that is not included in the array, just go and add it. + +Function mocks can be defined by using `FunctionsMockerHack::add_function_mocks`. This method accepts an associative array where keys are function names and values are callbacks with the same signature as the functions they are replacing. + +If you ever need to remove the configured function mocks from inside a test, you can do so by executing `FunctionsMockerHack::get_hack_instance()->reset()`. This is done automatically before each test via PHPUnit's `BeforeTestHook`, so normally you won't need to do that. + +Note that the code hacker is configured so that only the production code files are modified, the tests code itself is **not** modified. This means that you can use the original functions within your tests even if you have mocked them, for example the following would work: + +``` +//Mock get_option but only if the requested option name is 'foo' +FunctionsMockerHack::add_function_mocks([ + 'get_option' => function($name, $default = false) { + return 'foo' === $name ? 'mocked value for option foo' : get_option( $name, $default ); + } +]); +``` + +### Mocking public static methods + +For a public static method to be mockable the name of the class that defines it needs to be included in the array returned by `tests/legacy/classes-with-mockable-static-methods.php`, so if you need to mock a static method for a class that is not included in the array, just go and add it. + +Static method mocks can be defined by using `StaticMockerHack::add_method_mocks`. This method accepts an associative array where keys are class names and values are in turn associative arrays, those having method names as keys and callbacks with the same signature as the methods they are replacing as values. + +If you ever need to remove the configured static method mocks from inside a test, you can do so by executing `StaticMockerHack::get_hack_instance()->reset()`. This is done automatically before each test via PHPUnit's `BeforeTestHook`, so normally you won't need to do that. + +Note that the code hacker is configured so that only the production code files are modified, the tests code itself is **not** modified. This means that you can use the original static methods within your tests even if you have mocked them, for example the following would work: + +``` +StaticMockerHack::add_method_mocks([ + 'WC_Some_Legacy_Service' => [ + //Mock WC_Some_Legacy_Service::do_something but only if the supplied parameter is 'foo' + 'do_something' => function( $what ) { + return 'foo' === $what ? "MOCKED do_something invoked for '$what'" : WC_Some_Legacy_Service::do_something( $what ); + } + ] +]); +``` + +### Subclassing `final` classes + +Inside your test files you can create classes that extend classes marked as `final` thanks to the `BypassFinalsHack` that is registered at bootstrap time. No extra configuration is needed. + +If you want to try it out, mark the `WC_Admin_Foobar` in the previos example as `final`, then add the following to the tests file: `class WC_Admin_Foobar_Subclass extends WC_Admin_Foobar {}`. Without the hack you would get a `Class WC_Admin_Foobar_Subclass may not inherit from final class (WC_Admin_Foobar)` error when trying to run the tests. + +## How it works under the hood + +The core of the code hacker is the `CodeHacker` class, which is based on [the Bypass Finals project](https://github.com/dg/bypass-finals) by David Grudl. This class is actually [a streamWrapper class](https://www.php.net/manual/en/class.streamwrapper.php) for the regular filesystem, most of its methods are just short-circuited to the regular PHP filesystem handling functions but the `stream_open` method contains some code that allows the magic to happen. What it does (for PHP files only) is to read the file contents and apply all the necessary modifications to it, then if the code has been modified it is stored in a temporary file which is then the one that receives any further filesystem operations instead of the original file. That way, for all practical purposes the content of the file is the "hacked" content. + +The files inside `tests/Tools/CodeHacking/Hacks` implement the "hacks" (code file modifications) that are registered via `CodeHacker::add_hack` within `tests/legacy/bootstrap.php`. + +A `BeforeTestHook` is used to reset all hacks to its initial state to ensure that no functions or methods are being mocked when the test starts. + +The functions mocker works by replacing all instances of `the_function(...)` with `FunctionsMockerHack::the_function(...)`, then `FunctionsMockerHack::__call_static` is implemented in a way that invokes the appropriate callback if defined for the invoked function, or reverts to executing the original function if not. The static methods mocker works similarly, but replacing instances of `TheClass::the_method(...)` with `StaticMockerHack::invoke__the_method__for__TheClass(...)`. + +## Creating new hacks + +If you ever need to define a new hack to cover a different kind of code that's difficult to test, that's what you need to do. + +First, implement the hack as a class that contains a `public function hack($code, $path)` method and a `public function reset()` method. The former takes in `$code` a string with the contents of the file pointed by `$path` and returns the modified code, the later reverts the hack to its original state (e.g. for `FunctionsMockerHack` it unregisters all the previously registered function mocks). For convenience you can make your hack a subclass of `CodeHack` but that's not mandatory. + +Second, configure the hack as required inside the `initialize_code_hacker` method in `tests/legacy/bootstrap.php`, and register it using `CodeHacker::add_hack`. + +## Temporarily disabling the code hacker + +In a few rare cases the code hacker will cause problems with tests that do write operations on the local filesystem. In these cases it is possible to temporarily disable the code hacker using `self::disable_code_hacker()` and `self::reenable_code_hacker()` in the test (these methods are defined in `WC_Unit_Test_Case`). These methods are carefully written so that they won't enable the code hacker if it wasn't enabled when the test started, and there's a disabling requests count in place to ensure that the code hacker isn't enabled before it should. + +One of these cases is the usage of the `copy` command to copy files. Since this function is used in a few tests, a convenience `file_copy` method is defined in `WC_Unit_Test_Case`; it just temporarily disables the hacker, does the copy, and reenables the hacker. + +## An important note + +The code hacker is intended to be a **last resort** mechanism to test stuff that it's **really** difficult or impossible to test otherwise - the mechanisms already in place to help testing (e.g. the PHPUnit's mocks or the Woo helpers) should still be used whenever possible. And of course, the code hacker should not be an excuse to write code that's difficult to test. diff --git a/tests/bin/e2e-test-integration.js b/tests/bin/e2e-test-integration.js deleted file mode 100755 index d30d5f1068b..00000000000 --- a/tests/bin/e2e-test-integration.js +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env node - -const { spawnSync } = require( 'child_process' ); -const program = require( 'commander' ); -const { useJestPuppeteerConfig } = require( 'puppeteer-utils' ); - -program - .usage( ' [options]' ) - .option( '--dev', 'Development mode' ) - .parse( process.argv ); - -const testEnvVars = { - NODE_ENV: 'test:e2e', - JEST_PUPPETEER_CONFIG: 'tests/e2e-tests/config/jest-puppeteer.config.js', - NODE_CONFIG_DIR: 'tests/e2e-tests/config', -}; - -if ( program.dev ) { - testEnvVars.PUPPETEER_HEADLESS = 'false'; - testEnvVars.PUPPETEER_SLOWMO = '50'; - - delete testEnvVars.JEST_PUPPETEER_CONFIG; - useJestPuppeteerConfig(); -} - -const envVars = Object.assign( {}, process.env, testEnvVars ); - -let jestProcess = spawnSync( - 'jest', - [ - '--maxWorkers=1', - '--config=tests/e2e-tests/config/jest.config.js', - '--rootDir=./', - '--verbose', - program.args, - ], - { - stdio: 'inherit', - env: envVars, - } -); - -console.log( 'Jest exit code: ' + jestProcess.status ); - -// Pass Jest exit code to npm -process.exit( jestProcess.status ); diff --git a/tests/e2e-tests/config/jest-puppeteer.config.js b/tests/e2e-tests/config/jest-puppeteer.config.js deleted file mode 100644 index 13bd10fcc00..00000000000 --- a/tests/e2e-tests/config/jest-puppeteer.config.js +++ /dev/null @@ -1,8 +0,0 @@ -/** @format */ - -module.exports = { - launch: { - // Required for the logged out and logged in tests so they don't share app state/token. - browserContext: 'incognito', - } -}; diff --git a/tests/e2e-tests/config/jest.config.js b/tests/e2e-tests/config/jest.config.js deleted file mode 100644 index 96ea52f4907..00000000000 --- a/tests/e2e-tests/config/jest.config.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * External dependencies - */ -const { jestConfig } = require( 'puppeteer-utils' ); -const modifiedConfig = jestConfig; -const afterEnvSetup = modifiedConfig.setupFilesAfterEnv; - -afterEnvSetup.push( '/tests/e2e-tests/config/jest.setup.js'); -modifiedConfig.setupFilesAfterEnv = afterEnvSetup; - -// Sort test path alphabetically. This is needed so that `activate-and-setup` tests run first -modifiedConfig.testSequencer = '/tests/e2e-tests/config/jest-custom-sequencer.js'; - -module.exports = modifiedConfig; diff --git a/tests/e2e-tests/config/jest.setup.js b/tests/e2e-tests/config/jest.setup.js deleted file mode 100644 index 5588d7ed5e7..00000000000 --- a/tests/e2e-tests/config/jest.setup.js +++ /dev/null @@ -1,12 +0,0 @@ -/** format */ - -//Set the default test timeout to 60s -let jestTimeoutInMilliSeconds = 60000; - -// When running test in the Development mode, the test timeout is increased to 2 minutes which allows for errors to be inspected. -// Use `await jestPuppeteer.debug()` in test code to pause execution. -if ( process.env.JEST_PUPPETEER_CONFIG === 'tests/e2e-tests/config/jest-puppeteer.dev.config.js' ) { - jestTimeoutInMilliSeconds = 120000; -} - -jest.setTimeout( jestTimeoutInMilliSeconds ); diff --git a/tests/e2e-tests/README.md b/tests/e2e/README.md similarity index 87% rename from tests/e2e-tests/README.md rename to tests/e2e/README.md index 189b1cfd4c3..898b5b89d2f 100644 --- a/tests/e2e-tests/README.md +++ b/tests/e2e/README.md @@ -54,7 +54,7 @@ We recommend using Docker for running tests locally in order for the test enviro ### Environment Variables -During the process of Docker building a container with test site for running tests, site URL is being set. Admin and customer users are also being created in advance with details specified in the `docker-compose.yaml` file. As a result, there is `./tests/e2e-tests/config/default.json` file that contains pre-set variables needed to run the test: +During the process of Docker building a container with test site for running tests, site URL is being set. Admin and customer users are also being created in advance with details specified in the `docker-compose.yaml` file. As a result, there is `./tests/e2e/config/default.json` file that contains pre-set variables needed to run the test: ``` { @@ -72,7 +72,7 @@ During the process of Docker building a container with test site for running tes } ``` -If you changed either site URL or one of the users details in the `docker-compose.yaml` file, you'd need to copy the content of the `default.json`, paste it to `test:e2e.json` and edit it further there to match your own setup. +If you changed either site URL or one of the users details in the `docker-compose.yaml` file, you'd need to copy the content of the `default.json`, paste it to `test-e2e.json` and edit it further there to match your own setup. ### Jest test sequencer @@ -90,11 +90,13 @@ Setup Wizard e2e test (located in `activate-and-setup` directory) will run befor - Run `npm install` +- Run `npm install jest --global` + - Run `composer install --no-dev` - Run `npm run build` -- Run the following command to build the test site using Docker: `docker-compose up` and watch the site being built. Note that it may take a few minutes the first time you do that. The process is considered completed when the messages letting you know that WordPress was installed, WooCommerce was activated and users created will be displayed: +- Run the following command to build the test site using Docker: `npm run docker:up` and watch the site being built. Note that it may take a few minutes the first time you do that. The process is considered completed when the messages letting you know that WordPress was installed, WooCommerce was activated and users created will be displayed: ``` wordpress-cli_1 | Success: WordPress installed successfully. @@ -132,14 +134,14 @@ Tests are being run headless by default. However, sometimes it's useful to obser npm run test:e2e-dev ``` -The dev mode also enables SlowMo mode. SlowMo slows down Puppeteer’s operations so we can better see what is happening in the browser. You can adjust the SlowMo value by editing `PUPPETEER_SLOWMO` variable in `./tests/bin/e2e-test-integration.js` file. The default `PUPPETEER_SLOWMO=50` means test actions will be slowed down by 50 milliseconds. +The dev mode also enables SlowMo mode. SlowMo slows down Puppeteer’s operations so we can better see what is happening in the browser. You can adjust the SlowMo value by copying `/tests/e2e/env/config/jest.puppetee.config.js` to `/tests/e2e/config` and editing the value in that file. The default `PUPPETEER_SLOWMO=50` means test actions will be slowed down by 50 milliseconds. ### How to run an individual test To run an individual test, use the direct path to the spec. For example: ```bash -npm run test:e2e ./tests/e2e-tests/specs/wp-admin/wp-admin-product-new.test.js +npm run test:e2e ./tests/e2e/specs/wp-admin/wp-admin-product-new.test.js ``` ### How to skip tests @@ -159,7 +161,7 @@ it.only( 'Can make sure WooCommerce is activated. If not, activate it', async () As a result, when you run `setup-wizard.test.js`, only the login and activate tests will run. The rest will be skipped. You should see the following in the terminal: ``` - PASS tests/e2e-tests/specs/activate-and-setup/setup-wizard.test.js (11.927s) + PASS tests/e2e/specs/activate-and-setup/setup-wizard.test.js (11.927s) Store owner can login and make sure WooCommerce is activated ✓ Can login (7189ms) ✓ Can make sure WooCommerce is activated. If not, activate it (1187ms) @@ -196,7 +198,7 @@ We use the following tools to write e2e tests: - [jest-puppeteer](https://github.com/smooth-code/jest-puppeteer) – provides all required configuration to run tests using Puppeteer - [expect-puppeteer](https://github.com/smooth-code/jest-puppeteer/tree/master/packages/expect-puppeteer) – assertion library for Puppeteer -Tests are kept in `tests/e2e-tests/specs` folder. +Tests are kept in `tests/e2e/specs` folder. The following packages are being used to write tests: @@ -212,13 +214,5 @@ For Puppeteer debugging, follow [Google's documentation](https://developers.goog ### How to stop and restart Docker - Press `Ctrl+C` in the terminal window where the containers are running -- Stop the container(s) using the following command: `docker-compose down` -- Restart the containers using the following command: `docker-compose up` - -### How to stop Docker and do a clean restart - -Steps below will allow building a brand new site with a clean DB and no data as it was built initially: - -- Press `Ctrl+C` in the terminal window where the containers are running -- Stop the container(s) and delete all volumes using the following command: `docker-compose down -v` -- Restart the containers using the following command: `docker-compose up --build` +- Stop the container(s) using the following command: `npm run docker:down` +- Restart the containers using the following command: `npm run docker:up` diff --git a/tests/e2e/bin/build.js b/tests/e2e/bin/build.js new file mode 100755 index 00000000000..1f8a94d1da0 --- /dev/null +++ b/tests/e2e/bin/build.js @@ -0,0 +1,163 @@ +/** + * script to build packages into `build/` directory. + * + * Example: + * node ./bin/packages/build.js + */ + +/** + * External dependencies + */ +const fs = require( 'fs' ); +const path = require( 'path' ); +const glob = require( 'glob' ); +const babel = require( '@babel/core' ); +const chalk = require( 'chalk' ); +const mkdirp = require( 'mkdirp' ); +const deasync = require( 'deasync' ); + +/** + * Internal dependencies + */ +const getPackages = require( './get-packages' ); +const getBabelConfig = require( './get-babel-config' ); + +/** + * Module Constants + */ +const PACKAGES_DIR = path.resolve( __dirname, '../' ); +const SRC_DIR = 'src'; +const BUILD_DIR = { + main: 'build', + module: 'build-module', +}; +const DONE = chalk.reset.inverse.bold.green( ' DONE ' ); + +/** + * Get the package name for a specified file + * + * @param {string} file File name + * @return {string} Package name + */ +function getPackageName( file ) { + return path.relative( PACKAGES_DIR, file ).split( path.sep )[ 0 ]; +} + +const isJsFile = ( filepath ) => { + return /.\.js$/.test( filepath ); +}; + +/** + * Get Build Path for a specified file + * + * @param {string} file File to build + * @param {string} buildFolder Output folder + * @return {string} Build path + */ +function getBuildPath( file, buildFolder ) { + const pkgName = getPackageName( file ); + const pkgSrcPath = path.resolve( PACKAGES_DIR, pkgName, SRC_DIR ); + const pkgBuildPath = path.resolve( PACKAGES_DIR, pkgName, buildFolder ); + const relativeToSrcPath = path.relative( pkgSrcPath, file ); + return path.resolve( pkgBuildPath, relativeToSrcPath ); +} + +/** + * Given a list of scss and js filepaths, divide them into sets them and rebuild. + * + * @param {Array} files list of files to rebuild + */ +function buildFiles( files ) { + // Reduce files into a unique sets of javaScript files and scss packages. + const buildPaths = files.reduce( + ( accumulator, filePath ) => { + if ( isJsFile( filePath ) ) { + accumulator.jsFiles.add( filePath ); + } + return accumulator; + }, + { jsFiles: new Set() } + ); + + buildPaths.jsFiles.forEach( buildJsFile ); +} + +/** + * Build a javaScript file for the required environments (node and ES5) + * + * @param {string} file File path to build + * @param {boolean} silent Show logs + */ +function buildJsFile( file, silent ) { + buildJsFileFor( file, silent, 'main' ); + buildJsFileFor( file, silent, 'module' ); +} + +/** + * Build a file for a specific environment + * + * @param {string} file File path to build + * @param {boolean} silent Show logs + * @param {string} environment Dist environment (node or es5) + */ +function buildJsFileFor( file, silent, environment ) { + const buildDir = BUILD_DIR[ environment ]; + const destPath = getBuildPath( file, buildDir ); + const babelOptions = getBabelConfig( environment ); + babelOptions.sourceMaps = true; + babelOptions.sourceFileName = file; + + mkdirp.sync( path.dirname( destPath ) ); + const transformed = babel.transformFileSync( file, babelOptions ); + fs.writeFileSync( destPath + '.map', JSON.stringify( transformed.map ) ); + fs.writeFileSync( + destPath, + transformed.code + + '\n//# sourceMappingURL=' + + path.basename( destPath ) + + '.map' + ); + + if ( ! silent ) { + process.stdout.write( + chalk.green( ' \u2022 ' ) + + path.relative( PACKAGES_DIR, file ) + + chalk.green( ' \u21D2 ' ) + + path.relative( PACKAGES_DIR, destPath ) + + '\n' + ); + } +} + +/** + * Build the provided package path + * + * @param {string} packagePath absolute package path + */ +function buildPackage( packagePath ) { + const srcDir = path.resolve( packagePath, SRC_DIR ); + const jsFiles = glob.sync( `${ srcDir }/**/*.js`, { + ignore: [ + `${ srcDir }/**/test/**/*.js`, + `${ srcDir }/**/__mocks__/**/*.js`, + ], + nodir: true, + } ); + + process.stdout.write( `${ path.basename( packagePath ) }\n` ); + + // Build js files individually. + jsFiles.forEach( ( file ) => buildJsFile( file, true ) ); + + process.stdout.write( `${ DONE }\n` ); +} + +const files = process.argv.slice( 2 ); + +if ( files.length ) { + buildFiles( files ); +} else { + process.stdout.write( chalk.inverse( '>> Building packages \n' ) ); + getPackages().forEach( buildPackage ); + process.stdout.write( '\n' ); +} diff --git a/tests/e2e/bin/get-babel-config.js b/tests/e2e/bin/get-babel-config.js new file mode 100644 index 00000000000..e79bc306d07 --- /dev/null +++ b/tests/e2e/bin/get-babel-config.js @@ -0,0 +1,71 @@ +/** + * External dependencies + */ +const { get, map } = require( 'lodash' ); +const babel = require( '@babel/core' ); + +/** + * WordPress dependencies + */ +const { options: babelDefaultConfig } = babel.loadPartialConfig( { + configFile: '@wordpress/babel-preset-default', +} ); +const plugins = babelDefaultConfig.plugins; +if ( ! process.env.SKIP_JSX_PRAGMA_TRANSFORM ) { + plugins.push( [ '@wordpress/babel-plugin-import-jsx-pragma', { + scopeVariable: 'createElement', + source: '@wordpress/element', + isDefault: false, + } ] ); +} + +const overrideOptions = ( target, targetName, options ) => { + if ( get( target, [ 'file', 'request' ] ) === targetName ) { + return [ targetName, Object.assign( + {}, + target.options, + options + ) ]; + } + return target; +}; + +const babelConfigs = { + main: Object.assign( + {}, + babelDefaultConfig, + { + plugins, + presets: map( + babelDefaultConfig.presets, + ( preset ) => overrideOptions( preset, '@babel/preset-env', { + modules: 'commonjs', + } ) + ), + } + ), + module: Object.assign( + {}, + babelDefaultConfig, + { + plugins: map( + plugins, + ( plugin ) => overrideOptions( plugin, '@babel/plugin-transform-runtime', { + useESModules: true, + } ) + ), + presets: map( + babelDefaultConfig.presets, + ( preset ) => overrideOptions( preset, '@babel/preset-env', { + modules: false, + } ) + ), + } + ), +}; + +function getBabelConfig( environment ) { + return babelConfigs[ environment ]; +} + +module.exports = getBabelConfig; diff --git a/tests/e2e/bin/get-packages.js b/tests/e2e/bin/get-packages.js new file mode 100644 index 00000000000..dc6eaeb0ea8 --- /dev/null +++ b/tests/e2e/bin/get-packages.js @@ -0,0 +1,83 @@ +/** + * External dependencies + */ +const fs = require( 'fs' ); +const path = require( 'path' ); +const { overEvery, compact, includes, negate } = require( 'lodash' ); + +/** + * Absolute path to packages directory. + * + * @type {string} + */ +const PACKAGES_DIR = path.resolve( __dirname, '../' ); + +const { + /** + * Comma-separated string of packages to include in build. + * + * @type {string} + */ + INCLUDE_PACKAGES, + + /** + * Comma-separated string of packages to exclude from build. + * + * @type {string} + */ + EXCLUDE_PACKAGES, +} = process.env; + +/** + * Given a comma-separated string, returns a filter function which returns true + * if the item is contained within as a comma-separated entry. + * + * @param {Function} filterFn Filter function to call with item to test. + * @param {string} list Comma-separated list of items. + * + * @return {Function} Filter function. + */ +const createCommaSeparatedFilter = ( filterFn, list ) => { + const listItems = list.split( ',' ); + return ( item ) => filterFn( listItems, item ); +}; + +/** + * Returns true if the given base file name for a file within the packages + * directory is itself a directory. + * + * @param {string} file Packages directory file. + * + * @return {boolean} Whether file is a directory. + */ +function isDirectory( file ) { + return fs.lstatSync( path.resolve( PACKAGES_DIR, file ) ).isDirectory(); +} + +/** + * Filter predicate, returning true if the given base file name is to be + * included in the build. + * + * @param {string} pkg File base name to test. + * + * @return {boolean} Whether to include file in build. + */ +const filterPackages = overEvery( compact( [ + isDirectory, + INCLUDE_PACKAGES && createCommaSeparatedFilter( includes, INCLUDE_PACKAGES ), + EXCLUDE_PACKAGES && createCommaSeparatedFilter( negate( includes ), EXCLUDE_PACKAGES ), +] ) ); + +/** + * Returns the absolute path of all WordPress packages + * + * @return {Array} Package paths + */ +function getPackages() { + return fs + .readdirSync( PACKAGES_DIR ) + .filter( filterPackages ) + .map( ( file ) => path.resolve( PACKAGES_DIR, file ) ); +} + +module.exports = getPackages; diff --git a/tests/e2e/config/jest.config.js b/tests/e2e/config/jest.config.js new file mode 100644 index 00000000000..cc3a355f4fd --- /dev/null +++ b/tests/e2e/config/jest.config.js @@ -0,0 +1,8 @@ +const path = require( 'path' ); +const { jestConfig: baseE2Econfig } = require( '@woocommerce/e2e-environment' ); + +module.exports = { + ...baseE2Econfig, + // Specify the path of your project's E2E tests here. + roots: [ path.resolve( __dirname, '../specs' ) ], +}; diff --git a/tests/e2e-tests/config/test:e2e.json b/tests/e2e/config/test-e2e.json similarity index 100% rename from tests/e2e-tests/config/test:e2e.json rename to tests/e2e/config/test-e2e.json diff --git a/tests/e2e/docker/initialize.sh b/tests/e2e/docker/initialize.sh new file mode 100755 index 00000000000..f04484a8947 --- /dev/null +++ b/tests/e2e/docker/initialize.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +echo "Initializing WooCommerce E2E" + +wp plugin install woocommerce --activate +wp theme install twentynineteen --activate +wp user create customer customer@woocommercecoree2etestsuite.com --user_pass=password --role=customer --path=/var/www/html diff --git a/tests/e2e/env/.env b/tests/e2e/env/.env new file mode 100644 index 00000000000..c78edfceeaf --- /dev/null +++ b/tests/e2e/env/.env @@ -0,0 +1,15 @@ +# WordPress container environment +WORDPRESS_DB_HOST=db +WORDPRESS_DB_NAME=testdb +WORDPRESS_DB_USER=wordpress +WORDPRESS_DB_PASSWORD=wordpress +WORDPRESS_TABLE_PREFIX=wp_ +WORDPRESS_DEBUG=1 + +# WordPress CLI environment +WORDPRESS_PORT=8084 +WORDPRESS_HOST=wordpress-www:80 +WORDPRESS_TITLE=WooCommerce Core E2E Test Suite +WORDPRESS_LOGIN=admin +WORDPRESS_PASSWORD=password +WORDPRESS_EMAIL=admin@woocommercecoree2etestsuite.com diff --git a/tests/e2e/env/.eslintrc.js b/tests/e2e/env/.eslintrc.js new file mode 100644 index 00000000000..a54292c2b19 --- /dev/null +++ b/tests/e2e/env/.eslintrc.js @@ -0,0 +1,15 @@ +module.exports = { + extends: [ + 'plugin:jest/recommended', + ], + env: { + 'jest/globals': true, + }, + globals: { + page: true, + browser: true, + context: true, + jestPuppeteer: true, + }, + plugins: [ 'jest' ], +}; diff --git a/tests/e2e/env/.npmrc b/tests/e2e/env/.npmrc new file mode 100644 index 00000000000..43c97e719a5 --- /dev/null +++ b/tests/e2e/env/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/tests/e2e/env/CHANGELOG.md b/tests/e2e/env/CHANGELOG.md new file mode 100644 index 00000000000..fab008b360d --- /dev/null +++ b/tests/e2e/env/CHANGELOG.md @@ -0,0 +1,3 @@ +1.0.0 (unreleased) + +- Initial release \ No newline at end of file diff --git a/tests/e2e/env/README.md b/tests/e2e/env/README.md new file mode 100644 index 00000000000..2d5f40dbea8 --- /dev/null +++ b/tests/e2e/env/README.md @@ -0,0 +1,197 @@ +# End to End Testing Environment + +A reusable and extendable E2E testing environment for WooCommerce extensions. + +## Installation + +```bash +npm install @woocommerce/e2e-environment --save +npm install jest --global +``` + +## Configuration + +The `@woocommerce/e2e-environment` package exports configuration objects that can be consumed in JavaScript config files in your project. Additionally, it contains several files to serve as the base for a Docker container and Travis CI setup. + +### Babel Config + +Make sure you `npm install @babel/preset-env --save` if you have not already done so. Afterwards, extend your project's `babel.config.js` to contain the expected presets for E2E testing. + +```js +const { babelConfig: e2eBabelConfig } = require( '@woocommerce/e2e-environment' ); + +module.exports = function( api ) { + api.cache( true ); + + return { + ...e2eBabelConfig, + presets: [ + ...e2eBabelConfig.presets, + '@wordpress/babel-preset-default', + ], + .... + }; +}; +``` + +### ES Lint Config + +The E2E environment uses Puppeteer for headless browser testing, which uses certain globals variables. Avoid ES Lint errors by extending the config. + +```js +const { esLintConfig: baseConfig } = require( '@woocommerce/e2e-environment' ); + +module.exports = { + ...baseConfig, + root: true, + parser: 'babel-eslint', + extends: [ + ...baseConfig.extends, + 'wpcalypso/react', + 'plugin:jsx-a11y/recommended', + ], + plugins: [ + ...baseConfig.plugins, + 'jsx-a11y', + ], + env: { + ...baseConfig.env, + browser: true, + node: true, + }, + globals: { + ...baseConfig.globals, + wp: true, + wpApiSettings: true, + wcSettings: true, + }, + .... +}; +``` + +### Jest Config + +The E2E environment uses Jest as a test runner. Extending the base config is needed in order for Jest to run your project's test files. + +```js +const path = require( 'path' ); +const { jestConfig: baseE2Econfig } = require( '@woocommerce/e2e-environment' ); + +module.exports = { + ...baseE2Econfig, + // Specify the path of your project's E2E tests here. + roots: [ path.resolve( __dirname, '../specs' ) ], +}; +``` + +**NOTE:** Your project's Jest config file is expected to found at: `tests/e2e/config/jest.config.js`. + +### Webpack Config + +The E2E environment provides a `@woocommerce/e2e-tests` alias for easy use of the WooCommerce E2E test helpers. + +```js +const { webpackAlias: coreE2EAlias } = require( '@woocommerce/e2e-environment' ); + +module.exports = { + .... + resolve: { + alias: { + ...coreE2EAlias, + .... + }, + }, +}; +``` + +### Docker Setup + +The E2E environment will look for a `docker-compose.yaml` file in your project root. This will be combined with the base Docker config in the package. This is where you'll map your local project files into the Docker container(s). + +```yaml +version: '3.3' + +services: + + wordpress-www: + volumes: + # This path is relative to the first config file + # which is in node_modules/@woocommerce/e2e/env + - "../../../:/var/www/html/wp-content/plugins/your-project-here" + + wordpress-cli: + volumes: + - "../../../:/var/www/html/wp-content/plugins/your-project-here" +``` + +#### Docker Container Initialization Script + +You can provide an initialization script that will run in the WP-CLI Docker container. Place an executable file at `tests/e2e/docker/initialize.sh` in your project and it will be copied into the container and executed. While you can run any commands you wish, the intent here is to use WP-CLI to set up your testing environment. E.g.: + +``` +#!/bin/bash + +echo "Initializing WooCommerce E2E" + +wp plugin install woocommerce --activate +wp theme install twentynineteen --activate +wp user create customer customer@woocommercecoree2etestsuite.com --user_pass=password --role=customer --path=/var/www/html +``` + +### Additional Packages + +There are a few packages you may find useful in writing tests scripts. You can see these in use in the `tests/e2e/utils` and `tests/e2e/specs` folders. + +- `@wordpress/e2e-test-utils` +- `config` + +### Travis CI + +Add the following to the appropriate sections of your `.travis.yml` config file. + +```yaml +version: ~> 1.0 + + include: + - name: "Core E2E Tests" + php: 7.4 + env: WP_VERSION=latest WP_MULTISITE=0 RUN_E2E=1 + +.... + +script: + - npm install jest --global + - npm explore @woocommerce/e2e-environment -- npm run test:e2e + +.... + +after_script: + - npm explore @woocommerce/e2e-environment -- npm run docker:down +``` + +Use `[[ ${RUN_E2E} == 1 ]]` in your bash scripts to test for the core e2e test run. + +## Usage + +Start Docker + +```bash +npm explore @woocommerce/e2e-environment -- npm run docker:up +``` + +Run E2E Tests + +```bash +npm explore @woocommerce/e2e-environment -- npm run test:e2e +npm explore @woocommerce/e2e-environment -- npm run test:e2e-dev +``` + +Stop Docker + +```bash +npm explore @woocommerce/e2e-environment -- npm run docker:down +``` + +## Additional information + +Refer to [`tests/e2e/specs`](https://github.com/woocommerce/woocommerce/tree/master/tests/e2e/specs) for some test examples, and [`tests/e2e`](https://github.com/woocommerce/woocommerce/tree/master/tests/e2e) for general information on e2e tests. diff --git a/tests/e2e/env/babel.config.js b/tests/e2e/env/babel.config.js new file mode 100644 index 00000000000..197e0cf8cc2 --- /dev/null +++ b/tests/e2e/env/babel.config.js @@ -0,0 +1,12 @@ +module.exports = { + presets: [ + [ + '@babel/preset-env', + { + targets: { + node: 'current', + }, + }, + ], + ], +}; diff --git a/tests/e2e/env/bin/docker-compose.js b/tests/e2e/env/bin/docker-compose.js new file mode 100755 index 00000000000..3ba640585a3 --- /dev/null +++ b/tests/e2e/env/bin/docker-compose.js @@ -0,0 +1,74 @@ +#!/usr/bin/env node + +const { spawnSync } = require( 'child_process' ); +const program = require( 'commander' ); +const path = require( 'path' ); +const fs = require( 'fs' ); +const getAppPath = require( '../utils/app-root' ); + +const dockerArgs = []; +let command = ''; + +program + .command( 'up', 'Start and build the Docker container' ) + .command( 'down', 'Stop the Docker container and remove volumes' ) + .action( ( cmd, options ) => { + arg = options.args ? options.args[ 0 ] : options[ 0 ]; + if ( 'up' === arg ) { + command = 'up'; + dockerArgs.push( 'up', '--build', '-d' ); + } + + if ( 'down' === arg ) { + command = 'down'; + dockerArgs.push( 'down', '-v' ); + } + } ) + .parse( process.argv ); + +const appPath = getAppPath(); +const envVars = {}; + +if ( appPath ) { + // Look for a Docker compose file in the dependent app's path. + const appDockerComposefile = path.resolve( appPath, 'docker-compose.yaml' ); + + // Specify the app's Docker compose file in our command. + if ( fs.existsSync( appDockerComposefile ) ) { + dockerArgs.unshift( '-f', appDockerComposefile ); + } + + if ( 'up' === command ) { + // Look for an initialization script in the dependent app. + const appInitFile = path.resolve( appPath, 'tests/e2e/docker/initialize.sh' ); + + // If found, copy it into the wp-cli Docker context so + // it gets picked up by the entrypoint script. + if ( fs.existsSync( appInitFile ) ) { + fs.copyFileSync( + appInitFile, + path.resolve( __dirname, '../docker/wp-cli/initialize.sh' ) + ); + } + } + + // Provide an "app name" to use in Docker container names. + envVars.APP_NAME = path.basename( appPath ); +} + +// Ensure that the first Docker compose file loaded is from our local env. +dockerArgs.unshift( '-f', path.resolve( __dirname, '../docker-compose.yaml' ) ); + +const dockerProcess = spawnSync( + 'docker-compose', + dockerArgs, + { + stdio: 'inherit', + env: Object.assign( {}, process.env, envVars ), + } +); + +console.log( 'Docker exit code: ' + dockerProcess.status ); + +// Pass Docker exit code to npm +process.exit( dockerProcess.status ); diff --git a/tests/e2e/env/bin/e2e-test-integration.js b/tests/e2e/env/bin/e2e-test-integration.js new file mode 100755 index 00000000000..d45d38d5389 --- /dev/null +++ b/tests/e2e/env/bin/e2e-test-integration.js @@ -0,0 +1,77 @@ +#!/usr/bin/env node + +const { spawnSync } = require( 'child_process' ); +const program = require( 'commander' ); +const path = require( 'path' ); +const fs = require( 'fs' ); +const getAppPath = require( '../utils/app-root' ); + +program + .usage( ' [options]' ) + .option( '--dev', 'Development mode' ) + .parse( process.argv ); + +const appPath = getAppPath(); + +const nodeConfigDirs = [ + path.resolve( __dirname, '../config' ), +]; + +if ( appPath ) { + nodeConfigDirs.unshift( + path.resolve( appPath, 'tests/e2e/config' ) + ); +} + +const testEnvVars = { + NODE_ENV: 'test-e2e', + JEST_PUPPETEER_CONFIG: path.resolve( + __dirname, + '../config/jest-puppeteer.config.js' + ), + NODE_CONFIG_DIR: nodeConfigDirs.join( ':' ), + node_config_dev: program.dev ? 'yes' : 'no', + jest_test_timeout: program.dev ? 120000 : 30000, +}; + +let jestCommand = 'jest'; +const jestArgs = [ + '--maxWorkers=1', + '--rootDir=./', + '--verbose', + ...program.args, +]; + +if ( program.dev ) { + jestCommand = 'npx'; + jestArgs.unshift( 'ndb', 'jest' ); +} + +const envVars = Object.assign( {}, process.env, testEnvVars ); + +let configPath = path.resolve( __dirname, '../config/jest.config.js' ); + +// Look for a Jest config in the dependent app's path. +if ( appPath ) { + const appConfig = path.resolve( appPath, 'tests/e2e/config/jest.config.js' ); + + if ( fs.existsSync( appConfig ) ) { + configPath = appConfig; + } +} + +jestArgs.push( '--config=' + configPath ); + +const jestProcess = spawnSync( + jestCommand, + jestArgs, + { + stdio: 'inherit', + env: envVars, + } +); + +console.log( 'Jest exit code: ' + jestProcess.status ); + +// Pass Jest exit code to npm +process.exit( jestProcess.status ); diff --git a/tests/e2e/env/bin/install-wp-tests.sh b/tests/e2e/env/bin/install-wp-tests.sh new file mode 100755 index 00000000000..d6f3b95d898 --- /dev/null +++ b/tests/e2e/env/bin/install-wp-tests.sh @@ -0,0 +1,179 @@ +#!/usr/bin/env bash + +if [ $# -lt 3 ]; then + echo "usage: $0 [db-host] [wp-version] [skip-database-creation]" + exit 1 +fi + +DB_NAME=$1 +DB_USER=$2 +# Trim whitespace to work around an issue supplying an empty string through both `npm explore` and `npm run`. +DB_PASS=${3//[[:blank:]]/} +DB_HOST=${4-localhost} +WP_VERSION=${5-latest} +SKIP_DB_CREATE=${6-false} + +# directories +TMPDIR=${TMPDIR-/tmp} +TMPDIR=$(echo $TMPDIR | sed -e "s/\/$//") +WP_TESTS_DIR=${WP_TESTS_DIR-$TMPDIR/wordpress-tests-lib} +WP_CORE_DIR=${WP_CORE_DIR-$TMPDIR/wordpress/} + +download() { + if [ `which curl` ]; then + curl -s "$1" > "$2"; + elif [ `which wget` ]; then + wget -nv -O "$2" "$1" + fi +} + +if [[ $WP_VERSION =~ ^[0-9]+\.[0-9]+$ ]]; then + WP_TESTS_TAG="branches/$WP_VERSION" +elif [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0-9]+ ]]; then + if [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0] ]]; then + # version x.x.0 means the first release of the major version, so strip off the .0 and download version x.x + WP_TESTS_TAG="tags/${WP_VERSION%??}" + else + WP_TESTS_TAG="tags/$WP_VERSION" + fi +elif [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then + WP_TESTS_TAG="trunk" +else + # http serves a single offer, whereas https serves multiple. we only want one + download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json + grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json + LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//') + if [[ -z "$LATEST_VERSION" ]]; then + echo "Latest WordPress version could not be found" + exit 1 + fi + WP_TESTS_TAG="tags/$LATEST_VERSION" +fi + +set -ex + +install_wp() { + + if [ -d $WP_CORE_DIR ]; then + return; + fi + + mkdir -p $WP_CORE_DIR + + if [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then + mkdir -p $TMPDIR/wordpress-nightly + download https://wordpress.org/nightly-builds/wordpress-latest.zip $TMPDIR/wordpress-nightly/wordpress-nightly.zip + unzip -q $TMPDIR/wordpress-nightly/wordpress-nightly.zip -d $TMPDIR/wordpress-nightly/ + mv $TMPDIR/wordpress-nightly/wordpress/* $WP_CORE_DIR + else + if [ $WP_VERSION == 'latest' ]; then + local ARCHIVE_NAME='latest' + elif [[ $WP_VERSION =~ [0-9]+\.[0-9]+ ]]; then + # https serves multiple offers, whereas http serves single. + download https://api.wordpress.org/core/version-check/1.7/ $TMPDIR/wp-latest.json + if [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0] ]]; then + # version x.x.0 means the first release of the major version, so strip off the .0 and download version x.x + LATEST_VERSION=${WP_VERSION%??} + else + # otherwise, scan the releases and get the most up to date minor version of the major release + local VERSION_ESCAPED=`echo $WP_VERSION | sed 's/\./\\\\./g'` + LATEST_VERSION=$(grep -o '"version":"'$VERSION_ESCAPED'[^"]*' $TMPDIR/wp-latest.json | sed 's/"version":"//' | head -1) + fi + if [[ -z "$LATEST_VERSION" ]]; then + local ARCHIVE_NAME="wordpress-$WP_VERSION" + else + local ARCHIVE_NAME="wordpress-$LATEST_VERSION" + fi + else + local ARCHIVE_NAME="wordpress-$WP_VERSION" + fi + download https://wordpress.org/${ARCHIVE_NAME}.tar.gz $TMPDIR/wordpress.tar.gz + tar --strip-components=1 -zxmf $TMPDIR/wordpress.tar.gz -C $WP_CORE_DIR + fi + + download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php +} + +install_test_suite() { + # portable in-place argument for both GNU sed and Mac OSX sed + if [[ $(uname -s) == 'Darwin' ]]; then + local ioption='-i .bak' + else + local ioption='-i' + fi + + # set up testing suite if it doesn't yet exist + if [ ! -d $WP_TESTS_DIR ]; then + # set up testing suite + mkdir -p $WP_TESTS_DIR + svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes + svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/data/ $WP_TESTS_DIR/data + fi + + if [ ! -f wp-tests-config.php ]; then + download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php + # remove all forward slashes in the end + WP_CORE_DIR=$(echo $WP_CORE_DIR | sed "s:/\+$::") + sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR/':" "$WP_TESTS_DIR"/wp-tests-config.php + sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php + sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php + sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php + sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php + fi + +} + +install_db() { + + if [ ${SKIP_DB_CREATE} = "true" ]; then + return 0 + fi + + # parse DB_HOST for port or socket references + local PARTS=(${DB_HOST//\:/ }) + local DB_HOSTNAME=${PARTS[0]}; + local DB_SOCK_OR_PORT=${PARTS[1]}; + local EXTRA="" + + if ! [ -z $DB_HOSTNAME ] ; then + if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then + EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp" + elif ! [ -z $DB_SOCK_OR_PORT ] ; then + EXTRA=" --socket=$DB_SOCK_OR_PORT" + elif ! [ -z $DB_HOSTNAME ] ; then + EXTRA=" --host=$DB_HOSTNAME --protocol=tcp" + fi + fi + + # create database + mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA +} + +install_deps() { + + # Script Variables + BRANCH=$TRAVIS_BRANCH + REPO=$TRAVIS_REPO_SLUG + WORKING_DIR="$PWD" + + if [ "$TRAVIS_PULL_REQUEST_BRANCH" != "" ]; then + BRANCH=$TRAVIS_PULL_REQUEST_BRANCH + REPO=$TRAVIS_PULL_REQUEST_SLUG + fi + + # checkout dev version of woocommerce + cd "$WP_CORE_DIR/wp-content/plugins" + git clone --depth 1 "https://github.com/woocommerce/woocommerce.git" + # install dependencies + cd woocommerce + npm install + composer install --no-dev + + # Back to original dir + cd "$WORKING_DIR" +} + +install_wp +install_test_suite +install_db +install_deps diff --git a/tests/bin/run-e2e-CI.sh b/tests/e2e/env/bin/wait-for-build.sh similarity index 82% rename from tests/bin/run-e2e-CI.sh rename to tests/e2e/env/bin/wait-for-build.sh index e2ae6ec9cf2..75c8fbfadd5 100755 --- a/tests/bin/run-e2e-CI.sh +++ b/tests/e2e/env/bin/wait-for-build.sh @@ -9,7 +9,7 @@ DELAY_SEC=10 # Counter for the loop that checks if the Docker container had been built count=0 -while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8084/?page_id=4)" != "200" ]] +while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8084/?pagename=ready)" != "200" ]] do echo "$(date) - Docker container is still being built" @@ -23,6 +23,6 @@ do fi done -echo "$(date) - Docker container had been built successfully" - -npm run test:e2e +if [[ $count -gt 0 ]]; then + echo "$(date) - Docker container had been built successfully" +fi diff --git a/tests/e2e-tests/config/default.json b/tests/e2e/env/config/default.json similarity index 96% rename from tests/e2e-tests/config/default.json rename to tests/e2e/env/config/default.json index 13c4c230c8c..19693eece88 100644 --- a/tests/e2e-tests/config/default.json +++ b/tests/e2e/env/config/default.json @@ -27,7 +27,7 @@ "country": "United States (US)", "addressfirstline": "addr 1", "addresssecondline": "addr 2", - "countryandstate": "United States (US) -- California", + "countryandstate": "United States (US) — California", "city": "San Francisco", "state": "CA", "postcode": "94107" diff --git a/tests/e2e/env/config/env.setup.js b/tests/e2e/env/config/env.setup.js new file mode 100644 index 00000000000..6647b49d176 --- /dev/null +++ b/tests/e2e/env/config/env.setup.js @@ -0,0 +1,5 @@ +global.process.env = { + ...global.process.env, + // Gutenberg test util functions expect the test url to be at :8889, we change it to 8084. + WP_BASE_URL: 'http://localhost:8084', +}; diff --git a/tests/e2e-tests/config/jest-custom-sequencer.js b/tests/e2e/env/config/jest-custom-sequencer.js similarity index 54% rename from tests/e2e-tests/config/jest-custom-sequencer.js rename to tests/e2e/env/config/jest-custom-sequencer.js index 1b60c5f6ec3..0f9663f79b7 100644 --- a/tests/e2e-tests/config/jest-custom-sequencer.js +++ b/tests/e2e/env/config/jest-custom-sequencer.js @@ -1,11 +1,13 @@ -const Sequencer = require('@jest/test-sequencer').default; +const Sequencer = require( '@jest/test-sequencer' ).default; class CustomSequencer extends Sequencer { - sort(tests) { + sort( tests ) { // Test structure information // https://github.com/facebook/jest/blob/6b8b1404a1d9254e7d5d90a8934087a9c9899dab/packages/jest-runner/src/types.ts#L17-L21 - const copyTests = Array.from(tests); - return copyTests.sort((testA, testB) => (testA.path > testB.path ? 1 : -1)); + const copyTests = Array.from( tests ); + return copyTests.sort( ( testA, testB ) => + testA.path > testB.path ? 1 : -1 + ); } } diff --git a/tests/e2e/env/config/jest-puppeteer.config.js b/tests/e2e/env/config/jest-puppeteer.config.js new file mode 100644 index 00000000000..70fc3258a49 --- /dev/null +++ b/tests/e2e/env/config/jest-puppeteer.config.js @@ -0,0 +1,30 @@ +/** @format */ + +let puppeteerConfig; + +if ( 'no' == global.process.env.node_config_dev ) { + puppeteerConfig = { + launch: { + // Required for the logged out and logged in tests so they don't share app state/token. + browserContext: 'incognito', + }, + }; +} else { + puppeteerConfig = { + launch: { + slowMo: process.env.PUPPETEER_SLOWMO ? false : 50, + headless: process.env.PUPPETEER_HEADLESS || false, + ignoreHTTPSErrors: true, + args: [ '--window-size=1920,1080', '--user-agent=chrome' ], + devtools: true, + defaultViewport: { + width: 1280, + height: 800, + }, + // Required for the logged out and logged in tests so they don't share app state/token. + browserContext: 'incognito', + }, + }; +} + +module.exports = puppeteerConfig; diff --git a/tests/e2e/env/config/jest.config.js b/tests/e2e/env/config/jest.config.js new file mode 100644 index 00000000000..5afde75be93 --- /dev/null +++ b/tests/e2e/env/config/jest.config.js @@ -0,0 +1,31 @@ +module.exports = { + // Automatically clear mock calls and instances between every test + clearMocks: true, + + // An array of file extensions your modules use + moduleFileExtensions: [ 'js' ], + + moduleNameMapper: { + '@woocommerce/e2e-tests/(.*)': + '/tests/e2e/$1', + }, + + preset: 'jest-puppeteer', + + setupFiles: [ '/config/env.setup.js' ], + // A list of paths to modules that run some code to configure or set up the testing framework + // before each test + setupFilesAfterEnv: [ + '/build/setup/jest.setup.js', + 'expect-puppeteer', + ], + + // The glob patterns Jest uses to detect test files + testMatch: [ '**/*.(test|spec).js' ], + // Sort test path alphabetically. This is needed so that `activate-and-setup` tests run first + testSequencer: '/config/jest-custom-sequencer.js', + // Set the test timeout in milliseconds. + testTimeout: parseInt( global.process.env.jest_test_timeout ), + + transformIgnorePatterns: [ 'node_modules/(?!(woocommerce)/)' ], +}; diff --git a/tests/e2e/env/config/test-e2e.json b/tests/e2e/env/config/test-e2e.json new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/tests/e2e/env/config/test-e2e.json @@ -0,0 +1 @@ +{} diff --git a/tests/e2e/env/docker-compose.yaml b/tests/e2e/env/docker-compose.yaml new file mode 100644 index 00000000000..3cb8afb1e07 --- /dev/null +++ b/tests/e2e/env/docker-compose.yaml @@ -0,0 +1,59 @@ +version: '3.3' + +services: + + db: + container_name: "${APP_NAME}_db" + image: mariadb:10.4 + restart: on-failure + environment: + MYSQL_DATABASE: testdb + MYSQL_USER: wordpress + MYSQL_PASSWORD: wordpress + MYSQL_RANDOM_ROOT_PASSWORD: 'yes' + volumes: + - db:/var/lib/mysql + + wordpress-www: + container_name: "${APP_NAME}_wordpress-www" + depends_on: + - db + build: + context: ./docker/wordpress + ports: + - ${WORDPRESS_PORT}:80 + restart: on-failure + environment: + WORDPRESS_DB_HOST: ${WORDPRESS_DB_HOST} + WORDPRESS_DB_NAME: ${WORDPRESS_DB_NAME} + WORDPRESS_DB_USER: ${WORDPRESS_DB_USER} + WORDPRESS_DB_PASSWORD: ${WORDPRESS_DB_PASSWORD} + WORDPRESS_TABLE_PREFIX: "${WORDPRESS_TABLE_PREFIX}" + WORDPRESS_DEBUG: 1 + volumes: + - wordpress:/var/www/html + + wordpress-cli: + container_name: "${APP_NAME}_wordpress-cli" + depends_on: + - db + - wordpress-www + build: + context: ./docker/wp-cli + restart: on-failure +# user: xfs + environment: + WORDPRESS_PORT: ${WORDPRESS_PORT} + WORDPRESS_HOST: wordpress-www:80 + WORDPRESS_TITLE: ${WORDPRESS_TITLE} + WORDPRESS_LOGIN: ${WORDPRESS_LOGIN} + WORDPRESS_PASSWORD: ${WORDPRESS_PASSWORD} + WORDPRESS_EMAIL: "${WORDPRESS_EMAIL}" + DOMAIN_NAME: + + volumes: + - wordpress:/var/www/html + +volumes: + db: + wordpress: diff --git a/tests/e2e/env/docker/wordpress/Dockerfile b/tests/e2e/env/docker/wordpress/Dockerfile new file mode 100644 index 00000000000..8d927f52ee7 --- /dev/null +++ b/tests/e2e/env/docker/wordpress/Dockerfile @@ -0,0 +1 @@ +FROM wordpress:5.4 diff --git a/tests/e2e/env/docker/wp-cli/Dockerfile b/tests/e2e/env/docker/wp-cli/Dockerfile new file mode 100644 index 00000000000..9087e2d6b4f --- /dev/null +++ b/tests/e2e/env/docker/wp-cli/Dockerfile @@ -0,0 +1,22 @@ +FROM wordpress:cli-php7.4 + +USER root + +COPY wait-for-it.sh /usr/local/bin/wait-for-it +RUN chown xfs:xfs /usr/local/bin/wait-for-it && \ + chmod +x /usr/local/bin/wait-for-it + +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chown xfs:xfs /usr/local/bin/entrypoint.sh && \ + chmod +x /usr/local/bin/entrypoint.sh + +RUN chown xfs:xfs /home/www-data + +COPY initialize.sh /usr/local/bin/initialize.sh +RUN chown xfs:xfs /usr/local/bin/initialize.sh && \ + chmod +x /usr/local/bin/initialize.sh + +USER xfs +RUN mkdir /home/www-data/.wp-cli && echo "path: /var/www/html" > /home/www-data/.wp-cli/config.yml +USER root +ENTRYPOINT ["entrypoint.sh"] diff --git a/tests/e2e/env/docker/wp-cli/entrypoint.sh b/tests/e2e/env/docker/wp-cli/entrypoint.sh new file mode 100644 index 00000000000..80333975ac1 --- /dev/null +++ b/tests/e2e/env/docker/wp-cli/entrypoint.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +set -eu + +declare -p WORDPRESS_HOST +wait-for-it ${WORDPRESS_HOST} -t 120 + +## if file exists then exit early because initialization already happened. +if [ -f /var/www/html/.initialized ]; +then + echo "The environment has already been initialized." + exit 0 +fi + +chown xfs:xfs /var/www/html/wp-content +chown xfs:xfs /var/www/html/wp-content/plugins + +## switch user +if [ $UID -eq 0 ]; then + user=xfs + dir=/var/www/html + cd "$dir" + exec su -s /bin/bash "$user" "$0" -- "$@" + # nothing will be executed beyond that line, + # because exec replaces running process with the new one +fi + +declare -p WORDPRESS_PORT +[[ "${WORDPRESS_PORT}" == 80 ]] && \ +URL="http://localhost" || \ +URL="http://localhost:${WORDPRESS_PORT}" + +if $(wp core is-installed); +then + echo "Wordpress is already installed..." +else + WORDPRESS_INSTALLING=1 + declare -p WORDPRESS_TITLE >/dev/null + declare -p WORDPRESS_LOGIN >/dev/null + declare -p WORDPRESS_PASSWORD >/dev/null + declare -p WORDPRESS_EMAIL >/dev/null + echo "Installing wordpress..." + wp core install \ + --url=${URL} \ + --title="$WORDPRESS_TITLE" \ + --admin_user=${WORDPRESS_LOGIN} \ + --admin_password=${WORDPRESS_PASSWORD} \ + --admin_email=${WORDPRESS_EMAIL} \ + --skip-email +fi + +## Check for an initialization script. +declare -r INIT_SCRIPT=$(command -v initialize.sh) + +if [[ -x ${INIT_SCRIPT} ]]; then + . "$INIT_SCRIPT" +fi + +declare -r CURRENT_DOMAIN=$(wp option get siteurl) + +if ! [[ ${CURRENT_DOMAIN} == ${URL} ]]; then + echo "Replacing ${CURRENT_DOMAIN} with ${URL} in database..." + wp search-replace ${CURRENT_DOMAIN} ${URL} +fi + +if [[ $WORDPRESS_INSTALLING ]]; +then + wp post create \ + --post_type=page \ + --post_status=publish \ + --post_title='Ready' \ + --post_content='E2E-tests.' +fi + +echo "Visit $(wp option get siteurl)" +touch /var/www/html/.initialized diff --git a/tests/e2e/env/docker/wp-cli/wait-for-it.sh b/tests/e2e/env/docker/wp-cli/wait-for-it.sh new file mode 100644 index 00000000000..61e9858419c --- /dev/null +++ b/tests/e2e/env/docker/wp-cli/wait-for-it.sh @@ -0,0 +1,208 @@ +#!/usr/bin/env bash +#source https://github.com/vishnubob/wait-for-it/pull/81 +#The MIT License (MIT) +# +#Original work Copyright (c) 2016 Giles Hall: wait-for-it.sh +#Modified work Copyright (c) 2019 iturgeon: wait-for-it.sh +# +#Permission is hereby granted, free of charge, to any person obtaining a copy of +#this software and associated documentation files (the "Software"), to deal in +#the Software without restriction, including without limitation the rights to +#use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +#of the Software, and to permit persons to whom the Software is furnished to do +#so, subject to the following conditions: +# +#The above copyright notice and this permission notice shall be included in all +#copies or substantial portions of the Software. +# +#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +#SOFTWARE. + +# Use this script to test if a given TCP host/port are available + +WAITFORIT_cmdname=${0##*/} + +echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } + +usage() +{ + cat << USAGE >&2 +Usage: + $WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args] + -h HOST | --host=HOST Host or IP under test + -p PORT | --port=PORT TCP port under test + Alternatively, you specify the host and port as host:port + -s | --strict Only execute subcommand if the test succeeds + -q | --quiet Don't output any status messages + -t TIMEOUT | --timeout=TIMEOUT + Timeout in seconds, zero for no timeout + -- COMMAND ARGS Execute command with args after the test finishes +USAGE + exit 1 +} + +wait_for() +{ + if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then + echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" + else + echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout" + fi + WAITFORIT_start_ts=$(date +%s) + while : + do + if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then + nc -z $WAITFORIT_HOST $WAITFORIT_PORT + WAITFORIT_result=$? + else + (echo > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1 + WAITFORIT_result=$? + fi + if [[ $WAITFORIT_result -eq 0 ]]; then + WAITFORIT_end_ts=$(date +%s) + echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds" + break + fi + sleep 1 + done + return $WAITFORIT_result +} + +wait_for_wrapper() +{ + # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 + if [[ $WAITFORIT_QUIET -eq 1 ]]; then + timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & + else + timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & + fi + WAITFORIT_PID=$! + trap "kill -INT -$WAITFORIT_PID" INT + wait $WAITFORIT_PID + WAITFORIT_RESULT=$? + if [[ $WAITFORIT_RESULT -ne 0 ]]; then + echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" + fi + return $WAITFORIT_RESULT +} + +# process arguments +while [[ $# -gt 0 ]] +do + case "$1" in + *:* ) + WAITFORIT_hostport=(${1//:/ }) + WAITFORIT_HOST=${WAITFORIT_hostport[0]} + WAITFORIT_PORT=${WAITFORIT_hostport[1]} + shift 1 + ;; + --child) + WAITFORIT_CHILD=1 + shift 1 + ;; + -q | --quiet) + WAITFORIT_QUIET=1 + shift 1 + ;; + -s | --strict) + WAITFORIT_STRICT=1 + shift 1 + ;; + -h) + WAITFORIT_HOST="$2" + if [[ $WAITFORIT_HOST == "" ]]; then break; fi + shift 2 + ;; + --host=*) + WAITFORIT_HOST="${1#*=}" + shift 1 + ;; + -p) + WAITFORIT_PORT="$2" + if [[ $WAITFORIT_PORT == "" ]]; then break; fi + shift 2 + ;; + --port=*) + WAITFORIT_PORT="${1#*=}" + shift 1 + ;; + -t) + WAITFORIT_TIMEOUT="$2" + if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi + shift 2 + ;; + --timeout=*) + WAITFORIT_TIMEOUT="${1#*=}" + shift 1 + ;; + --) + shift + WAITFORIT_CLI=("$@") + break + ;; + --help) + usage + ;; + *) + echoerr "Unknown argument: $1" + usage + ;; + esac +done + +if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then + echoerr "Error: you need to provide a host and port to test." + usage +fi + +WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15} +WAITFORIT_STRICT=${WAITFORIT_STRICT:-0} +WAITFORIT_CHILD=${WAITFORIT_CHILD:-0} +WAITFORIT_QUIET=${WAITFORIT_QUIET:-0} +WAITFORIT_ISBUSY=0 +WAITFORIT_BUSYTIMEFLAG="" +WAITFORIT_TIMEOUT_PATH=$(type -p timeout) +WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH) + +# check to see if we're using busybox? +if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then + WAITFORIT_ISBUSY=1 +fi + +# see if timeout.c args have been updated in busybox v1.30.0 or newer +# note: this requires the use of bash on Alpine +if [[ $WAITFORIT_ISBUSY && $(busybox | head -1) =~ ^.*v([[:digit:]]+)\.([[:digit:]]+)\..+$ ]]; then + if [[ ${BASH_REMATCH[1]} -le 1 && ${BASH_REMATCH[2]} -lt 30 ]]; then + # using pre 1.30.0 version with `-t SEC` arg + WAITFORIT_BUSYTIMEFLAG="-t" + fi +fi + +if [[ $WAITFORIT_CHILD -gt 0 ]]; then + wait_for + WAITFORIT_RESULT=$? + exit $WAITFORIT_RESULT +else + if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then + wait_for_wrapper + WAITFORIT_RESULT=$? + else + wait_for + WAITFORIT_RESULT=$? + fi +fi + +if [[ $WAITFORIT_CLI != "" ]]; then + if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then + echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess" + exit $WAITFORIT_RESULT + fi + exec "${WAITFORIT_CLI[@]}" +else + exit $WAITFORIT_RESULT +fi diff --git a/tests/e2e/env/index.js b/tests/e2e/env/index.js new file mode 100644 index 00000000000..86ae8e23bc4 --- /dev/null +++ b/tests/e2e/env/index.js @@ -0,0 +1,12 @@ +// Internal dependencies +const babelConfig = require( './babel.config' ); +const esLintConfig = require( './.eslintrc.js' ); +const jestConfig = require( './config/jest.config.js' ); +const webpackAlias = require( './webpack-alias' ); + +module.exports = { + babelConfig, + esLintConfig, + jestConfig, + webpackAlias, +}; diff --git a/tests/e2e/env/package.json b/tests/e2e/env/package.json new file mode 100644 index 00000000000..f23629feff1 --- /dev/null +++ b/tests/e2e/env/package.json @@ -0,0 +1,52 @@ +{ + "name": "@woocommerce/e2e-environment", + "version": "0.1.5", + "description": "WooCommerce End to End Testing Environment Configuration.", + "author": "Automattic", + "license": "GPL-3.0-or-later", + "keywords": [ + "wordpress", + "woocommerce", + "e2e", + "puppeteer" + ], + "homepage": "https://github.com/woocommerce/woocommerce/tree/master/tests/e2e/env/README.md", + "repository": { + "type": "git", + "url": "https://github.com/woocommerce/woocommerce.git" + }, + "bugs": { + "url": "https://github.com/woocommerce/woocommerce/issues" + }, + "main": "index.js", + "module": "build-module/index.js", + "dependencies": { + "@wordpress/e2e-test-utils": "^4.6.0", + "@wordpress/jest-preset-default": "^5.4.0", + "app-root-path": "^3.0.0", + "jest": "^25.1.0", + "jest-puppeteer": "^4.4.0", + "puppeteer": "^2.1.1" + }, + "devDependencies": { + "@babel/cli": "^7.8.4", + "@babel/core": "^7.8.4", + "@babel/polyfill": "^7.8.3", + "@babel/preset-env": "^7.8.4", + "@wordpress/eslint-plugin": "^4.0.0", + "ndb": "^1.1.5", + "woocommerce": "git+https://github.com/woocommerce/woocommerce.git" + }, + "publishConfig": { + "access": "public" + }, + "scripts": { + "docker:up": "./bin/docker-compose.js up", + "docker:down": "./bin/docker-compose.js down", + "docker:clear-all": "docker rmi --force $(docker images -q)", + "docker:ssh": "docker exec -it woocommerce_wordpress-www /bin/bash", + "install-wp-tests": "./bin/install-wp-tests.sh", + "test:e2e": "bash ./bin/wait-for-build.sh && ./bin/e2e-test-integration.js", + "test:e2e-dev": "bash ./bin/wait-for-build.sh && ./bin/e2e-test-integration.js --dev" + } +} diff --git a/tests/e2e/env/src/setup/jest.setup.js b/tests/e2e/env/src/setup/jest.setup.js new file mode 100644 index 00000000000..b9633cb9995 --- /dev/null +++ b/tests/e2e/env/src/setup/jest.setup.js @@ -0,0 +1,256 @@ +/** + * External dependencies + */ +import { get } from 'lodash'; +import { + clearLocalStorage, + enablePageDialogAccept, + isOfflineMode, + setBrowserViewport, + switchUserToAdmin, + switchUserToTest, + visitAdminPage, +} from '@wordpress/e2e-test-utils'; + +/** + * Array of page event tuples of [ eventName, handler ]. + * + * @type {Array} + */ +const pageEvents = []; +/** + * Set of console logging types observed to protect against unexpected yet + * handled (i.e. not catastrophic) errors or warnings. Each key corresponds + * to the Puppeteer ConsoleMessage type, its value the corresponding function + * on the console global object. + * + * @type {Object} + */ +const OBSERVED_CONSOLE_MESSAGE_TYPES = { + warning: 'warn', + error: 'error', +}; + +async function setupBrowser() { + await clearLocalStorage(); + await setBrowserViewport( 'large' ); +} + +/** + * Navigates to the post listing screen and bulk-trashes any posts which exist. + * + * @return {Promise} Promise resolving once posts have been trashed. + */ +async function trashExistingPosts() { + await switchUserToAdmin(); + // Visit `/wp-admin/edit.php` so we can see a list of posts and delete them. + await visitAdminPage( 'edit.php' ); + + // If this selector doesn't exist there are no posts for us to delete. + const bulkSelector = await page.$( '#bulk-action-selector-top' ); + if ( ! bulkSelector ) { + return; + } + + // Select all posts. + await page.waitForSelector( '#cb-select-all-1' ); + await page.click( '#cb-select-all-1' ); + // Select the "bulk actions" > "trash" option. + await page.select( '#bulk-action-selector-top', 'trash' ); + // Submit the form to send all draft/scheduled/published posts to the trash. + await page.click( '#doaction' ); + await page.waitForXPath( + '//*[contains(@class, "updated notice")]/p[contains(text(), "moved to the Trash.")]' + ); + await switchUserToTest(); +} + +/** + * Navigates to the product listing screen and bulk-trashes any product which exist. + * + * @return {Promise} Promise resolving once products have been trashed. + */ +async function trashExistingProducts() { + await switchUserToAdmin(); + // Visit `/wp-admin/edit.php?post_type=product` so we can see a list of products and delete them. + await visitAdminPage( 'edit.php', 'post_type=product' ); + + // If this selector doesn't exist there are no products for us to delete. + const bulkSelector = await page.$( '#bulk-action-selector-top' ); + if ( ! bulkSelector ) { + return; + } + + // Select all products. + await page.waitForSelector( '#cb-select-all-1' ); + await page.click( '#cb-select-all-1' ); + // Select the "bulk actions" > "trash" option. + await page.select( '#bulk-action-selector-top', 'trash' ); + // Submit the form to send all draft/scheduled/published posts to the trash. + await page.click( '#doaction' ); + await page.waitForXPath( + '//*[contains(@class, "updated notice")]/p[contains(text(), "moved to the Trash.")]' + ); + await switchUserToTest(); +} + +/** + * Navigates to woocommerce import page and imports sample products. + * + * @return {Promise} Promise resolving once products have been imported. + */ +async function importSampleProducts() { + await switchUserToAdmin(); + // Visit Import Products page. + await visitAdminPage( + 'edit.php', + 'post_type=product&page=product_importer' + ); + await page.click( 'a.woocommerce-importer-toggle-advanced-options' ); + await page.focus( '#woocommerce-importer-file-url' ); + // local path for sample data that is included with woo. + await page.keyboard.type( + 'wp-content/plugins/woocommerce/sample-data/sample_products.csv' + ); + await page.click( '.wc-actions .button-next' ); + await page.waitForSelector( '.wc-importer-mapping-table' ); + await page.select( + '.wc-importer-mapping-table tr:nth-child(29) select', + '' + ); + await page.click( '.wc-actions .button-next' ); + await page.waitForXPath( + "//*[@class='woocommerce-importer-done' and contains(., 'Import complete! ')]" + ); + await switchUserToTest(); +} + +/** + * Adds an event listener to the page to handle additions of page event + * handlers, to assure that they are removed at test teardown. + */ +function capturePageEventsForTearDown() { + page.on( 'newListener', ( eventName, listener ) => { + pageEvents.push( [ eventName, listener ] ); + } ); +} + +/** + * Removes all bound page event handlers. + */ +function removePageEvents() { + pageEvents.forEach( ( [ eventName, handler ] ) => { + page.removeListener( eventName, handler ); + } ); +} + +/** + * Adds a page event handler to emit uncaught exception to process if one of + * the observed console logging types is encountered. + */ +function observeConsoleLogging() { + page.on( 'console', ( message ) => { + const type = message.type(); + if ( ! OBSERVED_CONSOLE_MESSAGE_TYPES.hasOwnProperty( type ) ) { + return; + } + + let text = message.text(); + + // An exception is made for _blanket_ deprecation warnings: Those + // which log regardless of whether a deprecated feature is in use. + if ( text.includes( 'This is a global warning' ) ) { + return; + } + + // A chrome advisory warning about SameSite cookies is informational + // about future changes, tracked separately for improvement in core. + // + // See: https://core.trac.wordpress.org/ticket/37000 + // See: https://www.chromestatus.com/feature/5088147346030592 + // See: https://www.chromestatus.com/feature/5633521622188032 + if ( + text.includes( 'A cookie associated with a cross-site resource' ) + ) { + return; + } + + // Viewing posts on the front end can result in this error, which + // has nothing to do with Gutenberg. + if ( text.includes( 'net::ERR_UNKNOWN_URL_SCHEME' ) ) { + return; + } + + // Network errors are ignored only if we are intentionally testing + // offline mode. + if ( + text.includes( 'net::ERR_INTERNET_DISCONNECTED' ) && + isOfflineMode() + ) { + return; + } + + // As of WordPress 5.3.2 in Chrome 79, navigating to the block editor + // (Posts > Add New) will display a console warning about + // non - unique IDs. + // See: https://core.trac.wordpress.org/ticket/23165 + if ( text.includes( 'elements with non-unique id #_wpnonce' ) ) { + return; + } + + // As of WordPress 5.3.2 in Chrome 79, navigating to the block editor + // (Posts > Add New) will display a console warning about + // non - unique IDs. + // See: https://core.trac.wordpress.org/ticket/23165 + if ( text.includes( 'elements with non-unique id #_wpnonce' ) ) { + return; + } + + const logFunction = OBSERVED_CONSOLE_MESSAGE_TYPES[ type ]; + + // As of Puppeteer 1.6.1, `message.text()` wrongly returns an object of + // type JSHandle for error logging, instead of the expected string. + // + // See: https://github.com/GoogleChrome/puppeteer/issues/3397 + // + // The recommendation there to asynchronously resolve the error value + // upon a console event may be prone to a race condition with the test + // completion, leaving a possibility of an error not being surfaced + // correctly. Instead, the logic here synchronously inspects the + // internal object shape of the JSHandle to find the error text. If it + // cannot be found, the default text value is used instead. + text = get( + message.args(), + [ 0, '_remoteObject', 'description' ], + text + ); + + // Disable reason: We intentionally bubble up the console message + // which, unless the test explicitly anticipates the logging via + // @wordpress/jest-console matchers, will cause the intended test + // failure. + + // eslint-disable-next-line no-console + console[ logFunction ]( text ); + } ); +} + +// Before every test suite run, delete all content created by the test. This ensures +// other posts/comments/etc. aren't dirtying tests and tests don't depend on +// each other's side-effects. +beforeAll( async () => { + capturePageEventsForTearDown(); + enablePageDialogAccept(); + observeConsoleLogging(); + await trashExistingPosts(); + await trashExistingProducts(); + await setupBrowser(); +} ); + +afterEach( async () => { + await setupBrowser(); +} ); + +afterAll( () => { + removePageEvents(); +} ); diff --git a/tests/e2e/env/utils/app-root.js b/tests/e2e/env/utils/app-root.js new file mode 100644 index 00000000000..2e8b9e24506 --- /dev/null +++ b/tests/e2e/env/utils/app-root.js @@ -0,0 +1,19 @@ +const path = require( 'path' ); + +const getAppRoot = () => { + // Figure out where we're installed. + // Typically will be in node_modules/, but WooCommerce + // uses a local file path (tests/e2e/env). + let appPath = false; + const moduleDir = path.dirname( require.resolve( '@woocommerce/e2e-environment' ) ); + + if ( -1 < moduleDir.indexOf( 'node_modules' ) ) { + appPath = moduleDir.split( 'node_modules' )[ 0 ]; + } else if ( -1 < moduleDir.indexOf( 'tests/e2e/env' ) ) { + appPath = moduleDir.split( 'tests/e2e/env' )[ 0 ]; + } + + return appPath; +}; + +module.exports = getAppRoot; diff --git a/tests/e2e/env/utils/index.js b/tests/e2e/env/utils/index.js new file mode 100644 index 00000000000..85531094226 --- /dev/null +++ b/tests/e2e/env/utils/index.js @@ -0,0 +1,5 @@ +const getAppRoot = require( './app-root' ); + +module.exports = { + getAppRoot, +}; diff --git a/tests/e2e/env/webpack-alias.js b/tests/e2e/env/webpack-alias.js new file mode 100644 index 00000000000..3c9d404cc68 --- /dev/null +++ b/tests/e2e/env/webpack-alias.js @@ -0,0 +1,11 @@ +/** + * External dependencies + */ +const path = require( 'path' ); + +module.exports = { + '@woocommerce/e2e-tests': path.resolve( + __dirname, + 'node_modules/woocommerce/tests/e2e' + ), +}; diff --git a/tests/e2e-tests/specs/activate-and-setup/setup-wizard.test.js b/tests/e2e/specs/activate-and-setup/setup-wizard.test.js similarity index 84% rename from tests/e2e-tests/specs/activate-and-setup/setup-wizard.test.js rename to tests/e2e/specs/activate-and-setup/setup-wizard.test.js index c8770c7ba66..cb0a8205336 100644 --- a/tests/e2e-tests/specs/activate-and-setup/setup-wizard.test.js +++ b/tests/e2e/specs/activate-and-setup/setup-wizard.test.js @@ -6,20 +6,17 @@ * Internal dependencies */ import { StoreOwnerFlow } from '../../utils/flows'; -import { completeOldSetupWizard, completeOnboardingWizard } from '../../utils/components'; +import { completeOnboardingWizard } from '../../utils/components'; import { permalinkSettingsPageSaveChanges, setCheckbox, settingsPageSaveChanges, verifyCheckboxIsSet, - verifyCheckboxIsUnset, verifyValueOfInputField + verifyValueOfInputField } from '../../utils'; -const config = require( 'config' ); - describe( 'Store owner can login and make sure WooCommerce is activated', () => { - - it( 'can login', async () => { + beforeAll( async () => { await StoreOwnerFlow.login(); } ); @@ -56,25 +53,16 @@ describe( 'Store owner can go through setup Task List', () => { it( 'can setup shipping', async () => { // Query for all tasks on the list const taskListItems = await page.$$( '.woocommerce-list__item-title' ); - expect( taskListItems ).toHaveLength( 5 ); + expect( taskListItems ).toHaveLength( 6 ); await Promise.all( [ // Click on "Set up shipping" task to move to the next step - taskListItems[2].click(), + taskListItems[3].click(), // Wait for shipping setup section to load page.waitForNavigation( { waitUntil: 'networkidle0' } ), ] ); - // Query for store location fields - const storeLocationFields = await page.$$( '.components-text-control__input' ); - expect( storeLocationFields ).toHaveLength( 4 ); - - // Wait for "Continue" button to become active - await page.waitForSelector( 'button.is-primary:not(:disabled)' ); - // Click on "Continue" button to move to the shipping cost section - await page.click( 'button.is-primary' ); - // Wait for "Proceed" button to become active await page.waitForSelector( 'button.is-primary:not(:disabled)' ); await page.waitFor( 3000 ); diff --git a/tests/e2e-tests/specs/front-end/front-end-cart.test.js b/tests/e2e/specs/front-end/front-end-cart.test.js similarity index 100% rename from tests/e2e-tests/specs/front-end/front-end-cart.test.js rename to tests/e2e/specs/front-end/front-end-cart.test.js diff --git a/tests/e2e-tests/specs/front-end/front-end-checkout.test.js b/tests/e2e/specs/front-end/front-end-checkout.test.js similarity index 100% rename from tests/e2e-tests/specs/front-end/front-end-checkout.test.js rename to tests/e2e/specs/front-end/front-end-checkout.test.js diff --git a/tests/e2e-tests/specs/front-end/front-end-my-account.test.js b/tests/e2e/specs/front-end/front-end-my-account.test.js similarity index 100% rename from tests/e2e-tests/specs/front-end/front-end-my-account.test.js rename to tests/e2e/specs/front-end/front-end-my-account.test.js diff --git a/tests/e2e-tests/specs/front-end/front-end-single-product.test.js b/tests/e2e/specs/front-end/front-end-single-product.test.js similarity index 100% rename from tests/e2e-tests/specs/front-end/front-end-single-product.test.js rename to tests/e2e/specs/front-end/front-end-single-product.test.js diff --git a/tests/e2e-tests/specs/wp-admin/wp-admin-coupon-new.test.js b/tests/e2e/specs/wp-admin/wp-admin-coupon-new.test.js similarity index 100% rename from tests/e2e-tests/specs/wp-admin/wp-admin-coupon-new.test.js rename to tests/e2e/specs/wp-admin/wp-admin-coupon-new.test.js diff --git a/tests/e2e-tests/specs/wp-admin/wp-admin-order-new.test.js b/tests/e2e/specs/wp-admin/wp-admin-order-new.test.js similarity index 100% rename from tests/e2e-tests/specs/wp-admin/wp-admin-order-new.test.js rename to tests/e2e/specs/wp-admin/wp-admin-order-new.test.js diff --git a/tests/e2e-tests/specs/wp-admin/wp-admin-product-new.test.js b/tests/e2e/specs/wp-admin/wp-admin-product-new.test.js similarity index 100% rename from tests/e2e-tests/specs/wp-admin/wp-admin-product-new.test.js rename to tests/e2e/specs/wp-admin/wp-admin-product-new.test.js diff --git a/tests/e2e-tests/specs/wp-admin/wp-admin-settings-general.test.js b/tests/e2e/specs/wp-admin/wp-admin-settings-general.test.js similarity index 100% rename from tests/e2e-tests/specs/wp-admin/wp-admin-settings-general.test.js rename to tests/e2e/specs/wp-admin/wp-admin-settings-general.test.js diff --git a/tests/e2e-tests/specs/wp-admin/wp-admin-settings-product.test.js b/tests/e2e/specs/wp-admin/wp-admin-settings-product.test.js similarity index 100% rename from tests/e2e-tests/specs/wp-admin/wp-admin-settings-product.test.js rename to tests/e2e/specs/wp-admin/wp-admin-settings-product.test.js diff --git a/tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js b/tests/e2e/specs/wp-admin/wp-admin-settings-tax.test.js similarity index 100% rename from tests/e2e-tests/specs/wp-admin/wp-admin-settings-tax.test.js rename to tests/e2e/specs/wp-admin/wp-admin-settings-tax.test.js diff --git a/tests/e2e-tests/utils/components.js b/tests/e2e/utils/components.js similarity index 98% rename from tests/e2e-tests/utils/components.js rename to tests/e2e/utils/components.js index d4cd5ea07a4..37b0e99e080 100644 --- a/tests/e2e-tests/utils/components.js +++ b/tests/e2e/utils/components.js @@ -69,7 +69,7 @@ const completeOnboardingWizard = async () => { // Wait for usage tracking pop-up window to appear await page.waitForSelector( '.components-modal__header-heading' ); await expect( page ).toMatchElement( - '.components-modal__header-heading', { text: 'Build a Better WooCommerce' } + '.components-modal__header-heading', { text: 'Build a better WooCommerce' } ); // Query for "Continue" buttons @@ -121,11 +121,11 @@ const completeOnboardingWizard = async () => { } // Wait for "Continue" button to become active - await page.waitForSelector( 'button.woocommerce-profile-wizard__continue:not(:disabled)' ); + await page.waitForSelector( 'button.is-primary:not(:disabled)' ); await Promise.all( [ // Click on "Continue" button to move to the next step - page.click( 'button.woocommerce-profile-wizard__continue' ), + page.click( 'button.is-primary' ), // Wait for "Tell us about your business" section to load page.waitForNavigation( { waitUntil: 'networkidle0' } ), @@ -186,9 +186,9 @@ const completeOnboardingWizard = async () => { await page.waitForSelector( '.woocommerce-profile-wizard__header-title' ); // Wait for "No thanks" button to become active - await page.waitForSelector( 'button.is-default:not(:disabled)' ); + await page.waitForSelector( 'button.is-secondary:not(:disabled)' ); // Click on "No thanks" button to move to the next step - await page.click( 'button.is-default' ); + await page.click( 'button.is-secondary' ); // End of onboarding wizard diff --git a/tests/e2e-tests/utils/flows.js b/tests/e2e/utils/flows.js similarity index 97% rename from tests/e2e-tests/utils/flows.js rename to tests/e2e/utils/flows.js index 50ea2716937..cb72820abb3 100644 --- a/tests/e2e-tests/utils/flows.js +++ b/tests/e2e/utils/flows.js @@ -241,16 +241,15 @@ const StoreOwnerFlow = { }, logout: async () => { - await page.goto(baseUrl + 'wp-login.php?action=logout', { + // Log out link in admin bar is not visible so can't be clicked directly. + const logoutLinks = await page.$$eval( + '#wp-admin-bar-logout a', + ( am ) => am.filter( ( e ) => e.href ).map( ( e ) => e.href ) + ); + + await page.goto( logoutLinks[ 0 ], { waitUntil: 'networkidle0', - }); - - await expect(page).toMatch('You are attempting to log out'); - - await Promise.all([ - page.waitForNavigation({ waitUntil: 'networkidle0' }), - page.click('a'), - ]); + } ); }, openAllOrdersView: async () => { diff --git a/tests/e2e-tests/utils/index.js b/tests/e2e/utils/index.js similarity index 100% rename from tests/e2e-tests/utils/index.js rename to tests/e2e/utils/index.js diff --git a/tests/bootstrap.php b/tests/legacy/bootstrap.php similarity index 74% rename from tests/bootstrap.php rename to tests/legacy/bootstrap.php index 0567482dfd8..9a5513ccebc 100644 --- a/tests/bootstrap.php +++ b/tests/legacy/bootstrap.php @@ -6,6 +6,12 @@ * @package WooCommerce Tests */ +use Automattic\WooCommerce\Testing\Tools\CodeHacking\CodeHacker; +use Automattic\WooCommerce\Testing\Tools\CodeHacking\Hacks\StaticMockerHack; +use Automattic\WooCommerce\Testing\Tools\CodeHacking\Hacks\FunctionsMockerHack; +use Automattic\WooCommerce\Testing\Tools\CodeHacking\Hacks\BypassFinalsHack; +use Composer\Autoload\ClassLoader; + /** * Class WC_Unit_Tests_Bootstrap */ @@ -29,6 +35,8 @@ class WC_Unit_Tests_Bootstrap { * @since 2.2 */ public function __construct() { + $this->tests_dir = dirname( __FILE__ ); + $this->initialize_code_hacker(); ini_set( 'display_errors', 'on' ); // phpcs:ignore WordPress.PHP.IniSet.display_errors_Blacklisted error_reporting( E_ALL ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.prevent_path_disclosure_error_reporting, WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_error_reporting @@ -40,8 +48,6 @@ class WC_Unit_Tests_Bootstrap { } // phpcs:enable WordPress.VIP.SuperGlobalInputUsage.AccessDetected - $this->tests_dir = dirname( __FILE__ ); - $this->plugin_dir = dirname( $this->tests_dir ); $this->wp_tests_dir = getenv( 'WP_TESTS_DIR' ) ? getenv( 'WP_TESTS_DIR' ) : sys_get_temp_dir() . '/wordpress-tests-lib'; // load test function so tests_add_filter() is available. @@ -60,6 +66,39 @@ class WC_Unit_Tests_Bootstrap { $this->includes(); } + /** + * Initialize the code hacker. + * + * @throws Exception Error when initializing one of the hacks. + */ + private function initialize_code_hacker() { + $this->plugin_dir = dirname( dirname( $this->tests_dir ) ); + + $hacking_base = $this->plugin_dir . '/tests/Tools/CodeHacking'; + require_once $hacking_base . '/CodeHacker.php'; + require_once $hacking_base . '/Hacks/CodeHack.php'; + require_once $hacking_base . '/Hacks/StaticMockerHack.php'; + require_once $hacking_base . '/Hacks/FunctionsMockerHack.php'; + require_once $hacking_base . '/Hacks/BypassFinalsHack.php'; + + CodeHacker::initialize( array( __DIR__ . '/../../includes/' ) ); + $replaceable_functions = include_once __DIR__ . '/mockable-functions.php'; + if ( ! empty( $replaceable_functions ) ) { + FunctionsMockerHack::initialize( $replaceable_functions ); + CodeHacker::add_hack( FunctionsMockerHack::get_hack_instance() ); + } + + $mockable_static_classes = include_once __DIR__ . '/classes-with-mockable-static-methods.php'; + if ( ! empty( $mockable_static_classes ) ) { + StaticMockerHack::initialize( $mockable_static_classes ); + CodeHacker::add_hack( StaticMockerHack::get_hack_instance() ); + } + + CodeHacker::add_hack( new BypassFinalsHack() ); + + CodeHacker::enable(); + } + /** * Load WooCommerce. * diff --git a/tests/legacy/classes-with-mockable-static-methods.php b/tests/legacy/classes-with-mockable-static-methods.php new file mode 100644 index 00000000000..5c4deecedfb --- /dev/null +++ b/tests/legacy/classes-with-mockable-static-methods.php @@ -0,0 +1,12 @@ + 0 ) { + self::$code_hacker_temporary_disables_requested++; + } + } + + /** + * Decrease the count of Code Hacker disable requests, and effectively re-enable it if the count reaches zero. + * Does nothing if the count is already zero. + */ + protected static function reenable_code_hacker() { + if ( self::$code_hacker_temporary_disables_requested > 0 ) { + self::$code_hacker_temporary_disables_requested--; + if ( 0 === self::$code_hacker_temporary_disables_requested ) { + CodeHacker::enable(); + } + } + } + /** * Setup test case. * @@ -99,4 +132,22 @@ class WC_Unit_Test_Case extends WP_HTTP_TestCase { $message = $message ? $message : "We're all doomed!"; throw new Exception( $message, $code ); } + + + /** + * Copies a file, temporarily disabling the code hacker. + * Use this instead of "copy" in tests for compatibility with the code hacker. + * + * TODO: Investigate why invoking "copy" within a test with the code hacker active causes the test to fail. + * + * @param string $source Path to the source file. + * @param string $dest The destination path. + * @return bool true on success or false on failure. + */ + public static function file_copy( $source, $dest ) { + self::disable_code_hacker(); + $result = copy( $source, $dest ); + self::reenable_code_hacker(); + return $result; + } } diff --git a/tests/framework/class-wc-unit-test-factory.php b/tests/legacy/framework/class-wc-unit-test-factory.php similarity index 100% rename from tests/framework/class-wc-unit-test-factory.php rename to tests/legacy/framework/class-wc-unit-test-factory.php diff --git a/tests/framework/helpers/class-wc-helper-coupon.php b/tests/legacy/framework/helpers/class-wc-helper-coupon.php similarity index 100% rename from tests/framework/helpers/class-wc-helper-coupon.php rename to tests/legacy/framework/helpers/class-wc-helper-coupon.php diff --git a/tests/framework/helpers/class-wc-helper-customer.php b/tests/legacy/framework/helpers/class-wc-helper-customer.php similarity index 100% rename from tests/framework/helpers/class-wc-helper-customer.php rename to tests/legacy/framework/helpers/class-wc-helper-customer.php diff --git a/tests/framework/helpers/class-wc-helper-fee.php b/tests/legacy/framework/helpers/class-wc-helper-fee.php similarity index 100% rename from tests/framework/helpers/class-wc-helper-fee.php rename to tests/legacy/framework/helpers/class-wc-helper-fee.php diff --git a/tests/framework/helpers/class-wc-helper-order.php b/tests/legacy/framework/helpers/class-wc-helper-order.php similarity index 100% rename from tests/framework/helpers/class-wc-helper-order.php rename to tests/legacy/framework/helpers/class-wc-helper-order.php diff --git a/tests/framework/helpers/class-wc-helper-payment-token.php b/tests/legacy/framework/helpers/class-wc-helper-payment-token.php similarity index 100% rename from tests/framework/helpers/class-wc-helper-payment-token.php rename to tests/legacy/framework/helpers/class-wc-helper-payment-token.php diff --git a/tests/framework/helpers/class-wc-helper-product.php b/tests/legacy/framework/helpers/class-wc-helper-product.php similarity index 100% rename from tests/framework/helpers/class-wc-helper-product.php rename to tests/legacy/framework/helpers/class-wc-helper-product.php diff --git a/tests/framework/helpers/class-wc-helper-settings.php b/tests/legacy/framework/helpers/class-wc-helper-settings.php similarity index 100% rename from tests/framework/helpers/class-wc-helper-settings.php rename to tests/legacy/framework/helpers/class-wc-helper-settings.php diff --git a/tests/framework/helpers/class-wc-helper-shipping-zones.php b/tests/legacy/framework/helpers/class-wc-helper-shipping-zones.php similarity index 100% rename from tests/framework/helpers/class-wc-helper-shipping-zones.php rename to tests/legacy/framework/helpers/class-wc-helper-shipping-zones.php diff --git a/tests/framework/helpers/class-wc-helper-shipping.php b/tests/legacy/framework/helpers/class-wc-helper-shipping.php similarity index 100% rename from tests/framework/helpers/class-wc-helper-shipping.php rename to tests/legacy/framework/helpers/class-wc-helper-shipping.php diff --git a/tests/framework/vendor/class-wp-test-spy-rest-server.php b/tests/legacy/framework/vendor/class-wp-test-spy-rest-server.php similarity index 100% rename from tests/framework/vendor/class-wp-test-spy-rest-server.php rename to tests/legacy/framework/vendor/class-wp-test-spy-rest-server.php diff --git a/tests/includes/listener-loader.php b/tests/legacy/includes/listener-loader.php similarity index 100% rename from tests/includes/listener-loader.php rename to tests/legacy/includes/listener-loader.php diff --git a/tests/includes/wp-http-testcase.php b/tests/legacy/includes/wp-http-testcase.php similarity index 100% rename from tests/includes/wp-http-testcase.php rename to tests/legacy/includes/wp-http-testcase.php diff --git a/tests/legacy/mockable-functions.php b/tests/legacy/mockable-functions.php new file mode 100644 index 00000000000..6d01727f569 --- /dev/null +++ b/tests/legacy/mockable-functions.php @@ -0,0 +1,12 @@ +plugin_dir . '/includes/admin/notes/class-wc-notes-run-db-update.php'; + + } + + /** + * Clean up before each test. + */ + public function setUp() { + if ( ! WC()->is_wc_admin_active() ) { + $this->markTestSkipped( 'WC Admin is not active on WP versions < 5.3' ); + return; + } + self::remove_db_update_notes(); + } + + /** + * Returns a list of note ids with name 'wc-update-db-reminder' from the database. + * + * @return array( int ) List of note ids with name 'wc-update-db-reminder'. + */ + private static function get_db_update_notes() { + $data_store = \WC_Data_Store::load( 'admin-note' ); + $note_ids = $data_store->get_notes_with_name( WC_Notes_Run_Db_Update::NOTE_NAME ); + return $note_ids; + } + + /** + * Removes all the notes with name 'wc-update-db-reminder' from the database. + */ + private static function remove_db_update_notes() { + $data_store = \WC_Data_Store::load( 'admin-note' ); + $note_ids = $data_store->get_notes_with_name( WC_Notes_Run_Db_Update::NOTE_NAME ); + foreach ( $note_ids as $note_id ) { + $note = new WC_Admin_Note( $note_id ); + $data_store->delete( $note ); + } + } + + /** + * Creates a sample note with name 'wc-update-db-reminder'. + * + * @return int Newly create note's id. + */ + private static function create_db_update_note() { + $update_url = html_entity_decode( + wp_nonce_url( + add_query_arg( 'do_update_woocommerce', 'true', admin_url( 'admin.php?page=wc-settings' ) ), + 'wc_db_update', + 'wc_db_update_nonce' + ) + ); + + $note_actions = array( + array( + 'name' => 'update-db_run', + 'label' => __( 'Update WooCommerce Database', 'woocommerce' ), + 'url' => $update_url, + 'status' => 'unactioned', + 'primary' => true, + ), + array( + 'name' => 'update-db_learn-more', + 'label' => __( 'Learn more about updates', 'woocommerce' ), + 'url' => 'https://docs.woocommerce.com/document/how-to-update-woocommerce/', + 'status' => 'unactioned', + 'primary' => false, + ), + ); + + $note = new WC_Admin_Note(); + + $note->set_title( 'WooCommerce database update required' ); + $note->set_content( 'To keep things running smoothly, we have to update your database to the newest version.' ); + $note->set_type( WC_Admin_Note::E_WC_ADMIN_NOTE_UPDATE ); + $note->set_name( WC_Notes_Run_Db_Update::NOTE_NAME ); + $note->set_content_data( (object) array() ); + $note->set_source( 'woocommerce-core' ); + $note->set_status( WC_Admin_Note::E_WC_ADMIN_NOTE_UNACTIONED ); + + // Set new actions. + $note->clear_actions(); + foreach ( $note_actions as $note_action ) { + $note->add_action( ...array_values( $note_action ) ); + } + + return $note->save(); + } + + /** + * No note should be created/exist if db version is equal to WC code version. + */ + public function test_noop_db_update_note() { + update_option( 'woocommerce_db_version', WC()->version ); + + // No notes initially. + $this->assertEquals( 0, count( self::get_db_update_notes() ), 'There should be no db update notes initially.' ); + + WC_Notes_Run_Db_Update::show_reminder(); + + // No notice should be created. + $this->assertEquals( 0, count( self::get_db_update_notes() ), 'There should be no db update notes created if db is up to date.' ); + } + + + /** + * Note should be created if there is none and WC is updated. + */ + public function test_create_db_update_note() { + // No notes initially. + $this->assertEquals( 0, count( self::get_db_update_notes() ), 'There should be no db update notes initially.' ); + + // Make it appear as if db version is lower than WC version, i.e. db update is required. + update_option( 'woocommerce_db_version', '3.9.0' ); + + WC_Notes_Run_Db_Update::show_reminder(); + + // A notice should be created. + $this->assertEquals( 1, count( self::get_db_update_notes() ), 'A db update note should be created if db is NOT up to date.' ); + + // Update the db option back. + update_option( 'woocommerce_db_version', WC()->version ); + } + + /** + * Note should be created if there is none and WC is updated. + */ + public function test_clean_up_multiple_db_update_notes() { + // No notes initially. + $this->assertEquals( 0, count( self::get_db_update_notes() ), 'There should be no db update notes initially.' ); + + $note_1 = self::create_db_update_note(); + $note_2 = self::create_db_update_note(); + + $this->assertEquals( 2, count( self::get_db_update_notes() ), 'There should be 2 db update notes after I created 2.' ); + + WC_Notes_Run_Db_Update::show_reminder(); + + // Only one notice should remain, in case 2 were created under some weird circumstances. + $this->assertEquals( 1, count( self::get_db_update_notes() ), 'A db update note should be created if db is NOT up to date.' ); + + } + + /** + * Test switch from db update needed to thanks note. + */ + public function test_db_update_note_to_thanks_note() { + // No notes initially. + $this->assertEquals( 0, count( self::get_db_update_notes() ), 'There should be no db update notes initially.' ); + + // Make it appear as if db version is lower than WC version, i.e. db update is required. + update_option( 'woocommerce_db_version', '3.9.0' ); + + // Magic 1: nothing to update-db note. + WC_Notes_Run_Db_Update::show_reminder(); + + $note_ids = self::get_db_update_notes(); + // An 'update required' notice should be created. + $this->assertEquals( 1, count( $note_ids ), 'A db update note should be created if db is NOT up to date.' ); + + $note = new WC_Admin_Note( $note_ids[0] ); + $actions = $note->get_actions(); + $this->assertEquals( 'update-db_run', $actions[0]->name, 'A db update note to update the database should be displayed now.' ); + + // Simulate database update has been performed. + update_option( 'woocommerce_db_version', WC()->version ); + + // Magic 2: update-db note to thank you note. + WC_Notes_Run_Db_Update::show_reminder(); + + $note = new WC_Admin_Note( $note_ids[0] ); + $actions = $note->get_actions(); + $this->assertEquals( 'update-db_done', $actions[0]->name, 'A db update note--Thanks for the update--should be displayed now.' ); + } + +} diff --git a/tests/unit-tests/admin/reports/class-wc-tests-admin-report.php b/tests/legacy/unit-tests/admin/reports/class-wc-tests-admin-report.php similarity index 100% rename from tests/unit-tests/admin/reports/class-wc-tests-admin-report.php rename to tests/legacy/unit-tests/admin/reports/class-wc-tests-admin-report.php diff --git a/tests/unit-tests/admin/reports/class-wc-tests-report-sales-by-date.php b/tests/legacy/unit-tests/admin/reports/class-wc-tests-report-sales-by-date.php similarity index 100% rename from tests/unit-tests/admin/reports/class-wc-tests-report-sales-by-date.php rename to tests/legacy/unit-tests/admin/reports/class-wc-tests-report-sales-by-date.php diff --git a/tests/legacy/unit-tests/admin/settings.php b/tests/legacy/unit-tests/admin/settings.php new file mode 100644 index 00000000000..585d996e14e --- /dev/null +++ b/tests/legacy/unit-tests/admin/settings.php @@ -0,0 +1,35 @@ +assertEquals( 'deny from all', $file_content ); + + // Test with "redirect" downloads method. + update_option( 'woocommerce_file_download_method', 'redirect' ); + WC_Admin_Settings::check_download_folder_protection(); + $file_content = @file_get_contents( $file_path ); + $this->assertEquals( 'Options -Indexes', $file_content ); + + update_option( 'woocommerce_file_download_method', $default ); + } +} diff --git a/tests/unit-tests/attributes/functions.php b/tests/legacy/unit-tests/attributes/functions.php similarity index 100% rename from tests/unit-tests/attributes/functions.php rename to tests/legacy/unit-tests/attributes/functions.php diff --git a/tests/unit-tests/cart/cart-fees.php b/tests/legacy/unit-tests/cart/cart-fees.php similarity index 100% rename from tests/unit-tests/cart/cart-fees.php rename to tests/legacy/unit-tests/cart/cart-fees.php diff --git a/tests/unit-tests/cart/cart.php b/tests/legacy/unit-tests/cart/cart.php similarity index 91% rename from tests/unit-tests/cart/cart.php rename to tests/legacy/unit-tests/cart/cart.php index 7c0fe0cb972..ccfe0074fdf 100644 --- a/tests/unit-tests/cart/cart.php +++ b/tests/legacy/unit-tests/cart/cart.php @@ -181,6 +181,10 @@ class WC_Tests_Cart extends WC_Unit_Test_Case { add_filter( 'woocommerce_customer_get_shipping_state', array( $this, 'force_customer_us_state' ) ); add_filter( 'woocommerce_customer_get_shipping_postcode', array( $this, 'force_customer_us_postcode' ) ); + // Create tax classes first. + WC_Tax::create_tax_class( '23percent' ); + WC_Tax::create_tax_class( '5percent' ); + $tax_rate = array( 'tax_rate_country' => '', 'tax_rate_state' => '', @@ -218,7 +222,7 @@ class WC_Tests_Cart extends WC_Unit_Test_Case { $product2 = WC_Helper_Product::create_simple_product(); $product2->set_price( 59 ); $product2->set_regular_price( 59 ); - $product->set_tax_class( '5percent' ); + $product2->set_tax_class( '23percent' ); $product2->save(); // Create a flat rate method. @@ -244,7 +248,7 @@ class WC_Tests_Cart extends WC_Unit_Test_Case { WC()->cart->add_to_cart( $product->get_id(), 1 ); WC()->session->set( 'chosen_shipping_methods', array( 'flat_rate' ) ); WC()->cart->calculate_totals(); - $this->assertEquals( 28.9, WC()->cart->total ); + $this->assertEquals( 27.05, WC()->cart->total ); // Add product2 to cart. WC()->cart->add_to_cart( $product2->get_id(), 1 ); @@ -2051,6 +2055,157 @@ class WC_Tests_Cart extends WC_Unit_Test_Case { $this->assertEquals( 70.86, WC()->cart->get_total( 'edit' ) ); } + /** + * Test that adding a variation with URL parameter increases the quantity appropriately + * as described in issue 24000. + */ + public function test_add_variation_by_url() { + add_filter( 'woocommerce_add_to_cart_redirect', '__return_false' ); + update_option( 'woocommerce_cart_redirect_after_add', 'no' ); + WC()->cart->empty_cart(); + WC()->session->set( 'wc_notices', null ); + + $product = WC_Helper_Product::create_variation_product(); + $variations = $product->get_available_variations(); + $variation = array_pop( $variations ); + + // Add variation with add_to_cart_action. + $_REQUEST['add-to-cart'] = $variation['variation_id']; + WC_Form_Handler::add_to_cart_action( false ); + $notices = WC()->session->get( 'wc_notices', array() ); + + // Reset filter / REQUEST variables. + unset( $_REQUEST['add-to-cart'] ); + remove_filter( 'woocommerce_add_to_cart_redirect', '__return_false' ); + + // Check if the item is in the cart. + $this->assertCount( 1, WC()->cart->get_cart_contents() ); + $this->assertEquals( 1, WC()->cart->get_cart_contents_count() ); + + // Check that there are no error notices. + $this->assertArrayNotHasKey( 'error', $notices ); + + // Add variation using parent id. + WC()->cart->add_to_cart( + $product->get_id(), + 1, + $variation['variation_id'], + array( + 'attribute_pa_size' => 'huge', + 'attribute_pa_colour' => 'red', + 'attribute_pa_number' => '2', + ) + ); + $notices = WC()->session->get( 'wc_notices', array() ); + + // Check that the second add to cart call increases the quantity of the existing cart-item. + $this->assertCount( 1, WC()->cart->get_cart_contents() ); + $this->assertEquals( 2, WC()->cart->get_cart_contents_count() ); + + // Check that there are no error notices. + $this->assertArrayNotHasKey( 'error', $notices ); + } + + /** + * Test that adding a variation via URL parameter fails when specifying a value for the attribute + * that differs from a value belonging to that variant. + */ + public function test_add_variation_by_url_with_invalid_attribute() { + add_filter( 'woocommerce_add_to_cart_redirect', '__return_false' ); + update_option( 'woocommerce_cart_redirect_after_add', 'no' ); + WC()->cart->empty_cart(); + WC()->session->set( 'wc_notices', null ); + + $product = WC_Helper_Product::create_variation_product(); + $variations = $product->get_available_variations(); + $variation = array_pop( $variations ); + + // Attempt adding variation with add_to_cart_action, specifying a different colour. + $_REQUEST['add-to-cart'] = $variation['variation_id']; + $_REQUEST['attribute_pa_colour'] = 'green'; + WC_Form_Handler::add_to_cart_action( false ); + $notices = WC()->session->get( 'wc_notices', array() ); + + // Reset filter / REQUEST variables. + unset( $_REQUEST['add-to-cart'] ); + unset( $_REQUEST['attribute_pa_colour'] ); + remove_filter( 'woocommerce_add_to_cart_redirect', '__return_false' ); + + // Check that the notices contain an error message about an invalid colour. + $this->assertArrayHasKey( 'error', $notices ); + $this->assertCount( 1, $notices['error'] ); + $this->assertEquals( 'Invalid value posted for colour', $notices['error'][0]['notice'] ); + } + + /** + * Test that adding a variation via URL parameter succeeds when some attributes belong to the + * variation and others are specificed via URL parameter. + */ + public function test_add_variation_by_url_with_valid_attribute() { + add_filter( 'woocommerce_add_to_cart_redirect', '__return_false' ); + update_option( 'woocommerce_cart_redirect_after_add', 'no' ); + WC()->cart->empty_cart(); + WC()->session->set( 'wc_notices', null ); + + $product = WC_Helper_Product::create_variation_product(); + $variations = $product->get_available_variations(); + $variation = array_shift( $variations ); + + // Attempt adding variation with add_to_cart_action, specifying attributes not defined in the variation. + $_REQUEST['add-to-cart'] = $variation['variation_id']; + $_REQUEST['attribute_pa_colour'] = 'red'; + $_REQUEST['attribute_pa_number'] = '1'; + WC_Form_Handler::add_to_cart_action( false ); + $notices = WC()->session->get( 'wc_notices', array() ); + + // Reset filter / REQUEST variables. + unset( $_REQUEST['add-to-cart'] ); + unset( $_REQUEST['attribute_pa_colour'] ); + unset( $_REQUEST['attribute_pa_number'] ); + remove_filter( 'woocommerce_add_to_cart_redirect', '__return_false' ); + + // Check if the item is in the cart. + $this->assertCount( 1, WC()->cart->get_cart_contents() ); + $this->assertEquals( 1, WC()->cart->get_cart_contents_count() ); + + // Check that there are no error notices. + $this->assertArrayNotHasKey( 'error', $notices ); + } + + /** + * Test that adding a varition via URL parameter fails when an 'any' attribute is missing. + */ + public function test_add_variation_by_url_fails_with_missing_any_attribute() { + add_filter( 'woocommerce_add_to_cart_redirect', '__return_false' ); + update_option( 'woocommerce_cart_redirect_after_add', 'no' ); + WC()->cart->empty_cart(); + WC()->session->set( 'wc_notices', null ); + + $product = WC_Helper_Product::create_variation_product(); + $variations = $product->get_available_variations(); + $variation = array_shift( $variations ); + + // Attempt adding variation with add_to_cart_action, without specifying attribute_pa_colour. + $_REQUEST['add-to-cart'] = $variation['variation_id']; + $_REQUEST['attribute_pa_number'] = '0'; + WC_Form_Handler::add_to_cart_action( false ); + $notices = WC()->session->get( 'wc_notices', array() ); + + // Reset filter / REQUEST variables. + unset( $_REQUEST['add-to-cart'] ); + unset( $_REQUEST['attribute_pa_number'] ); + remove_filter( 'woocommerce_add_to_cart_redirect', '__return_false' ); + + // Verify that there is nothing in the cart. + $this->assertCount( 0, WC()->cart->get_cart_contents() ); + $this->assertEquals( 0, WC()->cart->get_cart_contents_count() ); + + // Check that the notices contain an error message about an invalid colour. + $this->assertArrayHasKey( 'error', $notices ); + $this->assertCount( 1, $notices['error'] ); + $this->assertEquals( 'colour is a required field', $notices['error'][0]['notice'] ); + } + /** * Helper function. Adds 1.5 taxable fees to cart. */ diff --git a/tests/unit-tests/cart/functions.php b/tests/legacy/unit-tests/cart/functions.php similarity index 100% rename from tests/unit-tests/cart/functions.php rename to tests/legacy/unit-tests/cart/functions.php diff --git a/tests/unit-tests/checkout/checkout.php b/tests/legacy/unit-tests/checkout/checkout.php similarity index 56% rename from tests/unit-tests/checkout/checkout.php rename to tests/legacy/unit-tests/checkout/checkout.php index fb2ad7ea82d..d6639ec88ab 100644 --- a/tests/unit-tests/checkout/checkout.php +++ b/tests/legacy/unit-tests/checkout/checkout.php @@ -9,9 +9,8 @@ * Class WC_Checkout */ class WC_Tests_Checkout extends WC_Unit_Test_Case { - /** - * TearDown for tests. + * TearDown. */ public function tearDown() { parent::tearDown(); @@ -19,7 +18,7 @@ class WC_Tests_Checkout extends WC_Unit_Test_Case { } /** - * Setup for tests. + * Setup. */ public function setUp() { parent::setUp(); @@ -32,24 +31,24 @@ class WC_Tests_Checkout extends WC_Unit_Test_Case { * @throws Exception When unable to create order. */ public function test_create_order_with_limited_coupon() { - $coupon_code = 'coupon4one'; + $coupon_code = 'coupon4one'; $coupon_data_store = WC_Data_Store::load( 'coupon' ); - $coupon = WC_Helper_Coupon::create_coupon( + $coupon = WC_Helper_Coupon::create_coupon( $coupon_code, array( 'usage_limit' => 1 ) ); - $product = WC_Helper_Product::create_simple_product( true ); + $product = WC_Helper_Product::create_simple_product( true ); WC()->cart->add_to_cart( $product->get_id(), 1 ); WC()->cart->add_discount( $coupon->get_code() ); $checkout = WC_Checkout::instance(); $order_id = $checkout->create_order( array( - 'billing_email' => 'a@b.com', + 'billing_email' => 'a@b.com', 'payment_method' => 'dummy_payment_gateway', ) ); $this->assertNotWPError( $order_id ); - $order = new WC_Order( $order_id ); + $order = new WC_Order( $order_id ); $coupon_held_key = $order->get_data_store()->get_coupon_held_keys( $order ); $this->assertEquals( count( $coupon_held_key ), 1 ); $this->assertEquals( array_keys( $coupon_held_key )[0], $coupon->get_id() ); @@ -61,7 +60,7 @@ class WC_Tests_Checkout extends WC_Unit_Test_Case { WC()->cart->add_discount( $coupon->get_code() ); $order2_id = $checkout->create_order( array( - 'billing_email' => 'a@c.com', + 'billing_email' => 'a@c.com', 'payment_method' => 'dummy_payment_gateway', ) ); @@ -75,8 +74,8 @@ class WC_Tests_Checkout extends WC_Unit_Test_Case { * @throws Exception When unable to create an order. */ public function test_create_order_with_multiple_limited_coupons() { - $coupon_code1 = 'coupon1'; - $coupon_code2 = 'coupon2'; + $coupon_code1 = 'coupon1'; + $coupon_code2 = 'coupon2'; $coupon_data_store = WC_Data_Store::load( 'coupon' ); $coupon1 = WC_Helper_Coupon::create_coupon( @@ -91,10 +90,10 @@ class WC_Tests_Checkout extends WC_Unit_Test_Case { WC()->cart->add_to_cart( $product->get_id(), 1 ); WC()->cart->add_discount( $coupon_code1 ); WC()->cart->add_discount( $coupon_code2 ); - $checkout = WC_Checkout::instance(); + $checkout = WC_Checkout::instance(); $order_id1 = $checkout->create_order( array( - 'billing_email' => 'a@b.com', + 'billing_email' => 'a@b.com', 'payment_method' => 'dummy_payment_gateway', ) ); @@ -110,7 +109,7 @@ class WC_Tests_Checkout extends WC_Unit_Test_Case { $order2_id = $checkout->create_order( array( - 'billing_email' => 'a@b.com', + 'billing_email' => 'a@b.com', 'payment_method' => 'dummy_payment_gateway', ) ); @@ -188,4 +187,120 @@ class WC_Tests_Checkout extends WC_Unit_Test_Case { return 0.01; } + /** + * Helper method to create a managed product and a order for that product. + * + * @return array + * @throws Exception When unable to create an order . + */ + protected function create_order_for_managed_inventory_product() { + $product = WC_Helper_Product::create_simple_product(); + $product->set_props( array( 'manage_stock' => true ) ); + $product->set_stock_quantity( 10 ); + $product->save(); + + WC()->cart->add_to_cart( $product->get_id(), 9 ); + $this->assertEquals( true, WC()->cart->check_cart_items() ); + + $checkout = WC_Checkout::instance(); + $order_id = $checkout->create_order( + array( + 'payment_method' => 'cod', + 'billing_email' => 'a@b.com', + ) + ); + + // Assertions whether the order was created successfully. + $this->assertNotWPError( $order_id ); + $order = wc_get_order( $order_id ); + + return array( $product, $order ); + } + + /** + * Test when order is out stock because it is held by an order in pending status. + * + * @throws Exception When unable to create order. + */ + public function test_create_order_when_out_of_stock() { + list( $product, $order ) = $this->create_order_for_managed_inventory_product(); + + $this->assertEquals( 9, $order->get_item_count() ); + $this->assertEquals( 'pending', $order->get_status() ); + $this->assertEquals( 9, wc_get_held_stock_quantity( $product ) ); + + WC()->cart->empty_cart(); + WC()->cart->add_to_cart( $product->get_stock_managed_by_id(), 2 ); + + $this->assertEquals( false, WC()->cart->check_cart_items() ); + } + + /** + * Test if pending stock is cleared when order is cancelled. + * + * @throws Exception When unable to create order. + */ + public function test_pending_is_cleared_when_order_is_cancelled() { + list( $product, $order ) = $this->create_order_for_managed_inventory_product(); + + $this->assertEquals( 9, wc_get_held_stock_quantity( $product ) ); + $order->set_status( 'cancelled' ); + $order->save(); + + $this->assertEquals( 0, wc_get_held_stock_quantity( $product ) ); + $this->assertEquals( 10, $product->get_stock_quantity() ); + + } + + /** + * Test if pending stock is cleared when order is processing. + * + * @throws Exception When unable to create order. + */ + public function test_pending_is_cleared_when_order_processed() { + list( $product, $order ) = $this->create_order_for_managed_inventory_product(); + + $this->assertEquals( 9, wc_get_held_stock_quantity( $product ) ); + $order->set_status( 'processing' ); + $order->save(); + + $this->assertEquals( 0, wc_get_held_stock_quantity( $product ) ); + } + + /** + * Test creating order from managed stock for variable product. + * + * @throws Exception When unable to create an order. + */ + public function test_create_order_for_variation_product() { + $parent_product = WC_Helper_Product::create_variation_product(); + $variation = $parent_product->get_available_variations()[0]; + $variation = wc_get_product( $variation['variation_id'] ); + $variation->set_manage_stock( true ); + $variation->set_stock_quantity( 10 ); + $variation->save(); + WC()->cart->add_to_cart( $variation->get_id(), 9 ); + $this->assertEquals( true, WC()->cart->check_cart_items() ); + + $checkout = WC_Checkout::instance(); + $order_id = $checkout->create_order( + array( + 'payment_method' => 'cod', + 'billing_email' => 'a@b.com', + ) + ); + + // Assertions whether the first order was created successfully. + $this->assertNotWPError( $order_id ); + $order = wc_get_order( $order_id ); + + $this->assertEquals( 9, $order->get_item_count() ); + $this->assertEquals( 'pending', $order->get_status() ); + $this->assertEquals( 9, wc_get_held_stock_quantity( $variation ) ); + + WC()->cart->empty_cart(); + WC()->cart->add_to_cart( $variation->get_stock_managed_by_id(), 2 ); + + $this->assertEquals( false, WC()->cart->check_cart_items() ); + } } diff --git a/tests/unit-tests/core/main-class.php b/tests/legacy/unit-tests/core/main-class.php similarity index 94% rename from tests/unit-tests/core/main-class.php rename to tests/legacy/unit-tests/core/main-class.php index 5e9d92f4223..eb66ed137f0 100644 --- a/tests/unit-tests/core/main-class.php +++ b/tests/legacy/unit-tests/core/main-class.php @@ -41,7 +41,7 @@ class WC_Test_WooCommerce extends WC_Unit_Test_Case { * @since 2.2 */ public function test_constants() { - $this->assertEquals( str_replace( 'tests/unit-tests/core/', '', plugin_dir_path( __FILE__ ) ) . 'woocommerce.php', WC_PLUGIN_FILE ); + $this->assertEquals( str_replace( 'tests/legacy/unit-tests/core/', '', plugin_dir_path( __FILE__ ) ) . 'woocommerce.php', WC_PLUGIN_FILE ); $this->assertEquals( $this->wc->version, Constants::get_constant( 'WC_VERSION' ) ); $this->assertEquals( WC_VERSION, WOOCOMMERCE_VERSION ); $this->assertEquals( 6, WC_ROUNDING_PRECISION ); diff --git a/tests/unit-tests/core/post-types-admin.php b/tests/legacy/unit-tests/core/post-types-admin.php similarity index 100% rename from tests/unit-tests/core/post-types-admin.php rename to tests/legacy/unit-tests/core/post-types-admin.php diff --git a/tests/unit-tests/core/taxonomies.php b/tests/legacy/unit-tests/core/taxonomies.php similarity index 100% rename from tests/unit-tests/core/taxonomies.php rename to tests/legacy/unit-tests/core/taxonomies.php diff --git a/tests/unit-tests/countries/countries.php b/tests/legacy/unit-tests/countries/countries.php similarity index 100% rename from tests/unit-tests/countries/countries.php rename to tests/legacy/unit-tests/countries/countries.php diff --git a/tests/unit-tests/coupon/coupon.php b/tests/legacy/unit-tests/coupon/coupon.php similarity index 100% rename from tests/unit-tests/coupon/coupon.php rename to tests/legacy/unit-tests/coupon/coupon.php diff --git a/tests/unit-tests/coupon/data-store.php b/tests/legacy/unit-tests/coupon/data-store.php similarity index 100% rename from tests/unit-tests/coupon/data-store.php rename to tests/legacy/unit-tests/coupon/data-store.php diff --git a/tests/unit-tests/coupon/data.php b/tests/legacy/unit-tests/coupon/data.php similarity index 100% rename from tests/unit-tests/coupon/data.php rename to tests/legacy/unit-tests/coupon/data.php diff --git a/tests/unit-tests/coupon/functions.php b/tests/legacy/unit-tests/coupon/functions.php similarity index 100% rename from tests/unit-tests/coupon/functions.php rename to tests/legacy/unit-tests/coupon/functions.php diff --git a/tests/unit-tests/crud/data-store.php b/tests/legacy/unit-tests/crud/data-store.php similarity index 100% rename from tests/unit-tests/crud/data-store.php rename to tests/legacy/unit-tests/crud/data-store.php diff --git a/tests/unit-tests/crud/data.php b/tests/legacy/unit-tests/crud/data.php similarity index 100% rename from tests/unit-tests/crud/data.php rename to tests/legacy/unit-tests/crud/data.php diff --git a/tests/unit-tests/crud/meta.php b/tests/legacy/unit-tests/crud/meta.php similarity index 100% rename from tests/unit-tests/crud/meta.php rename to tests/legacy/unit-tests/crud/meta.php diff --git a/tests/unit-tests/crud/query.php b/tests/legacy/unit-tests/crud/query.php similarity index 100% rename from tests/unit-tests/crud/query.php rename to tests/legacy/unit-tests/crud/query.php diff --git a/tests/unit-tests/crud/refunds.php b/tests/legacy/unit-tests/crud/refunds.php similarity index 100% rename from tests/unit-tests/crud/refunds.php rename to tests/legacy/unit-tests/crud/refunds.php diff --git a/tests/unit-tests/customer/class-wc-customer-download-log-data-store.php b/tests/legacy/unit-tests/customer/class-wc-customer-download-log-data-store.php similarity index 100% rename from tests/unit-tests/customer/class-wc-customer-download-log-data-store.php rename to tests/legacy/unit-tests/customer/class-wc-customer-download-log-data-store.php diff --git a/tests/unit-tests/customer/class-wc-tests-customer-download.php b/tests/legacy/unit-tests/customer/class-wc-tests-customer-download.php similarity index 100% rename from tests/unit-tests/customer/class-wc-tests-customer-download.php rename to tests/legacy/unit-tests/customer/class-wc-tests-customer-download.php diff --git a/tests/unit-tests/customer/crud.php b/tests/legacy/unit-tests/customer/crud.php similarity index 100% rename from tests/unit-tests/customer/crud.php rename to tests/legacy/unit-tests/customer/crud.php diff --git a/tests/unit-tests/customer/customer-download-log.php b/tests/legacy/unit-tests/customer/customer-download-log.php similarity index 100% rename from tests/unit-tests/customer/customer-download-log.php rename to tests/legacy/unit-tests/customer/customer-download-log.php diff --git a/tests/unit-tests/customer/customer.php b/tests/legacy/unit-tests/customer/customer.php similarity index 100% rename from tests/unit-tests/customer/customer.php rename to tests/legacy/unit-tests/customer/customer.php diff --git a/tests/unit-tests/customer/functions.php b/tests/legacy/unit-tests/customer/functions.php similarity index 100% rename from tests/unit-tests/customer/functions.php rename to tests/legacy/unit-tests/customer/functions.php diff --git a/tests/unit-tests/discounts/discounts.php b/tests/legacy/unit-tests/discounts/discounts.php similarity index 100% rename from tests/unit-tests/discounts/discounts.php rename to tests/legacy/unit-tests/discounts/discounts.php diff --git a/tests/unit-tests/email/emails.php b/tests/legacy/unit-tests/email/emails.php similarity index 100% rename from tests/unit-tests/email/emails.php rename to tests/legacy/unit-tests/email/emails.php diff --git a/tests/unit-tests/exporter/product.php b/tests/legacy/unit-tests/exporter/product.php similarity index 100% rename from tests/unit-tests/exporter/product.php rename to tests/legacy/unit-tests/exporter/product.php diff --git a/tests/unit-tests/formatting/functions.php b/tests/legacy/unit-tests/formatting/functions.php similarity index 99% rename from tests/unit-tests/formatting/functions.php rename to tests/legacy/unit-tests/formatting/functions.php index a2e517dfea4..10c52e4fa2c 100644 --- a/tests/unit-tests/formatting/functions.php +++ b/tests/legacy/unit-tests/formatting/functions.php @@ -699,15 +699,15 @@ class WC_Tests_Formatting_Functions extends WC_Unit_Test_Case { // Test with missing UTC offset. delete_option( 'gmt_offset' ); - $this->assertEquals( 'UTC', wc_timezone_string() ); + $this->assertContains( wc_timezone_string(), array( '+00:00', 'UTC' ) ); // Test with manually set UTC offset. update_option( 'gmt_offset', -4 ); - $this->assertNotEquals( 'UTC', wc_timezone_string() ); + $this->assertNotContains( wc_timezone_string(), array( '+00:00', 'UTC' ) ); // Test with invalid offset. - update_option( 'gmt_offset', 99 ); - $this->assertEquals( 'UTC', wc_timezone_string() ); + update_option( 'gmt_offset', 'invalid' ); + $this->assertContains( wc_timezone_string(), array( '+00:00', 'UTC' ) ); // Restore default. update_option( 'gmt_offset', '0' ); diff --git a/tests/unit-tests/gateways/gateways.php b/tests/legacy/unit-tests/gateways/gateways.php similarity index 100% rename from tests/unit-tests/gateways/gateways.php rename to tests/legacy/unit-tests/gateways/gateways.php diff --git a/tests/unit-tests/gateways/paypal/request.php b/tests/legacy/unit-tests/gateways/paypal/request.php similarity index 100% rename from tests/unit-tests/gateways/paypal/request.php rename to tests/legacy/unit-tests/gateways/paypal/request.php diff --git a/tests/unit-tests/geolocation/class-wc-test-gelocation.php b/tests/legacy/unit-tests/geolocation/class-wc-test-gelocation.php similarity index 100% rename from tests/unit-tests/geolocation/class-wc-test-gelocation.php rename to tests/legacy/unit-tests/geolocation/class-wc-test-gelocation.php diff --git a/tests/unit-tests/importer/product.php b/tests/legacy/unit-tests/importer/product.php similarity index 99% rename from tests/unit-tests/importer/product.php rename to tests/legacy/unit-tests/importer/product.php index 4a8bad510da..e55fdd79351 100644 --- a/tests/unit-tests/importer/product.php +++ b/tests/legacy/unit-tests/importer/product.php @@ -147,7 +147,7 @@ class WC_Tests_Product_CSV_Importer extends WC_Unit_Test_Case { * @return void */ public function test_server_file() { - copy( $this->csv_file, ABSPATH . '/sample.csv' ); + self::file_copy( $this->csv_file, ABSPATH . '/sample.csv' ); $_POST['file_url'] = 'sample.csv'; $import_controller = new WC_Product_CSV_Importer_Controller(); $this->assertEquals( ABSPATH . 'sample.csv', $import_controller->handle_upload() ); @@ -644,7 +644,7 @@ class WC_Tests_Product_CSV_Importer extends WC_Unit_Test_Case { if ( false !== strpos( $url, 'http://demo.woothemes.com' ) ) { if ( ! empty( $request['filename'] ) ) { - copy( WC_Unit_Tests_Bootstrap::instance()->tests_dir . '/data/Dr1Bczxq4q.png', $request['filename'] ); + self::file_copy( WC_Unit_Tests_Bootstrap::instance()->tests_dir . '/data/Dr1Bczxq4q.png', $request['filename'] ); } $mocked_response = array( diff --git a/tests/unit-tests/importer/sample.csv b/tests/legacy/unit-tests/importer/sample.csv similarity index 100% rename from tests/unit-tests/importer/sample.csv rename to tests/legacy/unit-tests/importer/sample.csv diff --git a/tests/unit-tests/importer/sample_tax_rates.csv b/tests/legacy/unit-tests/importer/sample_tax_rates.csv similarity index 100% rename from tests/unit-tests/importer/sample_tax_rates.csv rename to tests/legacy/unit-tests/importer/sample_tax_rates.csv diff --git a/tests/unit-tests/importer/sample_update_product.csv b/tests/legacy/unit-tests/importer/sample_update_product.csv similarity index 100% rename from tests/unit-tests/importer/sample_update_product.csv rename to tests/legacy/unit-tests/importer/sample_update_product.csv diff --git a/tests/unit-tests/importer/tax.php b/tests/legacy/unit-tests/importer/tax.php similarity index 100% rename from tests/unit-tests/importer/tax.php rename to tests/legacy/unit-tests/importer/tax.php diff --git a/tests/unit-tests/integrations/class-dummy-integration.php b/tests/legacy/unit-tests/integrations/class-dummy-integration.php similarity index 100% rename from tests/unit-tests/integrations/class-dummy-integration.php rename to tests/legacy/unit-tests/integrations/class-dummy-integration.php diff --git a/tests/unit-tests/integrations/class-wc-tests-integrations.php b/tests/legacy/unit-tests/integrations/class-wc-tests-integrations.php similarity index 100% rename from tests/unit-tests/integrations/class-wc-tests-integrations.php rename to tests/legacy/unit-tests/integrations/class-wc-tests-integrations.php diff --git a/tests/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-database.php b/tests/legacy/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-database.php similarity index 95% rename from tests/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-database.php rename to tests/legacy/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-database.php index e4018d93824..6e424380a33 100644 --- a/tests/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-database.php +++ b/tests/legacy/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-database.php @@ -57,7 +57,12 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { $database_service = new WC_Integration_MaxMind_Database_Service( '' ); $expected_database = sys_get_temp_dir() . '/GeoLite2-Country_20200100/GeoLite2-Country.mmdb'; + self::disable_code_hacker(); $result = $database_service->download_database( 'testing_license' ); + self::reenable_code_hacker(); + if ( is_wp_error( $result ) ) { + $this->fail( $result->get_error_message() ); + } $this->assertEquals( $expected_database, $result ); @@ -126,7 +131,7 @@ class WC_Tests_MaxMind_Database extends WC_Unit_Test_Case { if ( 'https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=testing_license&suffix=tar.gz' === $url ) { // We need to copy the file to where the request is supposed to have streamed it. - copy( WC_Unit_Tests_Bootstrap::instance()->tests_dir . '/data/GeoLite2-Country.tar.gz', $request['filename'] ); + self::file_copy( WC_Unit_Tests_Bootstrap::instance()->tests_dir . '/data/GeoLite2-Country.tar.gz', $request['filename'] ); $mocked_response = array( 'response' => array( 'code' => 200 ), diff --git a/tests/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-integration.php b/tests/legacy/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-integration.php similarity index 100% rename from tests/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-integration.php rename to tests/legacy/unit-tests/integrations/maxmind-geolocation/class-wc-tests-maxmind-integration.php diff --git a/tests/unit-tests/libraries/class-wc-mock-background-process.php b/tests/legacy/unit-tests/libraries/class-wc-mock-background-process.php similarity index 100% rename from tests/unit-tests/libraries/class-wc-mock-background-process.php rename to tests/legacy/unit-tests/libraries/class-wc-mock-background-process.php diff --git a/tests/unit-tests/libraries/wp-background-process.php b/tests/legacy/unit-tests/libraries/wp-background-process.php similarity index 100% rename from tests/unit-tests/libraries/wp-background-process.php rename to tests/legacy/unit-tests/libraries/wp-background-process.php diff --git a/tests/unit-tests/log/log-handler-db.php b/tests/legacy/unit-tests/log/log-handler-db.php similarity index 100% rename from tests/unit-tests/log/log-handler-db.php rename to tests/legacy/unit-tests/log/log-handler-db.php diff --git a/tests/unit-tests/log/log-handler-email.php b/tests/legacy/unit-tests/log/log-handler-email.php similarity index 100% rename from tests/unit-tests/log/log-handler-email.php rename to tests/legacy/unit-tests/log/log-handler-email.php diff --git a/tests/unit-tests/log/log-handler-file.php b/tests/legacy/unit-tests/log/log-handler-file.php similarity index 100% rename from tests/unit-tests/log/log-handler-file.php rename to tests/legacy/unit-tests/log/log-handler-file.php diff --git a/tests/unit-tests/log/log-levels.php b/tests/legacy/unit-tests/log/log-levels.php similarity index 100% rename from tests/unit-tests/log/log-levels.php rename to tests/legacy/unit-tests/log/log-levels.php diff --git a/tests/unit-tests/log/logger.php b/tests/legacy/unit-tests/log/logger.php similarity index 100% rename from tests/unit-tests/log/logger.php rename to tests/legacy/unit-tests/log/logger.php diff --git a/tests/unit-tests/log/test_log_expected.txt b/tests/legacy/unit-tests/log/test_log_expected.txt similarity index 100% rename from tests/unit-tests/log/test_log_expected.txt rename to tests/legacy/unit-tests/log/test_log_expected.txt diff --git a/tests/unit-tests/order-items/class-wc-tests-order-item-data-store.php b/tests/legacy/unit-tests/order-items/class-wc-tests-order-item-data-store.php similarity index 100% rename from tests/unit-tests/order-items/class-wc-tests-order-item-data-store.php rename to tests/legacy/unit-tests/order-items/class-wc-tests-order-item-data-store.php diff --git a/tests/unit-tests/order-items/class-wc-tests-order-item-product.php b/tests/legacy/unit-tests/order-items/class-wc-tests-order-item-product.php similarity index 100% rename from tests/unit-tests/order-items/class-wc-tests-order-item-product.php rename to tests/legacy/unit-tests/order-items/class-wc-tests-order-item-product.php diff --git a/tests/unit-tests/order-items/functions.php b/tests/legacy/unit-tests/order-items/functions.php similarity index 100% rename from tests/unit-tests/order-items/functions.php rename to tests/legacy/unit-tests/order-items/functions.php diff --git a/tests/unit-tests/order-items/order-item-coupon.php b/tests/legacy/unit-tests/order-items/order-item-coupon.php similarity index 100% rename from tests/unit-tests/order-items/order-item-coupon.php rename to tests/legacy/unit-tests/order-items/order-item-coupon.php diff --git a/tests/unit-tests/order-items/order-item-fee.php b/tests/legacy/unit-tests/order-items/order-item-fee.php similarity index 100% rename from tests/unit-tests/order-items/order-item-fee.php rename to tests/legacy/unit-tests/order-items/order-item-fee.php diff --git a/tests/unit-tests/order-items/order-item-meta.php b/tests/legacy/unit-tests/order-items/order-item-meta.php similarity index 100% rename from tests/unit-tests/order-items/order-item-meta.php rename to tests/legacy/unit-tests/order-items/order-item-meta.php diff --git a/tests/unit-tests/order-items/order-item-tax.php b/tests/legacy/unit-tests/order-items/order-item-tax.php similarity index 100% rename from tests/unit-tests/order-items/order-item-tax.php rename to tests/legacy/unit-tests/order-items/order-item-tax.php diff --git a/tests/unit-tests/order/class-wc-tests-crud-orders.php b/tests/legacy/unit-tests/order/class-wc-tests-crud-orders.php similarity index 100% rename from tests/unit-tests/order/class-wc-tests-crud-orders.php rename to tests/legacy/unit-tests/order/class-wc-tests-crud-orders.php diff --git a/tests/unit-tests/order/class-wc-tests-order-functions.php b/tests/legacy/unit-tests/order/class-wc-tests-order-functions.php similarity index 100% rename from tests/unit-tests/order/class-wc-tests-order-functions.php rename to tests/legacy/unit-tests/order/class-wc-tests-order-functions.php diff --git a/tests/unit-tests/order/class-wc-tests-orders.php b/tests/legacy/unit-tests/order/class-wc-tests-orders.php similarity index 98% rename from tests/unit-tests/order/class-wc-tests-orders.php rename to tests/legacy/unit-tests/order/class-wc-tests-orders.php index 20305f95ed1..4877745a592 100644 --- a/tests/unit-tests/order/class-wc-tests-orders.php +++ b/tests/legacy/unit-tests/order/class-wc-tests-orders.php @@ -8,7 +8,7 @@ /** * Class WC_Tests_Order. */ -class WC_Tests_Order extends WC_Unit_Test_Case { +class WC_Tests_Orders extends WC_Unit_Test_Case { /** * Test for total when round at subtotal is enabled. diff --git a/tests/unit-tests/order/coupons.php b/tests/legacy/unit-tests/order/coupons.php similarity index 99% rename from tests/unit-tests/order/coupons.php rename to tests/legacy/unit-tests/order/coupons.php index 0fdb4fce3e9..dbfbea78180 100644 --- a/tests/unit-tests/order/coupons.php +++ b/tests/legacy/unit-tests/order/coupons.php @@ -371,6 +371,7 @@ class WC_Tests_Order_Coupons extends WC_Unit_Test_Case { public function test_inclusive_tax_rounding_on_totals() { update_option( 'woocommerce_prices_include_tax', 'yes' ); update_option( 'woocommerce_calc_taxes', 'yes' ); + update_option( 'woocommerce_tax_round_at_subtotal', 'yes' ); WC_Tax::_insert_tax_rate( array( @@ -440,12 +441,9 @@ class WC_Tests_Order_Coupons extends WC_Unit_Test_Case { $order->apply_coupon( $coupon->get_code() ); $applied_coupons = $order->get_items( 'coupon' ); - $applied_coupon = current( $applied_coupons ); $this->assertEquals( '16.95', $order->get_total() ); $this->assertEquals( '1.73', $order->get_total_tax() ); $this->assertEquals( '1.69', $order->get_discount_total() ); - - $this->assertEquals( '1.69', $applied_coupon->get_discount() ); } } diff --git a/tests/unit-tests/order/query.php b/tests/legacy/unit-tests/order/query.php similarity index 100% rename from tests/unit-tests/order/query.php rename to tests/legacy/unit-tests/order/query.php diff --git a/tests/unit-tests/packages/packages.php b/tests/legacy/unit-tests/packages/packages.php similarity index 100% rename from tests/unit-tests/packages/packages.php rename to tests/legacy/unit-tests/packages/packages.php diff --git a/tests/unit-tests/page-functions/class-wc-tests-page-functions.php b/tests/legacy/unit-tests/page-functions/class-wc-tests-page-functions.php similarity index 100% rename from tests/unit-tests/page-functions/class-wc-tests-page-functions.php rename to tests/legacy/unit-tests/page-functions/class-wc-tests-page-functions.php diff --git a/tests/unit-tests/payment-gateways/cod.php b/tests/legacy/unit-tests/payment-gateways/cod.php similarity index 100% rename from tests/unit-tests/payment-gateways/cod.php rename to tests/legacy/unit-tests/payment-gateways/cod.php diff --git a/tests/unit-tests/payment-gateways/payment-gateways.php b/tests/legacy/unit-tests/payment-gateways/payment-gateways.php similarity index 100% rename from tests/unit-tests/payment-gateways/payment-gateways.php rename to tests/legacy/unit-tests/payment-gateways/payment-gateways.php diff --git a/tests/unit-tests/payment-tokens/cc.php b/tests/legacy/unit-tests/payment-tokens/cc.php similarity index 100% rename from tests/unit-tests/payment-tokens/cc.php rename to tests/legacy/unit-tests/payment-tokens/cc.php diff --git a/tests/unit-tests/payment-tokens/echeck.php b/tests/legacy/unit-tests/payment-tokens/echeck.php similarity index 100% rename from tests/unit-tests/payment-tokens/echeck.php rename to tests/legacy/unit-tests/payment-tokens/echeck.php diff --git a/tests/unit-tests/payment-tokens/payment-token.php b/tests/legacy/unit-tests/payment-tokens/payment-token.php similarity index 100% rename from tests/unit-tests/payment-tokens/payment-token.php rename to tests/legacy/unit-tests/payment-tokens/payment-token.php diff --git a/tests/unit-tests/payment-tokens/payment-tokens.php b/tests/legacy/unit-tests/payment-tokens/payment-tokens.php similarity index 100% rename from tests/unit-tests/payment-tokens/payment-tokens.php rename to tests/legacy/unit-tests/payment-tokens/payment-tokens.php diff --git a/tests/unit-tests/privacy/export.php b/tests/legacy/unit-tests/privacy/export.php similarity index 94% rename from tests/unit-tests/privacy/export.php rename to tests/legacy/unit-tests/privacy/export.php index 2a9a8fb1ffd..0d8db0ee39e 100644 --- a/tests/unit-tests/privacy/export.php +++ b/tests/legacy/unit-tests/privacy/export.php @@ -71,10 +71,11 @@ class WC_Test_Privacy_Export extends WC_Unit_Test_Case { $this->assertEquals( array( array( - 'group_id' => 'woocommerce_customer', - 'group_label' => 'Customer Data', - 'item_id' => 'user', - 'data' => array( + 'group_id' => 'woocommerce_customer', + 'group_label' => 'Customer Data', + 'group_description' => 'User’s WooCommerce customer data.', + 'item_id' => 'user', + 'data' => array( array( 'name' => 'Billing Address 1', 'value' => '123 South Street', diff --git a/tests/unit-tests/product/class-wc-tests-product-download.php b/tests/legacy/unit-tests/product/class-wc-tests-product-download.php similarity index 100% rename from tests/unit-tests/product/class-wc-tests-product-download.php rename to tests/legacy/unit-tests/product/class-wc-tests-product-download.php diff --git a/tests/unit-tests/product/data-store.php b/tests/legacy/unit-tests/product/data-store.php similarity index 100% rename from tests/unit-tests/product/data-store.php rename to tests/legacy/unit-tests/product/data-store.php diff --git a/tests/unit-tests/product/data.php b/tests/legacy/unit-tests/product/data.php similarity index 100% rename from tests/unit-tests/product/data.php rename to tests/legacy/unit-tests/product/data.php diff --git a/tests/unit-tests/product/factory.php b/tests/legacy/unit-tests/product/factory.php similarity index 100% rename from tests/unit-tests/product/factory.php rename to tests/legacy/unit-tests/product/factory.php diff --git a/tests/unit-tests/product/functions.php b/tests/legacy/unit-tests/product/functions.php similarity index 100% rename from tests/unit-tests/product/functions.php rename to tests/legacy/unit-tests/product/functions.php diff --git a/tests/unit-tests/product/product-simple.php b/tests/legacy/unit-tests/product/product-simple.php similarity index 100% rename from tests/unit-tests/product/product-simple.php rename to tests/legacy/unit-tests/product/product-simple.php diff --git a/tests/unit-tests/product/product-variable.php b/tests/legacy/unit-tests/product/product-variable.php similarity index 100% rename from tests/unit-tests/product/product-variable.php rename to tests/legacy/unit-tests/product/product-variable.php diff --git a/tests/unit-tests/product/product-variation.php b/tests/legacy/unit-tests/product/product-variation.php similarity index 100% rename from tests/unit-tests/product/product-variation.php rename to tests/legacy/unit-tests/product/product-variation.php diff --git a/tests/unit-tests/product/query.php b/tests/legacy/unit-tests/product/query.php similarity index 100% rename from tests/unit-tests/product/query.php rename to tests/legacy/unit-tests/product/query.php diff --git a/tests/unit-tests/queue/queue.php b/tests/legacy/unit-tests/queue/queue.php similarity index 100% rename from tests/unit-tests/queue/queue.php rename to tests/legacy/unit-tests/queue/queue.php diff --git a/tests/unit-tests/session/class-wc-tests-session-handler.php b/tests/legacy/unit-tests/session/class-wc-tests-session-handler.php similarity index 100% rename from tests/unit-tests/session/class-wc-tests-session-handler.php rename to tests/legacy/unit-tests/session/class-wc-tests-session-handler.php diff --git a/tests/unit-tests/settings/register-wp-admin-settings.php b/tests/legacy/unit-tests/settings/register-wp-admin-settings.php similarity index 100% rename from tests/unit-tests/settings/register-wp-admin-settings.php rename to tests/legacy/unit-tests/settings/register-wp-admin-settings.php diff --git a/tests/unit-tests/setup/functions.php b/tests/legacy/unit-tests/setup/functions.php similarity index 100% rename from tests/unit-tests/setup/functions.php rename to tests/legacy/unit-tests/setup/functions.php diff --git a/tests/unit-tests/shipping/shipping-zone.php b/tests/legacy/unit-tests/shipping/shipping-zone.php similarity index 100% rename from tests/unit-tests/shipping/shipping-zone.php rename to tests/legacy/unit-tests/shipping/shipping-zone.php diff --git a/tests/unit-tests/shipping/shipping-zones.php b/tests/legacy/unit-tests/shipping/shipping-zones.php similarity index 100% rename from tests/unit-tests/shipping/shipping-zones.php rename to tests/legacy/unit-tests/shipping/shipping-zones.php diff --git a/tests/unit-tests/shipping/shipping.php b/tests/legacy/unit-tests/shipping/shipping.php similarity index 100% rename from tests/unit-tests/shipping/shipping.php rename to tests/legacy/unit-tests/shipping/shipping.php diff --git a/tests/unit-tests/shortcodes/products.php b/tests/legacy/unit-tests/shortcodes/products.php similarity index 100% rename from tests/unit-tests/shortcodes/products.php rename to tests/legacy/unit-tests/shortcodes/products.php diff --git a/tests/unit-tests/tax/tax.php b/tests/legacy/unit-tests/tax/tax.php similarity index 100% rename from tests/unit-tests/tax/tax.php rename to tests/legacy/unit-tests/tax/tax.php diff --git a/tests/unit-tests/templates/functions.php b/tests/legacy/unit-tests/templates/functions.php similarity index 100% rename from tests/unit-tests/templates/functions.php rename to tests/legacy/unit-tests/templates/functions.php diff --git a/tests/unit-tests/totals/totals.php b/tests/legacy/unit-tests/totals/totals.php similarity index 100% rename from tests/unit-tests/totals/totals.php rename to tests/legacy/unit-tests/totals/totals.php diff --git a/tests/unit-tests/util/api-functions.php b/tests/legacy/unit-tests/util/api-functions.php similarity index 97% rename from tests/unit-tests/util/api-functions.php rename to tests/legacy/unit-tests/util/api-functions.php index bdd1ebf7653..3fb98c57b12 100644 --- a/tests/unit-tests/util/api-functions.php +++ b/tests/legacy/unit-tests/util/api-functions.php @@ -236,14 +236,14 @@ class WC_Tests_API_Functions extends WC_Unit_Test_Case { } elseif ( 'http://somedomain.com/invalid-image-2.png' === $url ) { // image with an unsupported mime type. // we need to manually copy the file as we are mocking the request. without this an empty file is created. - copy( WC_Unit_Tests_Bootstrap::instance()->tests_dir . '/data/file.txt', $request['filename'] ); + self::file_copy( WC_Unit_Tests_Bootstrap::instance()->tests_dir . '/data/file.txt', $request['filename'] ); $mocked_response = array( 'response' => array( 'code' => 200 ), ); } elseif ( 'http://somedomain.com/' . $this->file_name === $url ) { // we need to manually copy the file as we are mocking the request. without this an empty file is created. - copy( WC_Unit_Tests_Bootstrap::instance()->tests_dir . '/data/Dr1Bczxq4q.png', $request['filename'] ); + self::file_copy( WC_Unit_Tests_Bootstrap::instance()->tests_dir . '/data/Dr1Bczxq4q.png', $request['filename'] ); $mocked_response = array( 'response' => array( 'code' => 200 ), diff --git a/tests/unit-tests/util/class-wc-rate-limiter.php b/tests/legacy/unit-tests/util/class-wc-rate-limiter.php similarity index 100% rename from tests/unit-tests/util/class-wc-rate-limiter.php rename to tests/legacy/unit-tests/util/class-wc-rate-limiter.php diff --git a/tests/unit-tests/util/class-wc-tests-core-functions.php b/tests/legacy/unit-tests/util/class-wc-tests-core-functions.php similarity index 88% rename from tests/unit-tests/util/class-wc-tests-core-functions.php rename to tests/legacy/unit-tests/util/class-wc-tests-core-functions.php index 9482291d412..5db7b9dfec4 100644 --- a/tests/unit-tests/util/class-wc-tests-core-functions.php +++ b/tests/legacy/unit-tests/util/class-wc-tests-core-functions.php @@ -283,7 +283,7 @@ class WC_Tests_Core_Functions extends WC_Unit_Test_Case { public function test_wc_get_log_file_path() { $log_dir = trailingslashit( WC_LOG_DIR ); $hash_name = sanitize_file_name( wp_hash( 'unit-tests' ) ); - $date_suffix = date( 'Y-m-d', time() ); + $date_suffix = date( 'Y-m-d', time() ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date $this->assertEquals( $log_dir . 'unit-tests-' . $date_suffix . '-' . $hash_name . '.log', wc_get_log_file_path( 'unit-tests' ) ); } @@ -569,6 +569,81 @@ class WC_Tests_Core_Functions extends WC_Unit_Test_Case { $this->assertEmpty( wc_get_template_part( 'nothinghere' ) ); } + /** + * Tests the wc_tokenize_path function. + */ + public function test_wc_tokenize_path() { + $path = wc_tokenize_path( ABSPATH . 'test', array() ); + $this->assertEquals( ABSPATH . 'test', $path ); + + $path = wc_tokenize_path( + ABSPATH . 'test', + array( + 'ABSPATH' => ABSPATH, + ) + ); + $this->assertEquals( '{{ABSPATH}}test', $path ); + + $path = wc_tokenize_path( + ABSPATH . 'test', + array( + 'WP_CONTENT_DIR' => WP_CONTENT_DIR, + ) + ); + $this->assertEquals( ABSPATH . 'test', $path ); + + $path = wc_tokenize_path( + WP_CONTENT_DIR . 'test', + array( + 'ABSPATH' => ABSPATH, + 'WP_CONTENT_DIR' => WP_CONTENT_DIR, + ) + ); + $this->assertEquals( '{{WP_CONTENT_DIR}}test', $path ); + } + + /** + * Tests the wc_untokenize_path function. + */ + public function test_wc_untokenize_path() { + $path = wc_untokenize_path( '{{ABSPATH}}test', array() ); + $this->assertEquals( '{{ABSPATH}}test', $path ); + + $path = wc_untokenize_path( + '{{ABSPATH}}test', + array( + 'ABSPATH' => ABSPATH, + ) + ); + $this->assertEquals( ABSPATH . 'test', $path ); + + $path = wc_untokenize_path( + '{{ABSPATH}}test', + array( + 'WP_CONTENT_DIR' => WP_CONTENT_DIR, + ) + ); + $this->assertEquals( '{{ABSPATH}}test', $path ); + + $path = wc_untokenize_path( + '{{WP_CONTENT_DIR}}test', + array( + 'WP_CONTENT_DIR' => WP_CONTENT_DIR, + 'ABSPATH' => ABSPATH, + ) + ); + $this->assertEquals( WP_CONTENT_DIR . 'test', $path ); + } + + /** + * Tests the wc_get_path_define_tokens function. + */ + public function test_wc_get_path_define_tokens() { + $defines = wc_get_path_define_tokens(); + $this->assertArrayHasKey( 'ABSPATH', $defines ); + $this->assertEquals( ABSPATH, $defines['ABSPATH'] ); + } + /** * Test wc_get_template. * @@ -606,6 +681,28 @@ class WC_Tests_Core_Functions extends WC_Unit_Test_Case { $this->assertNotEmpty( $template ); } + /** + * This test ensures that the absolute path to template files is replaced with a token. We do this so + * that the path can be made relative to each installation, and the cache can be shared. + */ + public function test_wc_get_template_cleans_absolute_path() { + add_filter( 'woocommerce_locate_template', array( $this, 'force_template_path' ), 10, 2 ); + + ob_start(); + try { + wc_get_template( 'global/wrapper-start.php' ); + } catch ( \Exception $exception ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch + // Since the file doesn't really exist this is going to throw an exception (which is fine for our test). + } + ob_end_clean(); + + remove_filter( 'woocommerce_locate_template', array( $this, 'force_template_path' ) ); + + $file_path = wp_cache_get( sanitize_key( 'template-global/wrapper-start.php---' . WC_VERSION ), 'woocommerce' ); + + $this->assertEquals( '{{ABSPATH}}global/wrapper-start.php', $file_path ); + } + /** * Test wc_get_image_size function. * @@ -956,7 +1053,9 @@ class WC_Tests_Core_Functions extends WC_Unit_Test_Case { $this->assertInstanceOf( 'WC_Customer', $this->wc->customer ); $this->assertInstanceOf( 'WC_Session', $this->wc->session ); - $this->wc->cart = $this->wc->customer = $this->wc->session = null; + $this->wc->cart = null; + $this->wc->customer = null; + $this->wc->session = null; $this->assertNull( $this->wc->cart ); $this->assertNull( $this->wc->customer ); $this->assertNull( $this->wc->session ); @@ -967,4 +1066,16 @@ class WC_Tests_Core_Functions extends WC_Unit_Test_Case { $this->assertInstanceOf( 'WC_Session', $this->wc->session ); } + + /** + * Allows us to force the template path. Since the ABSPATH is to /tmp/wordpress in tests, we need to do this + * in order to keep the paths consistent for testing purposes. + * + * @param string $template The path to the template file. + * @param string $template_name The name of the template file. + * @return string The path to be used instead. + */ + public function force_template_path( $template, $template_name ) { + return ABSPATH . $template_name; + } } diff --git a/tests/unit-tests/util/class-wc-tests-user-functions.php b/tests/legacy/unit-tests/util/class-wc-tests-user-functions.php similarity index 100% rename from tests/unit-tests/util/class-wc-tests-user-functions.php rename to tests/legacy/unit-tests/util/class-wc-tests-user-functions.php diff --git a/tests/unit-tests/util/class-wc-tests-wc-query.php b/tests/legacy/unit-tests/util/class-wc-tests-wc-query.php similarity index 100% rename from tests/unit-tests/util/class-wc-tests-wc-query.php rename to tests/legacy/unit-tests/util/class-wc-tests-wc-query.php diff --git a/tests/unit-tests/util/conditional-functions.php b/tests/legacy/unit-tests/util/conditional-functions.php similarity index 100% rename from tests/unit-tests/util/conditional-functions.php rename to tests/legacy/unit-tests/util/conditional-functions.php diff --git a/tests/unit-tests/util/deprecated-hooks.php b/tests/legacy/unit-tests/util/deprecated-hooks.php similarity index 100% rename from tests/unit-tests/util/deprecated-hooks.php rename to tests/legacy/unit-tests/util/deprecated-hooks.php diff --git a/tests/unit-tests/util/dummy-wc-logger.php b/tests/legacy/unit-tests/util/dummy-wc-logger.php similarity index 100% rename from tests/unit-tests/util/dummy-wc-logger.php rename to tests/legacy/unit-tests/util/dummy-wc-logger.php diff --git a/tests/unit-tests/util/install.php b/tests/legacy/unit-tests/util/install.php similarity index 95% rename from tests/unit-tests/util/install.php rename to tests/legacy/unit-tests/util/install.php index 8e9835384e8..49e4112d3a5 100644 --- a/tests/unit-tests/util/install.php +++ b/tests/legacy/unit-tests/util/install.php @@ -38,6 +38,7 @@ class WC_Tests_Install extends WC_Unit_Test_Case { /** * Test - install. */ + /** public function test_install() { // clean existing install first. if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) { @@ -45,13 +46,15 @@ class WC_Tests_Install extends WC_Unit_Test_Case { define( 'WC_REMOVE_ALL_DATA', true ); } - include dirname( dirname( dirname( dirname( __FILE__ ) ) ) ) . '/uninstall.php'; + include dirname( dirname( dirname( dirname( dirname( __FILE__ ) ) ) ) ) . '/uninstall.php'; delete_transient( 'wc_installing' ); WC_Install::install(); $this->assertEquals( WC()->version, get_option( 'woocommerce_version' ) ); } + * + **/ /** * Test - create pages. @@ -99,7 +102,7 @@ class WC_Tests_Install extends WC_Unit_Test_Case { define( 'WP_UNINSTALL_PLUGIN', true ); define( 'WC_REMOVE_ALL_DATA', true ); } - include dirname( dirname( dirname( dirname( __FILE__ ) ) ) ) . '/uninstall.php'; + include dirname( dirname( dirname( dirname( dirname( __FILE__ ) ) ) ) ) . '/uninstall.php'; WC_Install::create_roles(); diff --git a/tests/unit-tests/util/notice-functions.php b/tests/legacy/unit-tests/util/notice-functions.php similarity index 100% rename from tests/unit-tests/util/notice-functions.php rename to tests/legacy/unit-tests/util/notice-functions.php diff --git a/tests/unit-tests/util/plugin-updates.php b/tests/legacy/unit-tests/util/plugin-updates.php similarity index 100% rename from tests/unit-tests/util/plugin-updates.php rename to tests/legacy/unit-tests/util/plugin-updates.php diff --git a/tests/unit-tests/util/validation.php b/tests/legacy/unit-tests/util/validation.php similarity index 100% rename from tests/unit-tests/util/validation.php rename to tests/legacy/unit-tests/util/validation.php diff --git a/tests/unit-tests/webhooks/crud.php b/tests/legacy/unit-tests/webhooks/crud.php similarity index 100% rename from tests/unit-tests/webhooks/crud.php rename to tests/legacy/unit-tests/webhooks/crud.php diff --git a/tests/unit-tests/webhooks/functions.php b/tests/legacy/unit-tests/webhooks/functions.php similarity index 100% rename from tests/unit-tests/webhooks/functions.php rename to tests/legacy/unit-tests/webhooks/functions.php diff --git a/tests/unit-tests/widgets/class-dummy-widget.php b/tests/legacy/unit-tests/widgets/class-dummy-widget.php similarity index 100% rename from tests/unit-tests/widgets/class-dummy-widget.php rename to tests/legacy/unit-tests/widgets/class-dummy-widget.php diff --git a/tests/unit-tests/widgets/class-wc-tests-widget.php b/tests/legacy/unit-tests/widgets/class-wc-tests-widget.php similarity index 100% rename from tests/unit-tests/widgets/class-wc-tests-widget.php rename to tests/legacy/unit-tests/widgets/class-wc-tests-widget.php diff --git a/tests/php/includes/WCInstallTest.php b/tests/php/includes/WCInstallTest.php new file mode 100644 index 00000000000..063edef6280 --- /dev/null +++ b/tests/php/includes/WCInstallTest.php @@ -0,0 +1,92 @@ +prefix}wc_tax_rate_classes"; + $changed_table_name = "{$wpdb->prefix}wc_tax_rate_classes_2"; + $clear_query = 'DROP TABLE IF EXISTS %s;'; + $rename_table_query = 'RENAME TABLE %s to %s;'; + + // Workaround to call a private function. + $schema = function () { + return static::get_schema(); + }; + + // Rename a base table to simulate it as non-existing. + dbDelta( $schema->call( new \WC_Install() ) ); // Restore correct state. + $wpdb->query( sprintf( $clear_query, $changed_table_name ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared + $wpdb->query( sprintf( $rename_table_query, $original_table_name, $changed_table_name ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared + + $missing_tables = \WC_Install::verify_base_tables(); + + $wpdb->query( sprintf( $rename_table_query, $changed_table_name, $original_table_name ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared + add_filter( 'query', array( $this, '_drop_temporary_tables' ) ); + + $this->assertContains( $original_table_name, $missing_tables ); + $this->assertContains( 'base_tables_missing', \WC_Admin_Notices::get_notices() ); + + // Ideally, no missing table anymore because we have switched back table name. + $missing_tables = \WC_Install::verify_base_tables(); + + $this->assertNotContains( $original_table_name, $missing_tables ); + $this->assertNotContains( 'base_tables_missing', \WC_Admin_Notices::get_notices() ); + } + + + /** + * Test if verify base table can fix the table as well. + */ + public function test_verify_base_tables_fix_tables() { + global $wpdb; + + // Remove drop filter because we do want to drop temp table if it exists. + // This filter was added to only allow dropping temporary tables which will then be rollbacked after the test. + remove_filter( 'query', array( $this, '_drop_temporary_tables' ) ); + + $original_table_name = "{$wpdb->prefix}wc_tax_rate_classes"; + $changed_table_name = "{$wpdb->prefix}wc_tax_rate_classes_2"; + $clear_query = 'DROP TABLE IF EXISTS %s;'; + $rename_table_query = 'RENAME TABLE %s to %s;'; + + // Workaround to call a private function. + $schema = function () { + return static::get_schema(); + }; + + // Rename a base table to simulate it as non-existing. + dbDelta( $schema->call( new \WC_Install() ) ); // Restore correct state. + $wpdb->query( sprintf( $clear_query, $changed_table_name ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared + $wpdb->query( sprintf( $rename_table_query, $original_table_name, $changed_table_name ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared + + $missing_tables = \WC_Install::verify_base_tables( true, true ); + + $wpdb->query( sprintf( $clear_query, $original_table_name ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared + $wpdb->query( sprintf( $rename_table_query, $changed_table_name, $original_table_name ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared + add_filter( 'query', array( $this, '_drop_temporary_tables' ) ); + + // Ideally, no missing table because verify base tables created the table as well. + $this->assertNotContains( $original_table_name, $missing_tables ); + $this->assertNotContains( 'base_tables_missing', \WC_Admin_Notices::get_notices() ); + } + +} diff --git a/tests/php/includes/abstracts/class-wc-abstract-order-test.php b/tests/php/includes/abstracts/class-wc-abstract-order-test.php new file mode 100644 index 00000000000..bcb04fa28b5 --- /dev/null +++ b/tests/php/includes/abstracts/class-wc-abstract-order-test.php @@ -0,0 +1,76 @@ + '', + 'tax_rate_state' => '', + 'tax_rate' => '15.0000', + 'tax_rate_name' => 'tax', + 'tax_rate_priority' => '1', + 'tax_rate_order' => '1', + ); + WC_Tax::_insert_tax_rate( $tax_rate ); + + $product1 = WC_Helper_Product::create_simple_product(); + $product1->set_regular_price( 99.48 ); + $product1->save(); + + $product2 = WC_Helper_Product::create_simple_product(); + $product2->set_regular_price( 108.68 ); + $product2->save(); + + $order = new WC_Order(); + $order->add_product( $product1, 6 ); + $order->add_product( $product2, 6 ); + $order->save(); + + $this->order_calculate_rounding_line( $order ); + $this->order_calculate_rounding_subtotal( $order ); + } + + /** + * Helper method to test rounding per line for `test_order_calculate_26582`. + * + * @param WC_Order $order Order object. + */ + private function order_calculate_rounding_line( $order ) { + update_option( 'woocommerce_tax_round_at_subtotal', 'no' ); + + $order->calculate_totals( true ); + + $this->assertEquals( 1086.06, $order->get_subtotal() ); + $this->assertEquals( 162.90, $order->get_total_tax() ); + $this->assertEquals( 1248.96, $order->get_total() ); + } + + /** + * Helper method to test rounding at subtotal for `test_order_calculate_26582`. + * + * @param WC_Order $order Order object. + */ + private function order_calculate_rounding_subtotal( $order ) { + update_option( 'woocommerce_tax_round_at_subtotal', 'yes' ); + + $order->calculate_totals( true ); + + $this->assertEquals( 1086.05, $order->get_subtotal() ); + $this->assertEquals( 162.91, $order->get_total_tax() ); + $this->assertEquals( 1248.96, $order->get_total() ); + } + +} diff --git a/tests/php/includes/admin/helper/class-wc-helper-test.php b/tests/php/includes/admin/helper/class-wc-helper-test.php new file mode 100644 index 00000000000..e181f1e365e --- /dev/null +++ b/tests/php/includes/admin/helper/class-wc-helper-test.php @@ -0,0 +1,38 @@ +tests_dir . '/data/sample-woo-plugin.php', WP_PLUGIN_DIR . '/sample-woo-plugin.php' ); + + add_filter( 'extra_plugin_headers', 'wc_enable_wc_plugin_headers' ); + + $woo_plugins = \WC_Helper::get_local_woo_plugins(); + + // Restore previous state. + wp_clean_plugins_cache( false ); + + $this->assertArrayHasKey( $woocommerce_key, $woo_plugins ); + } + +} diff --git a/tests/php/includes/admin/importers/class-wc-product-csv-importer-controller-test.php b/tests/php/includes/admin/importers/class-wc-product-csv-importer-controller-test.php new file mode 100644 index 00000000000..af046f38931 --- /dev/null +++ b/tests/php/includes/admin/importers/class-wc-product-csv-importer-controller-test.php @@ -0,0 +1,64 @@ +plugin_dir . '/includes/import/class-wc-product-csv-importer.php'; + require_once $bootstrap->plugin_dir . '/includes/admin/importers/class-wc-product-csv-importer-controller.php'; + } + + /** + * Tests that the automatic mapping is case insensitive so that columns can be matched more easily. + */ + public function test_that_auto_mapping_is_case_insensitive() { + // Allow us to call the protected method. + $class = new ReflectionClass( WC_Product_CSV_Importer_Controller::class ); + $method = $class->getMethod( 'auto_map_columns' ); + $method->setAccessible( true ); + + $controller = new WC_Product_CSV_Importer_Controller(); + + // Test a few different casing formats first. + $columns = $method->invoke( $controller, array( 'Name', 'Type' ) ); + $this->assertEquals( + array( + 0 => 'name', + 1 => 'type', + ), + $columns + ); + $columns = $method->invoke( $controller, array( 'NAME', 'tYpE' ) ); + $this->assertEquals( + array( + 0 => 'name', + 1 => 'type', + ), + $columns + ); + + // Make sure that the case sensitivity doesn't squash the meta keys. + $columns = $method->invoke( $controller, array( 'Meta: _TESTING', 'Meta: _testing' ) ); + $this->assertEquals( + array( + 0 => 'meta:_TESTING', + 1 => 'meta:_testing', + ), + $columns + ); + } +} diff --git a/tests/php/src/.gitkeep b/tests/php/src/.gitkeep new file mode 100644 index 00000000000..ff96249002a --- /dev/null +++ b/tests/php/src/.gitkeep @@ -0,0 +1 @@ +# Placeholder to include the folder. Remove once tests have been written! diff --git a/tests/unit-tests/helper/class-wc-helper-api.php b/tests/unit-tests/helper/class-wc-helper-api.php new file mode 100644 index 00000000000..d59711770a2 --- /dev/null +++ b/tests/unit-tests/helper/class-wc-helper-api.php @@ -0,0 +1,109 @@ +http_responder = array( $this, 'mock_http_responses' ); + } + + /** + * Test that the url method returns the correct WooCommerce.com path. + * + * @return void + */ + public function test_api_url() { + $url = WC_Helper_API::url( '/test-path' ); + $this->assertEquals( 'https://woocommerce.com/wp-json/helper/1.0/test-path', $url ); + } + + /** + * Test a GET request through the WC_Helper_API. + * + * @return void + */ + public function test_get_request() { + $request = WC_Helper_API::get( + 'test-get' + ); + + $this->assertEquals( '200', $request['response']['code'] ); + } + + /** + * Test a POST request through the WC_Helper_API. + * + * @return void + */ + public function test_post_request() { + $request = WC_Helper_API::post( + 'test-post' + ); + + $this->assertEquals( '200', $request['response']['code'] ); + } + + /** + * Test a PUT request through the WC_Helper_API. + * + * @return void + */ + public function test_put_request() { + $request = WC_Helper_API::put( + 'test-put' + ); + + $this->assertEquals( '200', $request['response']['code'] ); + } + + /** + * Provides a mocked response for various paths and request methods. + * + * This function is called by WP_HTTP_TestCase::http_request_listner(). + * + * @param array $request Request arguments. + * @param string $url URL of the request. + * + * @return array|false mocked response or false to let WP perform a regular request. + */ + protected function mock_http_responses( $request, $url ) { + $mocked_response = false; + + if ( 'GET' === $request['method'] && WC_Helper_API::url( 'test-get' ) === $url ) { + $mocked_response = array( + 'body' => 'Mocked response', + 'response' => array( 'code' => 200 ), + ); + } + + if ( 'POST' === $request['method'] && WC_Helper_API::url( 'test-post' ) === $url ) { + $mocked_response = array( + 'body' => 'Mocked response', + 'response' => array( 'code' => 200 ), + ); + } + + if ( 'PUT' === $request['method'] && WC_Helper_API::url( 'test-put' ) === $url ) { + $mocked_response = array( + 'body' => 'Mocked response', + 'response' => array( 'code' => 200 ), + ); + } + + return $mocked_response; + } + +} diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 00000000000..fc2c07c61de --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,9 @@ +const { webpackAlias: coreE2EAlias } = require( '@woocommerce/e2e-environment' ); + +module.exports = { + resolve: { + alias: { + ...coreE2EAlias, + }, + }, +}; diff --git a/woocommerce.php b/woocommerce.php index 7f394d7e637..47da64854ef 100644 --- a/woocommerce.php +++ b/woocommerce.php @@ -3,11 +3,13 @@ * Plugin Name: WooCommerce * Plugin URI: https://woocommerce.com/ * Description: An eCommerce toolkit that helps you sell anything. Beautifully. - * Version: 4.1.0 + * Version: 4.3.0-dev * Author: Automattic * Author URI: https://woocommerce.com * Text Domain: woocommerce * Domain Path: /i18n/languages/ + * Requires at least: 5.2 + * Requires PHP: 7.0 * * @package WooCommerce */

          +

          + +

          +
          : ' : ''; ?>