diff --git a/.eslintrc.normal.js b/.eslintrc.normal.js index ea55de2a3cdf3..5768fca228ddf 100644 --- a/.eslintrc.normal.js +++ b/.eslintrc.normal.js @@ -125,7 +125,7 @@ module.exports = { // JSDoc plugin overrides 'jsdoc/check-alignment': 1, // Recommended - 'jsdoc/check-examples': 1, + 'jsdoc/check-examples': 0, // See https://github.com/eslint/eslint/issues/14745 'jsdoc/check-indentation': 1, 'jsdoc/check-param-names': 1, // Recommended 'jsdoc/check-syntax': 1, diff --git a/.github/files/build-all-projects.sh b/.github/files/build-all-projects.sh index 51aa0f84d82b1..e1c365ec80933 100755 --- a/.github/files/build-all-projects.sh +++ b/.github/files/build-all-projects.sh @@ -30,7 +30,7 @@ echo "::group::Changelogger setup" echo "::endgroup::" echo "::group::Determining build order" -TMP="$(tools/get-build-order.php)" +TMP="$(pnpx jetpack dependencies build-order --pretty --ignore-root)" SLUGS=() mapfile -t SLUGS <<<"$TMP" echo "::endgroup::" @@ -79,7 +79,7 @@ for SLUG in "${SLUGS[@]}"; do OLDLOCK= fi fi - if (cd $BASE && pnpx jetpack build "${SLUG}" -v --production); then + if (cd $BASE && pnpx jetpack build "${SLUG}" -v --production --timing --no-pnpm-install); then FAIL=false else FAIL=true @@ -190,7 +190,7 @@ for SLUG in "${SLUGS[@]}"; do # Copy the resulting list of files into the clone. xargs cp --parents --target-directory="$BUILD_DIR" - if [[ "$SLUG" == "plugins/jetpack" ]]; then + if [[ "$SLUG" == "plugins/jetpack" || "$SLUG" == "plugins/backup" ]]; then echo "::group::Copying Jetpack files for backward compatibility." OLD_VENDOR_DIR="$BUILD_DIR/vendor" diff --git a/.github/files/create-e2e-projects-matrix.sh b/.github/files/create-e2e-projects-matrix.sh new file mode 100755 index 0000000000000..43706bfd34fc6 --- /dev/null +++ b/.github/files/create-e2e-projects-matrix.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +set -eo pipefail + +PROJECTS=('{"project":"Jetpack","path":"projects/plugins/jetpack/tests/e2e","testArgs":[],"slackArgs":[]}' '{"project":"Boost","path":"projects/plugins/boost/tests/e2e","testArgs":[],"slackArgs":[]}') +PROJECTS_MATRIX=() +RUN_NAME='' + +if [[ "$GITHUB_EVENT_NAME" == "pull_request" || "$GITHUB_EVENT_NAME" == "push" ]]; then + CHANGED_PROJECTS="$(.github/files/list-changed-projects.sh)" + + for PROJECT in "${PROJECTS[@]}"; do + PROJECT_PATH=$(jq -r ".path" <<<"$PROJECT") + TARGETS=$(jq -r -e ".ci.targets" "$PROJECT_PATH/package.json") + + if [[ "$TARGETS" == "[]" || "$TARGETS" == "" ]]; then + # if no target projects are found run the tests + PROJECTS_MATRIX+=("$PROJECT") + else + # iterate over defined target plugins/projects and see if they are changed + for TARGET in $(jq -r -e ".[]" <<<"$TARGETS"); do + RESULT=$(jq --arg prj "$TARGET" '.[$prj]' <<<"$CHANGED_PROJECTS") + if [[ "$RESULT" == true ]]; then + PROJECTS_MATRIX+=("$PROJECT") + break + fi + done + fi + done +else + # gutenberg scheduled run + if [ "$CRON" == "0 */12 * * *" ]; then + PROJECTS_MATRIX+=('{"project":"Jetpack with Gutenberg","path":"projects/plugins/jetpack/tests/e2e","testArgs":["blocks"],"slackArgs":["--report", "gutenberg"]}') + RUN_NAME='gutenberg' + fi + + # atomic scheduled run + if [ "$CRON" == "30 */4 * * *" ]; then + PROJECTS_MATRIX+=('{"project":"Jetpack on Atomic","path":"projects/plugins/jetpack/tests/e2e","testArgs":["blocks", "--grep-invert", "wordads"],"slackArgs":["--report", "atomic"]}') + RUN_NAME='atomic' + fi +fi + +jq -n -c --arg runName "$RUN_NAME" --argjson projects "$(jq -s -c -r '.' <<<"${PROJECTS_MATRIX[@]}")" '{ "run": $runName, "matrix": $projects }' diff --git a/.github/files/generate-ci-matrix.php b/.github/files/generate-ci-matrix.php index d852c39f0c0f8..85336222ab802 100755 --- a/.github/files/generate-ci-matrix.php +++ b/.github/files/generate-ci-matrix.php @@ -58,7 +58,7 @@ 'script' => 'test-php', 'php' => $php, 'wp' => 'latest', - 'timeout' => 15, // 2021-01-18: Successful runs seem to take ~8 minutes for PHP 5.6 and for the 7.4 master run, ~5.5-6 for 7.x and 8.0. + 'timeout' => 20, // 2022-01-25: 5.6 tests have started timing out at 15 minutes. Previously: Successful runs seem to take ~8 minutes for PHP 5.6 and for the 7.4 master run, ~5.5-6 for 7.x and 8.0. ); } // Merge this into the above once we decide PHP 8.1 is stable and WP latest works with 8.1. diff --git a/.github/files/list-changed-projects.php b/.github/files/list-changed-projects.php deleted file mode 100755 index 99ebdad8366d8..0000000000000 --- a/.github/files/list-changed-projects.php +++ /dev/null @@ -1,216 +0,0 @@ -#!/usr/bin/env php -pull_request->base->sha ) || ! isset( $event->pull_request->head->sha ) ) { - fprintf( STDERR, "Missing pull_request data in GITHUB_EVENT_PATH file\n" ); - exit( 1 ); - } - $base = $event->pull_request->base->sha; - $head = $event->pull_request->head->sha; - debug( 'GITHUB_EVENT_NAME is pull_request, checking diff from %s...%s.', $base, $head ); - } elseif ( 'push' === $event ) { - debug( 'GITHUB_EVENT_NAME is push, considering all projects changed.' ); - return get_all_projects(); - } else { - fprintf( STDERR, "Unsupported GITHUB_EVENT_NAME \"%s\"\n", $event ); - exit( 1 ); - } - - $pipes = null; - $p = proc_open( - sprintf( 'git -c core.quotepath=off diff --no-renames --name-only %s...%s', escapeshellarg( $base ), escapeshellarg( $head ) ), - array( array( 'pipe', 'r' ), array( 'pipe', 'w' ), STDERR ), - $pipes - ); - if ( ! $p ) { - exit( 1 ); - } - fclose( $pipes[0] ); - - // PHP doesn't seem to have something that'll correctly handle `**`, so munge to a regex. - $ignore_regexes = array(); - foreach ( $ignore_globs as $glob ) { - $re = '!^'; - for ( $i = 0, $l = strlen( $glob ); $i < $l; $i++ ) { - $c = $glob[ $i ]; - switch ( $c ) { - case '\\': - $re .= preg_quote( $glob[ ++$i ], '!' ); - break; - case '*': - if ( '*' === $glob[ $i + 1 ] ) { - $i++; - $re .= '.*'; - } else { - $re .= '[^/]*'; - } - break; - case '?': - $re .= '[^/]'; - break; - default: - $re .= preg_quote( $c, '!' ); - break; - } - } - $re .= '$!'; - $ignore_regexes[ $glob ] = $re; - } - - $projects = array(); - // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition - while ( ( $line = fgets( $pipes[1] ) ) ) { - $line = trim( $line ); - if ( in_array( $line, $infrastructure_files, true ) ) { - debug( 'PR touches infrastructure file %s, considering all projects changed.', $line ); - return get_all_projects(); - } - foreach ( $ignore_regexes as $glob => $re ) { - if ( preg_match( $re, $line ) ) { - debug( 'PR touches file %s, but ignoring due to match with `%s`.', $line, $glob ); - continue 2; - } - } - $parts = explode( '/', $line, 4 ); - if ( count( $parts ) === 4 && 'projects' === $parts[0] ) { - $slug = "{$parts[1]}/{$parts[2]}"; - } else { - $slug = 'monorepo'; - } - if ( empty( $projects[ $slug ] ) ) { - debug( 'PR touches file %s, marking %s as changed.', $line, $slug ); - $projects[ $slug ] = true; - } - } - fclose( $pipes[1] ); - - $status = proc_close( $p ); - if ( $status ) { - exit( $status ); - } - - ksort( $projects ); - return array_keys( $projects ); -} - -// Get a list of projects indicating which are changed. -$projects = array_fill_keys( get_changed_projects(), true ) + array_fill_keys( get_all_projects(), false ); - -// Figure out if any projects depend on a changed project. Repeat to propagate until none are found. -$deps = get_dependencies(); -do { - $any = false; - foreach ( $projects as $project => $changed ) { - if ( $changed || ! isset( $deps[ $project ] ) ) { - continue; - } - foreach ( $deps[ $project ] as $slug ) { - if ( ! empty( $projects[ $slug ] ) ) { - debug( 'Project %s depends on %s, marking it as changed.', $project, $slug ); - $projects[ $project ] = true; - $any = true; - break; - } - } - } -} while ( $any ); - -// Output. -ksort( $projects ); -echo json_encode( $projects, JSON_FORCE_OBJECT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) . "\n"; diff --git a/.github/files/list-changed-projects.sh b/.github/files/list-changed-projects.sh new file mode 100755 index 0000000000000..62f5236a2d97f --- /dev/null +++ b/.github/files/list-changed-projects.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +set -eo pipefail + +cd $(dirname "${BASH_SOURCE[0]}")/../.. + +. tools/includes/chalk-lite.sh + +function debug { + blue "$@" >&2 +} + +function die { + echo "::error::$*" >&2 + exit 1 +} + +ARGS=( --add-dependents ) + +# Code coverage probably needs to run all tests to avoid confusing metrics. +# @todo Switch it to use codecov.io's carryforward: https://about.codecov.io/blog/new-product-test-only-what-you-change-with-carryforward-flags/ +if [[ "$TEST_SCRIPT" == "test-coverage" ]]; then + debug "TEST_SCRIPT is test-coverage, considering all projects changed." +elif [[ "${GITHUB_EVENT_NAME:?}" == "pull_request" ]]; then + [[ -f "${GITHUB_EVENT_PATH:?}" ]] || die "GITHUB_EVENT_PATH file $GITHUB_EVENT_PATH does not exist" + DIFF="$(jq -r '"\( .pull_request.base.sha )..\( .pull_request.head.sha )"' "$GITHUB_EVENT_PATH")" + debug "GITHUB_EVENT_NAME is pull_request, checking diff from $DIFF" + ARGS+=( --verbose "--git-changed=$DIFF" ) +elif [[ "${GITHUB_EVENT_NAME:?}" == "push" ]]; then + debug "GITHUB_EVENT_NAME is push, considering all projects changed." +else + die "Unsupported GITHUB_EVENT_NAME \"$GITHUB_EVENT_NAME\"" +fi + +pnpx jetpack dependencies list "${ARGS[@]}" | jq -ncR 'reduce inputs as $i ({}; .[$i] |= true)' diff --git a/.github/files/required-review.yaml b/.github/files/required-review.yaml index 961f2a1b239fa..2137cf8c28b3f 100644 --- a/.github/files/required-review.yaml +++ b/.github/files/required-review.yaml @@ -22,6 +22,8 @@ paths: - 'projects/packages/**' - 'projects/plugins/jetpack/**' + # Exclude packages managed by other teams, which are covered by other blocks below. + - '!projects/packages/search/**' teams: - jetpack-approvers @@ -44,10 +46,11 @@ - heart-of-gold - jetpack-approvers -# The Search team reviews changes to the Search plugin +# The Search team reviews changes to the Search plugin, and the Search package. - name: Search paths: - 'projects/plugins/search/**' + - 'projects/packages/search/**' teams: - jetpack-search - jetpack-approvers diff --git a/.github/files/setup-wordpress-env.sh b/.github/files/setup-wordpress-env.sh index 2caa7692c58b5..d98076fd31a8d 100755 --- a/.github/files/setup-wordpress-env.sh +++ b/.github/files/setup-wordpress-env.sh @@ -35,12 +35,6 @@ case "$WP_BRANCH" in ;; latest) LATEST=$(php ./tools/get-wp-version.php) - # 5.8.x still requires a monkey-patched obsolete version of phpunit. - # If that's latest, run the coverage test with the upcoming 5.9 instead. - # @todo: Remove this once WordPress 5.9 is "latest". - if [[ "$LATEST" == 5.8.* && "$TEST_SCRIPT" == "test-coverage" ]]; then - LATEST=master - fi git clone --depth=1 --branch "$LATEST" git://develop.git.wordpress.org/ /tmp/wordpress-latest ;; previous) diff --git a/.github/renovate.json b/.github/renovate.json index ab8845b0e46dc..18d7f6454df30 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -24,6 +24,7 @@ "@automattic/jetpack-idc", "@automattic/jetpack-licensing", "@automattic/jetpack-partner-coupon", + "@automattic/jetpack-shared-extension-utils", "@automattic/jetpack-storybook", "@automattic/jetpack-webpack-config", "@automattic/remove-asset-webpack-plugin", @@ -57,14 +58,18 @@ "automattic/jetpack-partner", "automattic/jetpack-password-checker", "automattic/jetpack-phpcs-filter", + "automattic/jetpack-plans", + "automattic/jetpack-plugins-installer", "automattic/jetpack-post-list", + "automattic/jetpack-publicize", "automattic/jetpack-redirect", "automattic/jetpack-roles", "automattic/jetpack-search", "automattic/jetpack-status", "automattic/jetpack-sync", "automattic/jetpack-terms-of-service", - "automattic/jetpack-tracking" + "automattic/jetpack-tracking", + "automattic/jetpack-waf" ], "enabled": false }, diff --git a/.github/workflows/e2e-tests-atomic.yml b/.github/workflows/e2e-tests-atomic.yml deleted file mode 100644 index b9498e9c372e8..0000000000000 --- a/.github/workflows/e2e-tests-atomic.yml +++ /dev/null @@ -1,90 +0,0 @@ -name: Jetpack E2E Tests on Atomic sites - -on: - schedule: - - cron: '0 */4 * * *' - -jobs: - e2e-tests: - name: "E2E tests" - runs-on: ubuntu-latest - timeout-minutes: 25 - env: - TEST_SITE: atomic - - steps: - - uses: actions/checkout@v2 - - - name: Setup tools - uses: ./.github/actions/tool-setup - with: - php: false - - - name: Install - working-directory: projects/plugins/jetpack/tests/e2e - env: - CONFIG_KEY: ${{ secrets.E2E_CONFIG_KEY }} - run: | - pnpm install - pnpm run test-decrypt-all-config - - - name: Run tests - working-directory: projects/plugins/jetpack/tests/e2e - run: pnpm run test-e2e -- blocks --grep-invert wordads - - - name: Upload test artifacts - if: ${{ always() }} - continue-on-error: true - uses: actions/upload-artifact@v2 - with: - name: test-output-${{ matrix.group }} - path: projects/plugins/jetpack/tests/e2e/output - - - name: Send Slack notification - if: ${{ failure() }} - env: - GITHUB_CONTEXT: ${{ toJson(github) }} - working-directory: projects/plugins/jetpack/tests/e2e - run: pnpm slack -- suite atomic --report atomic - - slack-notification: - name: "Slack notification" - runs-on: ubuntu-latest - needs: e2e-tests - env: - CONFIG_KEY: ${{ secrets.E2E_CONFIG_KEY }} - GITHUB_CONTEXT: ${{ toJson(github) }} - TEST_SITE: atomic - - steps: - - uses: actions/checkout@v2 - - - name: Setup tools - uses: ./.github/actions/tool-setup - with: - php: false - - - name: Send Slack notification - working-directory: projects/plugins/jetpack/tests/e2e - env: - RESULT: ${{ needs.e2e-tests.result }} - run: | - pnpm install - pnpm run test-decrypt-all-config - pnpm slack -- status $RESULT --report atomic - - test-reports: - name: "Trigger test report workflow" - runs-on: ubuntu-latest - if: ${{ ! cancelled() }} - needs: e2e-tests - - steps: - - uses: actions/checkout@v2 - - - name: Trigger test report workflow - uses: ./.github/actions/test-report-dispatch - with: - token: ${{ secrets.E2E_TEST_REPORTS_TOKEN }} - event_type: e2e - report_name: atomic diff --git a/.github/workflows/e2e-tests-boost.yml b/.github/workflows/e2e-tests-boost.yml deleted file mode 100644 index 5e6029d85e601..0000000000000 --- a/.github/workflows/e2e-tests-boost.yml +++ /dev/null @@ -1,124 +0,0 @@ -name: Jetpack Boost E2E Tests - -on: - pull_request: - push: - branches: [ master ] -concurrency: - group: e2e-tests-boost-${{ github.event_name }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - check: - name: "Check if Boost E2E tests should run" - runs-on: ubuntu-latest - timeout-minutes: 1 # 2021-11-12: Should only take a second. - outputs: - boost: ${{ steps.check.outputs.boost }} - steps: - - uses: actions/checkout@v2 - # For pull requests, list-changed-projects.php needs the merge base. - - name: Deepen to merge base - if: github.event_name == 'pull_request' - uses: ./.github/actions/deepen-to-merge-base - - id: check - run: | - CHANGED="$(.github/files/list-changed-projects.php --debug)" - BOOST="$(jq '.["plugins/boost"]' <<<"$CHANGED")" - echo "::set-output name=boost::${BOOST}" - - e2e-tests: - name: "Boost E2E tests" - runs-on: ubuntu-latest - timeout-minutes: 25 - needs: check - if: needs.check.outputs.boost == 'true' - - steps: - - uses: actions/checkout@v2 - - - name: Setup tools - uses: ./.github/actions/tool-setup - - - name: Build Production Jetpack & Jetpack Boost - run: | - pnpm install - pnpx jetpack build plugins/jetpack -v --production - pnpx jetpack build plugins/boost -v --production - - - name: Environment set-up - working-directory: projects/plugins/boost/tests/e2e - env: - CONFIG_KEY: ${{ secrets.E2E_CONFIG_KEY }} - run: | - pnpm install - pnpm run test-decrypt-config - pnpm run env-start - pnpm run tunnel-on - - - name: Run tests - working-directory: projects/plugins/boost/tests/e2e - run: pnpm run test-e2e - - - name: Environment tear-down - if: ${{ always() }} - working-directory: projects/plugins/boost/tests/e2e - continue-on-error: true - run: | - pnpm run tunnel-off - pnpm run tunnel-write-logs - - - name: Upload test artifacts - if: ${{ always() }} - continue-on-error: true - uses: actions/upload-artifact@v2 - with: - name: test-output-boost - path: projects/plugins/boost/tests/e2e/output - - - name: Send Slack notification - if: ${{ failure() }} - env: - GITHUB_CONTEXT: ${{ toJson(github) }} - working-directory: projects/plugins/boost/tests/e2e - run: pnpm slack -- suite boost - - slack-notification: - name: "Slack notification" - runs-on: ubuntu-latest - needs: e2e-tests - env: - CONFIG_KEY: ${{ secrets.E2E_CONFIG_KEY }} - GITHUB_CONTEXT: ${{ toJson(github) }} - - steps: - - uses: actions/checkout@v2 - - - name: Setup tools - uses: ./.github/actions/tool-setup - with: - php: false - - - name: Send Slack notification - working-directory: projects/plugins/boost/tests/e2e - env: - RESULT: ${{ needs.e2e-tests.result }} - run: | - pnpm install - pnpm run test-decrypt-config - pnpm slack -- status $RESULT - - test-reports: - name: "Trigger test report workflow" - runs-on: ubuntu-latest - needs: e2e-tests - if: ${{ ! cancelled() && needs.e2e-tests.result != 'skipped' }} - - steps: - - uses: actions/checkout@v2 - - - name: Trigger test report workflow - uses: ./.github/actions/test-report-dispatch - with: - token: ${{ secrets.E2E_TEST_REPORTS_TOKEN }} - event_type: e2e diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index d4339d9e6f355..9de4ab34c233b 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -1,4 +1,4 @@ -name: Jetpack E2E Tests +name: E2E Tests on: pull_request: @@ -9,42 +9,62 @@ on: paths-ignore: - '**.md' schedule: - - cron: '0 */12 * * *' + - cron: '0 */12 * * *' # gutenberg run, every 12 hours - if you update this, also update it in .github/files/create-e2e-projects-matrix.sh + - cron: '30 */4 * * *' # atomic run, every 4 hours - if you update this, also update it in .github/files/create-e2e-projects-matrix.sh + concurrency: group: e2e-tests-${{ github.event_name }}-${{ github.ref }} cancel-in-progress: true jobs: - create-matrix: + create-test-matrix: name: "Determine tests matrix" runs-on: ubuntu-latest - timeout-minutes: 1 # 2021-02-03: Should only take a second. + timeout-minutes: 3 outputs: - matrix: ${{ steps.create-matrix.outputs.matrix }} + matrix: ${{ steps.evaluate.outputs.matrix }} + runName: ${{ steps.evaluate.outputs.runName }} steps: - uses: actions/checkout@v2 - - id: create-matrix + + # For pull requests, list-changed-projects.sh needs the merge base. + - name: Deepen to merge base + if: github.event_name == 'pull_request' + uses: ./.github/actions/deepen-to-merge-base + + - name: Setup tools + uses: ./.github/actions/tool-setup + + # Required for list-changed-projects.sh + - name: Install monorepo run: | - MATRIX='[{"group":"pre-connection","tests":"specs/pre-connection"},{"group":"connection","tests":"specs/connection"},{"group":"post-connection","tests":"specs/post-connection"}]' - if [ "$GITHUB_EVENT_NAME" == schedule ]; then - MATRIX=$(echo $MATRIX | jq '. + [{"group": "gutenberg","tests": "blocks"}]' | jq -c .) - fi - echo $MATRIX + pnpm install + + - name: Create test plan + id: evaluate + env: + CRON: ${{ github.event.schedule }} + run: | + TEST_PLAN="$(.github/files/create-e2e-projects-matrix.sh)" + echo "$TEST_PLAN" + + MATRIX=$(jq -r -c ".matrix" <<<"$TEST_PLAN") + echo "$MATRIX" echo "::set-output name=matrix::$MATRIX" + RUN_NAME=$(jq -r -c ".run" <<<"$TEST_PLAN") + echo "$RUN_NAME" + echo "::set-output name=runName::$RUN_NAME" + e2e-tests: - name: "E2E ${{ matrix.group }} tests" + name: "${{ matrix.project }} e2e tests" runs-on: ubuntu-latest - needs: create-matrix - timeout-minutes: 25 # 2021-04-16: Successful runs seem to take 11-17 minutes + needs: create-test-matrix + timeout-minutes: 25 strategy: fail-fast: false matrix: - include: ${{ fromJson( needs.create-matrix.outputs.matrix ) }} - env: - GROUP: ${{ matrix.group }} - TESTS: ${{ matrix.tests }} - GUTENBERG: bundle # default value. Can be overridden later based on matrix.group value + include: ${{ fromJson( needs.create-test-matrix.outputs.matrix ) }} if: github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name steps: @@ -53,86 +73,86 @@ jobs: - name: Setup tools uses: ./.github/actions/tool-setup - - name: Build Production Jetpack - env: - COMPOSER_ROOT_VERSION: "dev-master" + - name: Install monorepo run: | pnpm install - pnpx jetpack build packages/search -v --production - pnpx jetpack build plugins/jetpack -v --production - - name: Environment set-up - working-directory: projects/plugins/jetpack/tests/e2e + - name: Test environment set-up + working-directory: ${{ matrix.path }} env: CONFIG_KEY: ${{ secrets.E2E_CONFIG_KEY }} + COMPOSER_ROOT_VERSION: "dev-master" + RUN_NAME: ${{ needs.create-test-matrix.outputs.runName }} run: | + echo "::group::Install e2e project" pnpm install - pnpm run test-decrypt-all-config - pnpm run env-start - pnpm run tunnel-on - - - name: Set up Gutenberg - if: matrix.group == 'gutenberg' - working-directory: projects/plugins/jetpack/tests/e2e - run: pnpx e2e-env gb-setup + echo "::endgroup::" + + echo "::group::Decrypt config" + pnpm run config:decrypt + echo "::endgroup::" + + if [ "${RUN_NAME}" != atomic ]; then + echo "::group::Build plugin(s)" + pnpm run build + echo "::endgroup::" + + echo "::group::Start docker environment" + pnpm run env:up + echo "::endgroup::" + + echo "::group::Create tunnel" + pnpm run tunnel:up + echo "::endgroup::" + else + echo "TEST_SITE=atomic" >> $GITHUB_ENV + fi + + if [ "${RUN_NAME}" == gutenberg ]; then + echo "::group::Setting up Gutenberg" + pnpx e2e-env gb-setup + echo "::endgroup::" + fi + + - name: Run ${{ matrix.project }} tests + working-directory: ${{ matrix.path }} + env: + JSON_ARGS: ${{ toJSON(matrix.testArgs) }} + run: | + mapfile -t TEST_ARGS < <(jq -r '.[]' <<<"$JSON_ARGS") + pnpm run test:run -- "${TEST_ARGS[@]}" - - name: Run ${{ matrix.group }} tests - working-directory: projects/plugins/jetpack/tests/e2e - run: pnpm run test-e2e -- $TESTS + - name: Send Slack notification + if: ${{ ! cancelled() }} + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + SUITE: ${{ matrix.project }} + JSON_ARGS: ${{ toJSON(matrix.slackArgs) }} + working-directory: ${{ matrix.path }} + run: | + mapfile -t ARGS < <(jq -r '.[]' <<<"$JSON_ARGS") + pnpm run slack -- suite $SUITE "${ARGS[@]}" - - name: Environment tear-down + - name: Test environment tear-down if: ${{ always() }} - working-directory: projects/plugins/jetpack/tests/e2e + working-directory: ${{ matrix.path }} continue-on-error: true run: | - pnpm run tunnel-off - pnpm run tunnel-write-logs + pnpm run tunnel:down - name: Upload test artifacts if: ${{ always() }} continue-on-error: true uses: actions/upload-artifact@v2 with: - name: test-output-${{ matrix.group }} - path: projects/plugins/jetpack/tests/e2e/output - - - name: Send Slack notification - if: ${{ failure() }} - env: - GITHUB_CONTEXT: ${{ toJson(github) }} - working-directory: projects/plugins/jetpack/tests/e2e - run: pnpm slack -- suite $GROUP - - slack-notification: - name: "Slack notification" - runs-on: ubuntu-latest - needs: e2e-tests - env: - CONFIG_KEY: ${{ secrets.E2E_CONFIG_KEY }} - GITHUB_CONTEXT: ${{ toJson(github) }} - - steps: - - uses: actions/checkout@v2 + name: test-output-${{ matrix.project }} + path: ${{ matrix.path }}/output - - name: Setup tools - uses: ./.github/actions/tool-setup - with: - php: false - - - name: Send Slack notification - working-directory: projects/plugins/jetpack/tests/e2e - env: - RESULT: ${{ needs.e2e-tests.result }} - run: | - pnpm install - pnpm run test-decrypt-all-config - pnpm slack -- status $RESULT - - test-reports: - name: "Trigger test report workflow" + test-report: + name: "Test report" runs-on: ubuntu-latest if: ${{ ! cancelled() }} - needs: e2e-tests + needs: [create-test-matrix, e2e-tests] steps: - uses: actions/checkout@v2 @@ -142,3 +162,6 @@ jobs: with: token: ${{ secrets.E2E_TEST_REPORTS_TOKEN }} event_type: e2e + report_name: ${{needs.create-test-matrix.outputs.runName}} + + diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 3091acd21336a..f1968e3230427 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -484,10 +484,10 @@ jobs: timeout-minutes: 1 # 2021-01-18: Successful runs take just a few seconds steps: - uses: actions/checkout@v2 - - name: Tool versions - run: | - which jq - jq --version + - name: Setup tools + uses: ./.github/actions/tool-setup + with: + php: false - run: tools/check-intra-monorepo-deps.sh -v - run: .github/files/check-monorepo-package-repos.sh diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 423e291979843..c3d402fd2f319 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -22,7 +22,7 @@ jobs: days-before-pr-stale: 90 # Issues and PRs with these labels will never be considered stale. exempt-issue-labels: '[Pri] High,[Pri] BLOCKER,[Type] Good For Community,[Type] Good First Bug,FixTheFlows' - exempt-pr-labels: '[Pri] High,[Pri] BLOCKER,[Type] Good For Community,[Type] Good First Bug,FixTheFlows' + exempt-pr-labels: '[Pri] High,[Pri] BLOCKER,FixTheFlows' # Label to use when marking an issue / PR as stale stale-pr-label: '[Status] Stale' stale-issue-label: '[Status] Stale' @@ -51,4 +51,3 @@ jobs: testing instructions, is it up to date with master, and it is still valid. Feel free to close this PR if you think it's not valid anymore — if you do, please add a brief explanation.

- operations-per-run: 2 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 942418e97d733..96ac6bd72013d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -56,7 +56,7 @@ jobs: # codecov.io requires a fetch depth > 1. fetch-depth: 2 - # For pull requests, list-changed-projects.php needs the merge base. + # For pull requests, list-changed-projects.sh needs the merge base. # But it doesn't have to be checked out, and codecov.io requires it not be. - name: Deepen to merge base if: github.event_name == 'pull_request' @@ -71,10 +71,16 @@ jobs: coverage: ${{ matrix.script == 'test-coverage' && 'pcov' || 'none' }} node: ${{ matrix.node }} + - name: Monorepo install + run: | + echo "::group::Pnpm" + pnpm install + echo "::endgroup::" + - name: Detect changed projects id: changed run: | - CHANGED="$(.github/files/list-changed-projects.php --debug)" + CHANGED="$(.github/files/list-changed-projects.sh)" ANY_PLUGINS="$(jq --argjson changed "$CHANGED" -n '$changed | with_entries( select( .key | startswith( "plugins/" ) ) ) | any')" echo "::set-output name=projects::${CHANGED}" echo "::set-output name=any-plugins::${ANY_PLUGINS}" @@ -83,12 +89,6 @@ jobs: if: steps.changed.outputs.any-plugins == 'true' && matrix.wp != 'none' run: .github/files/setup-wordpress-env.sh - - name: Monorepo install - run: | - echo "::group::Pnpm" - pnpm install - echo "::endgroup::" - - name: Run project tests env: EXPERIMENTAL: ${{ matrix.experimental && 'true' || 'false' }} diff --git a/.gitignore b/.gitignore index bd9ce9ca8cba6..9f74bee2f5693 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ jetpack_vendor/ /tools/docker/compose-extras.built.yml /tools/docker/compose-mappings.built.yml /tools/docker/jetpack-docker-config.yml +/tools/phpcs.log # File for personal customiziations, if desired. /tools/docker/mu-plugins/0-sandbox.php diff --git a/.phpcs.xml.dist b/.phpcs.xml.dist index 3f2fd388a97ef..4e8fd21d0086e 100644 --- a/.phpcs.xml.dist +++ b/.phpcs.xml.dist @@ -7,11 +7,6 @@ - - - /projects/plugins/jetpack/extensions/blocks/podcast-player/templates/* - - diff --git a/composer.json b/composer.json index 2763df5427592..39c1a5b4317ab 100644 --- a/composer.json +++ b/composer.json @@ -8,12 +8,13 @@ "issues": "https://github.com/Automattic/jetpack/issues" }, "require-dev": { - "automattic/jetpack-codesniffer": "2.4.x-dev", + "automattic/jetpack-codesniffer": "2.5.x-dev", "automattic/jetpack-phpcs-filter": "1.0.x-dev", "dealerdirect/phpcodesniffer-composer-installer": "0.7.1", "php-parallel-lint/php-parallel-lint": "1.3.1", "sirbrillig/phpcs-changed": "2.8.1", - "squizlabs/php_codesniffer": "3.6.1" + "squizlabs/php_codesniffer": "3.6.1", + "wp-coding-standards/wpcs": "dev-develop as 2.3.1" }, "scripts": { "php:lint": [ diff --git a/composer.lock b/composer.lock index a8d7145a4fe4b..d2bf2a12ccb01 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "cfc3d18e703804b5510c6cdf0f022874", + "content-hash": "df73dd15564af4a919363b27f59c7c35", "packages": [], "packages-dev": [ { @@ -62,14 +62,15 @@ "dist": { "type": "path", "url": "projects/packages/codesniffer", - "reference": "0c6a653df0a0baed6fe0b7558b34e733dec3f13c" + "reference": "defc334cb374051af045c9f32205a605efc8df09" }, "require": { + "automattic/vipwpcs": "^2.3", "dealerdirect/phpcodesniffer-composer-installer": "^0.7", "mediawiki/mediawiki-codesniffer": "^38.0", "phpcompatibility/phpcompatibility-wp": "^2.1", "sirbrillig/phpcs-variable-analysis": "^2.10", - "wp-coding-standards/wpcs": "^2.3" + "wp-coding-standards/wpcs": "dev-develop as 2.3.1" }, "require-dev": { "automattic/jetpack-changelogger": "^3.0", @@ -83,7 +84,7 @@ "link-template": "https://github.com/Automattic/jetpack-codesniffer/compare/v${old}...v${new}" }, "branch-alias": { - "dev-master": "2.4.x-dev" + "dev-master": "2.5.x-dev" } }, "autoload": { @@ -164,6 +165,58 @@ "relative": true } }, + { + "name": "automattic/vipwpcs", + "version": "2.3.3", + "source": { + "type": "git", + "url": "https://github.com/Automattic/VIP-Coding-Standards.git", + "reference": "6cd0a6a82bc0ac988dbf9d6a7c2e293dc8ac640b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Automattic/VIP-Coding-Standards/zipball/6cd0a6a82bc0ac988dbf9d6a7c2e293dc8ac640b", + "reference": "6cd0a6a82bc0ac988dbf9d6a7c2e293dc8ac640b", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7", + "php": ">=5.4", + "sirbrillig/phpcs-variable-analysis": "^2.11.1", + "squizlabs/php_codesniffer": "^3.5.5", + "wp-coding-standards/wpcs": "^2.3" + }, + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^0.5", + "php-parallel-lint/php-parallel-lint": "^1.0", + "phpcompatibility/php-compatibility": "^9", + "phpcsstandards/phpcsdevtools": "^1.0", + "phpunit/phpunit": "^4 || ^5 || ^6 || ^7" + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Contributors", + "homepage": "https://github.com/Automattic/VIP-Coding-Standards/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress VIP minimum coding conventions", + "keywords": [ + "phpcs", + "standards", + "wordpress" + ], + "support": { + "issues": "https://github.com/Automattic/VIP-Coding-Standards/issues", + "source": "https://github.com/Automattic/VIP-Coding-Standards", + "wiki": "https://github.com/Automattic/VIP-Coding-Standards/wiki" + }, + "time": "2021-09-29T16:20:23+00:00" + }, { "name": "composer/semver", "version": "3.2.7", @@ -674,6 +727,130 @@ }, "time": "2021-12-30T16:37:40+00:00" }, + { + "name": "phpcsstandards/phpcsextra", + "version": "1.0.0-alpha3", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHPCSExtra.git", + "reference": "a8415f9c2b7360e7184aad803a2c7e2b0544b4f1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSExtra/zipball/a8415f9c2b7360e7184aad803a2c7e2b0544b4f1", + "reference": "a8415f9c2b7360e7184aad803a2c7e2b0544b4f1", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7", + "php": ">=5.4", + "phpcsstandards/phpcsutils": "^1.0 || dev-develop", + "squizlabs/php_codesniffer": "^3.3.1" + }, + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^0.5", + "php-parallel-lint/php-parallel-lint": "^1.0", + "phpcsstandards/phpcsdevtools": "^1.0", + "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0" + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHPCSExtra/graphs/contributors" + } + ], + "description": "A collection of sniffs and standards for use with PHP_CodeSniffer.", + "keywords": [ + "PHP_CodeSniffer", + "phpcbf", + "phpcodesniffer-standard", + "phpcs", + "standards" + ], + "support": { + "issues": "https://github.com/PHPCSStandards/PHPCSExtra/issues", + "source": "https://github.com/PHPCSStandards/PHPCSExtra" + }, + "time": "2020-06-29T03:39:34+00:00" + }, + { + "name": "phpcsstandards/phpcsutils", + "version": "1.0.0-alpha3", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHPCSUtils.git", + "reference": "a16c989b8421e29c336ece5c4099b48585994673" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/a16c989b8421e29c336ece5c4099b48585994673", + "reference": "a16c989b8421e29c336ece5c4099b48585994673", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7", + "php": ">=5.4", + "squizlabs/php_codesniffer": "^2.6.0 || ^3.1.0 || 4.0.x-dev@dev" + }, + "conflict": { + "squizlabs/php_codesniffer": "3.5.3" + }, + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^0.5", + "php-parallel-lint/php-parallel-lint": "^1.2.0", + "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + }, + "type": "phpcodesniffer-standard", + "autoload": { + "classmap": [ + "PHPCSUtils/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHPCSUtils/graphs/contributors" + } + ], + "description": "A suite of utility functions for use with PHP_CodeSniffer", + "homepage": "https://phpcsutils.com/", + "keywords": [ + "PHP_CodeSniffer", + "phpcbf", + "phpcodesniffer-standard", + "phpcs", + "phpcs2", + "phpcs3", + "standards", + "tokens", + "utility" + ], + "support": { + "docs": "https://phpcsutils.com/", + "issues": "https://github.com/PHPCSStandards/PHPCSUtils/issues", + "source": "https://github.com/PHPCSStandards/PHPCSUtils" + }, + "time": "2020-06-28T21:57:33+00:00" + }, { "name": "sirbrillig/phpcs-changed", "version": "v2.8.1", @@ -704,15 +881,15 @@ ], "type": "library", "autoload": { - "psr-4": { - "PhpcsChanged\\": "PhpcsChanged/" - }, "files": [ "PhpcsChanged/Cli.php", "PhpcsChanged/SvnWorkflow.php", "PhpcsChanged/GitWorkflow.php", "PhpcsChanged/functions.php" - ] + ], + "psr-4": { + "PhpcsChanged\\": "PhpcsChanged/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -841,31 +1018,32 @@ }, { "name": "wp-coding-standards/wpcs", - "version": "2.3.0", + "version": "dev-develop", "source": { "type": "git", "url": "https://github.com/WordPress/WordPress-Coding-Standards.git", - "reference": "7da1894633f168fe244afc6de00d141f27517b62" + "reference": "73f3d69b3a200935b80f5fd265bfbee8d642d082" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/7da1894633f168fe244afc6de00d141f27517b62", - "reference": "7da1894633f168fe244afc6de00d141f27517b62", + "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/73f3d69b3a200935b80f5fd265bfbee8d642d082", + "reference": "73f3d69b3a200935b80f5fd265bfbee8d642d082", "shasum": "" }, "require": { "php": ">=5.4", - "squizlabs/php_codesniffer": "^3.3.1" + "phpcsstandards/phpcsextra": "^1.0", + "phpcsstandards/phpcsutils": "^1.0", + "squizlabs/php_codesniffer": "^3.5.0" }, "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || ^0.6", + "php-parallel-lint/php-console-highlighter": "^0.5", + "php-parallel-lint/php-parallel-lint": "^1.0", "phpcompatibility/php-compatibility": "^9.0", "phpcsstandards/phpcsdevtools": "^1.0", "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" }, - "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically." - }, + "default-branch": true, "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", "license": [ @@ -888,14 +1066,22 @@ "source": "https://github.com/WordPress/WordPress-Coding-Standards", "wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki" }, - "time": "2020-05-13T23:57:56+00:00" + "time": "2021-12-30T19:26:09+00:00" + } + ], + "aliases": [ + { + "package": "wp-coding-standards/wpcs", + "version": "dev-develop", + "alias": "2.3.1", + "alias_normalized": "2.3.1.0" } ], - "aliases": [], "minimum-stability": "dev", "stability-flags": { "automattic/jetpack-codesniffer": 20, - "automattic/jetpack-phpcs-filter": 20 + "automattic/jetpack-phpcs-filter": 20, + "wp-coding-standards/wpcs": 20 }, "prefer-stable": true, "prefer-lowest": false, diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 4a352646bd7b6..ed8ec86a7ede3 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -25,7 +25,7 @@ Once your development environment is ready, you can get started and [create your If you'd like to contribute but don't know where to get started, you can take a look at existing issues: - ["Good First Bug"](https://github.com/Automattic/jetpack/labels/%5BType%5D%20Good%20First%20Bug) issues are a good entry point to get familiar with Jetpack's code base. -- All issues labeled with [the "Good For Community" label](https://github.com/Automattic/Jetpack/issues?q=is%3Aopen+is%3Aissue+label%3A%22%5BType%5D+Good+For+Community%22) are fair game. That's a great way to contribute new features and fix small issues within Jetpack. +- All issues labeled with [the "Good For Community" label](https://github.com/Automattic/jetpack/issues?q=is%3Aopen+sort%3Aupdated-desc+label%3A%22Good+For+Community%22) are fair game. That's a great way to contribute new features and fix small issues within Jetpack. ### We’re Here To Help diff --git a/docs/examples/bootstrap.php b/docs/examples/bootstrap.php index d6ed85d124e11..ac0abb95220a1 100644 --- a/docs/examples/bootstrap.php +++ b/docs/examples/bootstrap.php @@ -61,10 +61,12 @@ if ( ! class_exists( PHPUnit\Framework\MockObject\InvocationMocker::class, false ) && file_exists( "$_tests_dir/includes/phpunit7/MockObject/InvocationMocker.php" ) ) { + // phpcs:disable WordPressVIPMinimum.Files.IncludingFile.NotAbsolutePath require "$_tests_dir/includes/phpunit7/MockObject/Builder/NamespaceMatch.php"; require "$_tests_dir/includes/phpunit7/MockObject/Builder/ParametersMatch.php"; require "$_tests_dir/includes/phpunit7/MockObject/InvocationMocker.php"; require "$_tests_dir/includes/phpunit7/MockObject/MockMethod.php"; + // phpcs:enable } else { fprintf( STDOUT, diff --git a/docs/monorepo.md b/docs/monorepo.md index 6e8a705c2c0ae..9af553b192126 100644 --- a/docs/monorepo.md +++ b/docs/monorepo.md @@ -128,7 +128,8 @@ We use `composer.json` to hold metadata about projects. Much of our generic tool * `.extra.autotagger`: Set truthy to enable automatic release-version tagging in the mirror repo. See [Mirror repositories > Autotagger](#autotagger) for details. * `.extra.changelogger`: Configuration object for [Changelogger](#jetpack-changelogger). See [its documentation](https://github.com/Automattic/jetpack-changelogger#configuration) for details. * `.extra.changelogger-default-type`: Certain of our tools automatically create Changelogger change entries. This is the value to use for `--type` when doing so. Default type is `changed`. -* `.extra.dependencies`: This optional array specifies the "slugs" of any within-monorepo dependencies that can't otherwise be inferred. The "slug" consists of the two levels of directory under `projects/`, e.g. `plugins/jetpack` or `packages/lazy-images`. See [Testing](#testing) for details. +* `.extra.dependencies.build`: This optional array specifies the "slugs" of any within-monorepo build dependencies that can't otherwise be inferred. The "slug" consists of the two levels of directory under `projects/`, e.g. `plugins/jetpack` or `packages/lazy-images`. +* `.extra.dependencies.test`: This optional array specifies the "slugs" of any within-monorepo testing dependencies that can't otherwise be inferred. The "slug" consists of the two levels of directory under `projects/`, e.g. `plugins/jetpack` or `packages/lazy-images`. See [Testing](#testing) for details. * `.extra.dev-releases`: Indicate that the plugin will have developer alpha releases. Instead of the mirror repositories showing "VER-alpha", they'll start at "VER-a.0" and you can use the `-a` flag to the release tooling to release "VER-a.1". * `.extra.mirror-repo`: This specifies the name of the GitHub mirror repo, i.e. the "Automattic/jetpack-_something_" in "https://github.com/Automattic/jetpack-_something_". * `.extra.npmjs-autopublish`: Set truthy to enable automatic publishing of tagged versions to npmjs.com. See [Mirror repositories > Npmjs Auto-publisher](#npmjs-auto-publisher) for details. @@ -169,7 +170,8 @@ The Jetpack Monorepo includes GitHub actions to run a number of CI checks on all Tests for a project are only run for a PR if changes are made to the project or its dependencies. Dependencies may be specified as: * For Composer packages included in the monorepo, via `.require` and `.require-dev` in `composer.json`. -* For any other dependencies, via `.extra.dependencies` in `composer.json`. +* For JavaScript packages included in the monorepo, via `.dependencies` and `.devDependencies` in `package.json`. +* For any other dependencies, via `.extra.dependencies.test` in `composer.json`. The test environment will be set up with appropriate tools, including node, pnpm, php, phpdbg, and composer. Unless otherwise specified below, the versions of node and php will be those specified in `.github/versions.sh`. Other necessary tools may be pulled in via composer and pnpm. diff --git a/docs/quick-start.md b/docs/quick-start.md index fad5a0676f952..73d9eee30e43f 100644 --- a/docs/quick-start.md +++ b/docs/quick-start.md @@ -11,7 +11,9 @@ This guide assumes you are using MacOS or a Linux machine and are an Automattici ### Using the installation script To speed up the installation process, you may use our monorepo installation script. To do so: - - clone the Jetpack repo: `git clone https://github.com/Automattic/jetpack.git` + - clone the Jetpack repo using one of these two methods: + - A public SSH key ([recommended](https://github.com/Automattic/jetpack/blob/master/docs/development-environment.md#clone-the-repository)): `git clone git@github.com:Automattic/Jetpack.git` + - HTTPS: `git clone https://github.com/Automattic/jetpack.git` - `cd` into the cloned `jetpack` folder. - run `tools/install-monorepo.sh` from the monorepo root. Once the installation is complete, continue onto the section [Running Jetpack locally](#running-jetpack-locally). @@ -25,8 +27,9 @@ Prior to installation, we recommend using [`Homebrew`](https://brew.sh/) to mana The Jetpack Monorepo requires the following to be installed on your machine: -- Start by cloning the GitHub repo: - - `git clone https://github.com/Automattic/jetpack.git` +- Start by cloning the GitHub repo using one of these two methods: + - A public SSH key ([recommended](https://github.com/Automattic/jetpack/blob/master/docs/development-environment.md#clone-the-repository)): `git clone git@github.com:Automattic/Jetpack.git` + - HTTPS: `git clone https://github.com/Automattic/jetpack.git` - If you're not an Automattician, you can [fork the repo following the instructions here](https://docs.github.com/en/get-started/quickstart/contributing-to-projects). - Bash (will need to be updated from default Mac version): `brew install bash` - jq (JSON processor used in scripts): `brew install jq` @@ -47,10 +50,10 @@ To setup Docker: - Mac: `brew install --cask docker` (This will take a while!) - Linux: `brew install docker` - `open -a Docker` (or open the app from your Applications folder) to open the GUI application. You will likely need to enter your device password and accept their terms for a first time setup. -- Copy the settings file: `cp tools/docker/default.env tools/docker/.env` +- Copy the settings file from within the monorepo root: `cp tools/docker/default.env tools/docker/.env` - Open `tools/docker/.env` and make any modifications you'd like. - It's strongly recommend you at least change `WP_ADMIN_PASSWORD` to something more secure. -- Start the Docker container using `jetpack docker up` (this may take some time for the first setup) +- Start the Docker container using `jetpack docker up -d` (this may take some time for the first setup) - Install WordPress in your Docker container using `jetpack docker install` - Open up http://localhost to see your site! @@ -60,7 +63,9 @@ For more in depth Docker instructions, follow the [Docker environment for Jetpac In order to test features that require a WordPress.com connection and other network related Jetpack features, you'll need a test site that can create local HTTP tunnels. If you're an Automattician, we recommend using Jurassic Tube: -- Add a subdomain on [jurassic.tube](https://jurassic.tube/) +**Warning: This creates a tunnel to your local machine which should not be trusted as secure. If it is compromised, so is your computer and everything it has access to. Only `jetpack docker jt-up` when needed for testing things that require the site to be publicly accessible, and `jetpack docker jt-down` when completed.** + +- Visit the [jurassic.tube](https://jurassic.tube/) homepage to create a subdomain - Make sure you've run `pnpm install && pnpm cli-link` - Make sure Docker is running `jetpack docker up -d` - Stand on the monorepo root in your terminal and run `mkdir tools/docker/bin/jt` diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a1abf1735894a..53d650b9d960a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -77,8 +77,8 @@ importers: projects/js-packages/api: specifiers: - '@automattic/jetpack-config': workspace:^0.1.3-alpha - '@wordpress/url': 3.3.1 + '@automattic/jetpack-config': workspace:^0.1.3 + '@wordpress/url': 3.4.0 chai-fetch-mock: 3.0.0 fetch-mock: 9.11.0 jetpack-js-test-runner: workspace:* @@ -86,7 +86,7 @@ importers: nyc: 15.1.0 dependencies: '@automattic/jetpack-config': link:../config - '@wordpress/url': 3.3.1 + '@wordpress/url': 3.4.0 lodash: 4.17.21 devDependencies: chai-fetch-mock: 3.0.0_fetch-mock@9.11.0 @@ -109,20 +109,20 @@ importers: projects/js-packages/base-styles: specifiers: - '@wordpress/base-styles': 4.0.4 + '@wordpress/base-styles': 4.1.0 devDependencies: - '@wordpress/base-styles': 4.0.4 + '@wordpress/base-styles': 4.1.0 projects/js-packages/components: specifiers: '@automattic/format-currency': 1.0.0-alpha.0 - '@automattic/jetpack-base-styles': workspace:^0.1.7-alpha + '@automattic/jetpack-base-styles': workspace:^0.1.8-alpha '@babel/core': 7.16.0 '@babel/preset-react': 7.16.0 '@wordpress/browserslist-config': 4.1.0 - '@wordpress/components': 19.1.6 - '@wordpress/date': 4.2.3 - '@wordpress/i18n': 4.2.4 + '@wordpress/components': 19.3.0 + '@wordpress/date': 4.3.0 + '@wordpress/i18n': 4.3.0 classnames: 2.3.1 jetpack-js-test-runner: workspace:* lodash: 4.17.21 @@ -134,9 +134,9 @@ importers: dependencies: '@automattic/format-currency': 1.0.0-alpha.0_react@17.0.2 '@wordpress/browserslist-config': 4.1.0 - '@wordpress/components': 19.1.6_aae888dfa296766acacf1a733aa50b3a - '@wordpress/date': 4.2.3 - '@wordpress/i18n': 4.2.4 + '@wordpress/components': 19.3.0_aae888dfa296766acacf1a733aa50b3a + '@wordpress/date': 4.3.0 + '@wordpress/i18n': 4.3.0 classnames: 2.3.1 lodash: 4.17.21 prop-types: 15.8.1 @@ -153,24 +153,26 @@ importers: projects/js-packages/config: specifiers: jetpack-js-test-runner: workspace:* + nyc: 15.1.0 devDependencies: jetpack-js-test-runner: link:../../../tools/js-test-runner + nyc: 15.1.0 projects/js-packages/connection: specifiers: - '@automattic/jetpack-analytics': workspace:^0.1.7-alpha - '@automattic/jetpack-api': workspace:^0.8.3-alpha - '@automattic/jetpack-base-styles': workspace:^0.1.7-alpha - '@automattic/jetpack-components': workspace:^0.10.3-alpha - '@automattic/jetpack-config': workspace:^0.1.3-alpha + '@automattic/jetpack-analytics': workspace:^0.1.7 + '@automattic/jetpack-api': workspace:^0.8.4-alpha + '@automattic/jetpack-base-styles': workspace:^0.1.8-alpha + '@automattic/jetpack-components': workspace:^0.10.5-alpha + '@automattic/jetpack-config': workspace:^0.1.3 '@babel/core': 7.16.0 '@babel/preset-react': 7.16.0 - '@wordpress/base-styles': 4.0.4 + '@wordpress/base-styles': 4.1.0 '@wordpress/browserslist-config': 4.1.0 - '@wordpress/components': 19.1.6 - '@wordpress/data': 6.1.5 - '@wordpress/element': 4.0.4 - '@wordpress/i18n': 4.2.4 + '@wordpress/components': 19.3.0 + '@wordpress/data': 6.2.0 + '@wordpress/element': 4.1.0 + '@wordpress/i18n': 4.3.0 jetpack-js-test-runner: workspace:* lodash: 4.17.21 nyc: 15.1.0 @@ -183,12 +185,12 @@ importers: '@automattic/jetpack-api': link:../api '@automattic/jetpack-components': link:../components '@automattic/jetpack-config': link:../config - '@wordpress/base-styles': 4.0.4 + '@wordpress/base-styles': 4.1.0 '@wordpress/browserslist-config': 4.1.0 - '@wordpress/components': 19.1.6_aae888dfa296766acacf1a733aa50b3a - '@wordpress/data': 6.1.5_react@17.0.2 - '@wordpress/element': 4.0.4 - '@wordpress/i18n': 4.2.4 + '@wordpress/components': 19.3.0_aae888dfa296766acacf1a733aa50b3a + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/element': 4.1.0 + '@wordpress/i18n': 4.3.0 lodash: 4.17.21 prop-types: 15.8.1 devDependencies: @@ -206,7 +208,7 @@ importers: '@babel/preset-react': 7.16.0 chalk: 4.1.2 commander: 7.2.0 - eslint: 7.32.0 + eslint: 8.8.0 jetpack-js-test-runner: workspace:* nyc: 15.1.0 parse-diff: 0.8.1 @@ -216,7 +218,7 @@ importers: commander: 7.2.0 parse-diff: 0.8.1 devDependencies: - eslint: 7.32.0 + eslint: 8.8.0 jetpack-js-test-runner: link:../../../tools/js-test-runner nyc: 15.1.0 @@ -226,7 +228,7 @@ importers: '@wordpress/browserslist-config': 4.1.0 browserslist: ^4.17.6 debug: ^4.3.2 - eslint: 7.32.0 + eslint: 8.8.0 eslint-plugin-es: 4.1.0 jest: 27.3.1 semver: ^7.3.5 @@ -237,8 +239,8 @@ importers: semver: 7.3.5 devDependencies: '@wordpress/browserslist-config': 4.1.0 - eslint: 7.32.0 - eslint-plugin-es: 4.1.0_eslint@7.32.0 + eslint: 8.8.0 + eslint-plugin-es: 4.1.0_eslint@8.8.0 jest: 27.3.1 projects/js-packages/i18n-check-webpack-plugin: @@ -256,36 +258,34 @@ importers: projects/js-packages/i18n-loader-webpack-plugin: specifiers: - '@wordpress/dependency-extraction-webpack-plugin': 3.2.1 - '@wordpress/i18n': 4.2.4 + '@wordpress/dependency-extraction-webpack-plugin': 3.3.0 + '@wordpress/i18n': 4.3.0 debug: ^4.3.2 jest: 27.3.1 - md5-es: ^1.8.2 webpack: 5.65.0 dependencies: debug: 4.3.3 - md5-es: 1.8.2 devDependencies: - '@wordpress/dependency-extraction-webpack-plugin': 3.2.1_webpack@5.65.0 - '@wordpress/i18n': 4.2.4 + '@wordpress/dependency-extraction-webpack-plugin': 3.3.0_webpack@5.65.0 + '@wordpress/i18n': 4.3.0 jest: 27.3.1 webpack: 5.65.0 projects/js-packages/idc: specifiers: - '@automattic/jetpack-analytics': workspace:^0.1.7-alpha - '@automattic/jetpack-api': workspace:^0.8.3-alpha - '@automattic/jetpack-base-styles': workspace:^0.1.7-alpha - '@automattic/jetpack-components': workspace:^0.10.3-alpha + '@automattic/jetpack-analytics': workspace:^0.1.7 + '@automattic/jetpack-api': workspace:^0.8.4-alpha + '@automattic/jetpack-base-styles': workspace:^0.1.8-alpha + '@automattic/jetpack-components': workspace:^0.10.5-alpha '@babel/core': 7.16.0 '@babel/preset-react': 7.16.0 - '@wordpress/base-styles': 4.0.4 - '@wordpress/components': 19.1.6 - '@wordpress/compose': 5.0.7 - '@wordpress/data': 6.1.5 - '@wordpress/element': 4.0.4 - '@wordpress/i18n': 4.2.4 - '@wordpress/url': 3.3.1 + '@wordpress/base-styles': 4.1.0 + '@wordpress/components': 19.3.0 + '@wordpress/compose': 5.1.0 + '@wordpress/data': 6.2.0 + '@wordpress/element': 4.1.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/url': 3.4.0 jetpack-js-test-runner: workspace:* nyc: 15.1.0 prop-types: ^15.7.2 @@ -297,13 +297,13 @@ importers: '@automattic/jetpack-api': link:../api '@automattic/jetpack-base-styles': link:../base-styles '@automattic/jetpack-components': link:../components - '@wordpress/base-styles': 4.0.4 - '@wordpress/components': 19.1.6_aae888dfa296766acacf1a733aa50b3a - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2 - '@wordpress/element': 4.0.4 - '@wordpress/i18n': 4.2.4 - '@wordpress/url': 3.3.1 + '@wordpress/base-styles': 4.1.0 + '@wordpress/components': 19.3.0_aae888dfa296766acacf1a733aa50b3a + '@wordpress/compose': 5.1.0_react@17.0.2 + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/element': 4.1.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/url': 3.4.0 prop-types: 15.8.1 devDependencies: '@babel/core': 7.16.0 @@ -316,56 +316,60 @@ importers: projects/js-packages/licensing: specifiers: - '@automattic/jetpack-api': workspace:^0.8.3-alpha - '@automattic/jetpack-base-styles': workspace:^0.1.7-alpha - '@automattic/jetpack-components': workspace:^0.10.3-alpha + '@automattic/jetpack-api': workspace:^0.8.4-alpha + '@automattic/jetpack-base-styles': workspace:^0.1.8-alpha + '@automattic/jetpack-components': workspace:^0.10.5-alpha '@babel/core': 7.16.0 '@babel/preset-react': 7.16.0 - '@wordpress/components': 19.1.6 - '@wordpress/element': 4.0.4 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 + '@wordpress/components': 19.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/icons': 6.2.0 jetpack-js-test-runner: workspace:* + nyc: 15.1.0 prop-types: 15.7.2 react: 17.0.2 react-test-renderer: 17.0.2 dependencies: '@automattic/jetpack-api': link:../api '@automattic/jetpack-components': link:../components - '@wordpress/components': 19.1.6_@babel+core@7.16.0+react@17.0.2 - '@wordpress/element': 4.0.4 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 + '@wordpress/components': 19.3.0_@babel+core@7.16.0+react@17.0.2 + '@wordpress/element': 4.1.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/icons': 6.2.0 prop-types: 15.7.2 devDependencies: '@automattic/jetpack-base-styles': link:../base-styles '@babel/core': 7.16.0 '@babel/preset-react': 7.16.0_@babel+core@7.16.0 jetpack-js-test-runner: link:../../../tools/js-test-runner + nyc: 15.1.0 react: 17.0.2 react-test-renderer: 17.0.2_react@17.0.2 projects/js-packages/partner-coupon: specifiers: - '@automattic/jetpack-components': workspace:^0.10.3-alpha - '@automattic/jetpack-connection': workspace:^0.14.0-alpha + '@automattic/jetpack-components': workspace:^0.10.5-alpha + '@automattic/jetpack-connection': workspace:^0.15.1-alpha '@babel/core': 7.16.0 '@babel/preset-react': 7.16.0 - '@wordpress/i18n': 4.2.4 + '@wordpress/i18n': 4.3.0 classnames: 2.3.1 jetpack-js-test-runner: workspace:* + nyc: 15.1.0 prop-types: 15.7.2 react: 17.0.2 dependencies: '@automattic/jetpack-components': link:../components '@automattic/jetpack-connection': link:../connection - '@wordpress/i18n': 4.2.4 + '@wordpress/i18n': 4.3.0 classnames: 2.3.1 prop-types: 15.7.2 devDependencies: '@babel/core': 7.16.0 '@babel/preset-react': 7.16.0_@babel+core@7.16.0 jetpack-js-test-runner: link:../../../tools/js-test-runner + nyc: 15.1.0 react: 17.0.2 projects/js-packages/remove-asset-webpack-plugin: @@ -379,9 +383,17 @@ importers: jest: 27.3.1 webpack: 5.65.0 + projects/js-packages/shared-extension-utils: + specifiers: + jetpack-js-test-runner: workspace:* + nyc: 15.1.0 + devDependencies: + jetpack-js-test-runner: link:../../../tools/js-test-runner + nyc: 15.1.0 + projects/js-packages/storybook: specifiers: - '@automattic/jetpack-base-styles': workspace:^0.1.7-alpha + '@automattic/jetpack-base-styles': workspace:^0.1.8-alpha '@babel/core': 7.16.0 '@babel/plugin-syntax-jsx': 7.16.0 '@babel/preset-react': 7.16.0 @@ -403,12 +415,12 @@ importers: '@storybook/builder-webpack5': 6.4.10 '@storybook/manager-webpack5': 6.4.10 '@storybook/react': 6.4.10 - '@wordpress/babel-preset-default': 6.4.1 - '@wordpress/block-editor': 8.0.12 - '@wordpress/block-library': 6.0.17 - '@wordpress/components': 19.1.6 - '@wordpress/format-library': 3.0.18 - '@wordpress/postcss-plugins-preset': 3.2.5 + '@wordpress/babel-preset-default': 6.5.0 + '@wordpress/block-editor': 8.1.0 + '@wordpress/block-library': 6.1.0 + '@wordpress/components': 19.3.0 + '@wordpress/format-library': 3.1.0 + '@wordpress/postcss-plugins-preset': 3.3.0 babel-plugin-inline-json-import: 0.3.2 concurrently: 6.0.2 css-loader: 6.5.1 @@ -440,12 +452,12 @@ importers: '@storybook/builder-webpack5': 6.4.10_react@17.0.2 '@storybook/manager-webpack5': 6.4.10_react@17.0.2 '@storybook/react': 6.4.10_e92bd153364abdbbdd93b0e4261d62de - '@wordpress/babel-preset-default': 6.4.1 - '@wordpress/block-editor': 8.0.12_@babel+core@7.16.0+react@17.0.2 - '@wordpress/block-library': 6.0.17_@babel+core@7.16.0+react@17.0.2 - '@wordpress/components': 19.1.6_@babel+core@7.16.0+react@17.0.2 - '@wordpress/format-library': 3.0.18_@babel+core@7.16.0+react@17.0.2 - '@wordpress/postcss-plugins-preset': 3.2.5 + '@wordpress/babel-preset-default': 6.5.0 + '@wordpress/block-editor': 8.1.0_@babel+core@7.16.0+react@17.0.2 + '@wordpress/block-library': 6.1.0_@babel+core@7.16.0+react@17.0.2 + '@wordpress/components': 19.3.0_@babel+core@7.16.0+react@17.0.2 + '@wordpress/format-library': 3.1.0_@babel+core@7.16.0+react@17.0.2 + '@wordpress/postcss-plugins-preset': 3.3.0 babel-plugin-inline-json-import: 0.3.2 concurrently: 6.0.2 css-loader: 6.5.1_webpack@5.65.0 @@ -458,9 +470,9 @@ importers: projects/js-packages/webpack-config: specifiers: '@automattic/babel-plugin-preserve-i18n': 1.0.0 - '@automattic/babel-plugin-replace-textdomain': workspace:^1.0.2-alpha - '@automattic/i18n-check-webpack-plugin': workspace:^1.0.3-alpha - '@automattic/i18n-loader-webpack-plugin': workspace:^1.0.3-alpha + '@automattic/babel-plugin-replace-textdomain': workspace:^1.0.2 + '@automattic/i18n-check-webpack-plugin': workspace:^1.0.4 + '@automattic/i18n-loader-webpack-plugin': workspace:^2.0.1-alpha '@automattic/webpack-rtl-plugin': 5.1.0 '@babel/compat-data': 7.16.4 '@babel/core': 7.16.0 @@ -472,13 +484,14 @@ importers: '@babel/preset-typescript': 7.16.0 '@babel/runtime': 7.16.3 '@wordpress/browserslist-config': 4.1.0 - '@wordpress/dependency-extraction-webpack-plugin': 3.2.1 + '@wordpress/dependency-extraction-webpack-plugin': 3.3.0 babel-loader: 8.2.3 browserslist: 4.19.1 css-loader: 6.5.1 css-minimizer-webpack-plugin: 3.1.4 duplicate-package-checker-webpack-plugin: 3.0.0 mini-css-extract-plugin: 2.4.5 + nyc: 15.1.0 terser-webpack-plugin: 5.2.5 thread-loader: 3.0.4 webpack: 5.65.0 @@ -497,7 +510,7 @@ importers: '@babel/preset-react': 7.16.0_@babel+core@7.16.0 '@babel/preset-typescript': 7.16.0_@babel+core@7.16.0 '@wordpress/browserslist-config': 4.1.0 - '@wordpress/dependency-extraction-webpack-plugin': 3.2.1_webpack@5.65.0 + '@wordpress/dependency-extraction-webpack-plugin': 3.3.0_webpack@5.65.0 babel-loader: 8.2.3_8dd2b11efd9b7265f9b7da54f0e73ab1 browserslist: 4.19.1 css-loader: 6.5.1_webpack@5.65.0 @@ -509,24 +522,37 @@ importers: devDependencies: '@babel/core': 7.16.0 '@babel/runtime': 7.16.3 + nyc: 15.1.0 webpack: 5.65.0_webpack-cli@4.9.1 webpack-cli: 4.9.1_webpack@5.65.0 projects/packages/admin-ui: specifiers: {} + projects/packages/assets: + specifiers: + '@automattic/jetpack-webpack-config': workspace:^1.1.2-alpha + jest: 27.3.1 + md5-es: 1.8.2 + webpack: 5.65.0 + devDependencies: + '@automattic/jetpack-webpack-config': link:../../js-packages/webpack-config + jest: 27.3.1 + md5-es: 1.8.2 + webpack: 5.65.0 + projects/packages/connection-ui: specifiers: - '@automattic/jetpack-api': workspace:^0.8.3-alpha - '@automattic/jetpack-connection': workspace:^0.14.0-alpha - '@automattic/jetpack-webpack-config': workspace:^1.0.3-alpha + '@automattic/jetpack-api': workspace:^0.8.4-alpha + '@automattic/jetpack-connection': workspace:^0.15.1-alpha + '@automattic/jetpack-webpack-config': workspace:^1.1.2-alpha '@babel/core': 7.16.0 '@babel/preset-env': 7.16.4 '@babel/register': 7.16.0 '@babel/runtime': 7.16.3 '@wordpress/browserslist-config': 4.1.0 - '@wordpress/data': 6.1.5 - '@wordpress/i18n': 4.2.4 + '@wordpress/data': 6.2.0 + '@wordpress/i18n': 4.3.0 enzyme: 3.11.0 jest: 27.3.1 react: 17.0.2 @@ -538,7 +564,7 @@ importers: dependencies: '@automattic/jetpack-api': link:../../js-packages/api '@automattic/jetpack-connection': link:../../js-packages/connection - '@wordpress/data': 6.1.5_react@17.0.2 + '@wordpress/data': 6.2.0_react@17.0.2 devDependencies: '@automattic/jetpack-webpack-config': link:../../js-packages/webpack-config '@babel/core': 7.16.0 @@ -546,7 +572,7 @@ importers: '@babel/register': 7.16.0_@babel+core@7.16.0 '@babel/runtime': 7.16.3 '@wordpress/browserslist-config': 4.1.0 - '@wordpress/i18n': 4.2.4 + '@wordpress/i18n': 4.3.0 enzyme: 3.11.0 jest: 27.3.1 react: 17.0.2 @@ -558,14 +584,14 @@ importers: projects/packages/identity-crisis: specifiers: - '@automattic/jetpack-idc': workspace:^0.9.0-alpha - '@automattic/jetpack-webpack-config': workspace:^1.0.3-alpha + '@automattic/jetpack-idc': workspace:^0.9.2-alpha + '@automattic/jetpack-webpack-config': workspace:^1.1.2-alpha '@babel/core': 7.16.0 '@babel/preset-env': 7.16.4 '@babel/register': 7.16.0 '@babel/runtime': 7.16.3 '@wordpress/browserslist-config': 4.1.0 - '@wordpress/data': 6.1.5 + '@wordpress/data': 6.2.0 fancy-log: 1.3.3 react: 17.0.2 react-dom: 17.0.2 @@ -574,7 +600,7 @@ importers: webpack: 5.65.0 dependencies: '@automattic/jetpack-idc': link:../../js-packages/idc - '@wordpress/data': 6.1.5_react@17.0.2 + '@wordpress/data': 6.2.0_react@17.0.2 devDependencies: '@automattic/jetpack-webpack-config': link:../../js-packages/webpack-config '@babel/core': 7.16.0 @@ -591,7 +617,7 @@ importers: projects/packages/jitm: specifiers: - '@automattic/jetpack-webpack-config': workspace:^1.0.3-alpha + '@automattic/jetpack-webpack-config': workspace:^1.1.2-alpha '@wordpress/browserslist-config': 4.1.0 sass: 1.43.3 sass-loader: 12.4.0 @@ -607,7 +633,7 @@ importers: projects/packages/lazy-images: specifiers: - '@automattic/jetpack-webpack-config': workspace:^1.0.3-alpha + '@automattic/jetpack-webpack-config': workspace:^1.1.2-alpha copy-webpack-plugin: 10.2.0 intersection-observer: 0.12.0 webpack: 5.65.0 @@ -619,11 +645,12 @@ importers: projects/packages/my-jetpack: specifiers: - '@automattic/jetpack-analytics': workspace:^0.1.7-alpha - '@automattic/jetpack-base-styles': workspace:^0.1.7-alpha - '@automattic/jetpack-components': workspace:^0.10.3-alpha - '@automattic/jetpack-connection': workspace:^0.14.0-alpha - '@automattic/jetpack-webpack-config': workspace:^1.0.3-alpha + '@automattic/format-currency': 1.0.0-alpha.0 + '@automattic/jetpack-analytics': workspace:^0.1.7 + '@automattic/jetpack-base-styles': workspace:^0.1.8-alpha + '@automattic/jetpack-components': workspace:^0.10.5-alpha + '@automattic/jetpack-connection': workspace:^0.15.1-alpha + '@automattic/jetpack-webpack-config': workspace:^1.1.2-alpha '@babel/core': 7.16.0 '@babel/preset-env': 7.16.4 '@babel/register': 7.16.0 @@ -634,9 +661,11 @@ importers: '@testing-library/react': 11.2.7 '@testing-library/react-hooks': 4.0.1 '@testing-library/user-event': 12.8.3 - '@wordpress/components': 19.1.6 - '@wordpress/data': 6.1.5 - '@wordpress/i18n': 4.2.4 + '@wordpress/api-fetch': 6.0.0 + '@wordpress/components': 19.3.0 + '@wordpress/data': 6.2.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/icons': 6.2.0 classnames: 2.3.1 enzyme: 3.11.0 jest: 27.3.1 @@ -644,19 +673,24 @@ importers: prop-types: 15.8.1 react: 17.0.2 react-dom: 17.0.2 + react-router-dom: '6' sass: 1.43.3 sass-loader: 12.4.0 storybook-addon-mock: 2.0.2 webpack: 5.65.0 dependencies: + '@automattic/format-currency': 1.0.0-alpha.0_react@17.0.2 '@automattic/jetpack-analytics': link:../../js-packages/analytics '@automattic/jetpack-components': link:../../js-packages/components '@automattic/jetpack-connection': link:../../js-packages/connection - '@wordpress/components': 19.1.6_aae888dfa296766acacf1a733aa50b3a - '@wordpress/data': 6.1.5_react@17.0.2 - '@wordpress/i18n': 4.2.4 + '@wordpress/api-fetch': 6.0.0 + '@wordpress/components': 19.3.0_aae888dfa296766acacf1a733aa50b3a + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/i18n': 4.3.0 + '@wordpress/icons': 6.2.0 classnames: 2.3.1 prop-types: 15.8.1 + react-router-dom: 6.2.1_react-dom@17.0.2+react@17.0.2 devDependencies: '@automattic/jetpack-base-styles': link:../../js-packages/base-styles '@automattic/jetpack-webpack-config': link:../../js-packages/webpack-config @@ -684,10 +718,10 @@ importers: specifiers: '@automattic/calypso-color-schemes': 2.1.1 '@automattic/color-studio': 2.5.0 - '@automattic/jetpack-analytics': workspace:^0.1.7-alpha - '@automattic/jetpack-api': workspace:^0.8.3-alpha - '@automattic/jetpack-components': workspace:^0.10.3-alpha - '@automattic/jetpack-webpack-config': workspace:^1.0.3-alpha + '@automattic/jetpack-analytics': workspace:^0.1.7 + '@automattic/jetpack-api': workspace:^0.8.4-alpha + '@automattic/jetpack-components': workspace:^0.10.5-alpha + '@automattic/jetpack-webpack-config': workspace:^1.1.2-alpha '@babel/core': 7.16.0 '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.0 '@babel/preset-env': 7.16.4 @@ -696,14 +730,14 @@ importers: '@size-limit/preset-app': 6.0.3 '@testing-library/jest-dom': 5.14.1 '@testing-library/preact': 2.0.1 - '@wordpress/base-styles': 4.0.4 - '@wordpress/block-editor': 8.0.12 + '@wordpress/base-styles': 4.1.0 + '@wordpress/block-editor': 8.1.0 '@wordpress/browserslist-config': 4.1.0 - '@wordpress/data': 6.1.5 - '@wordpress/dependency-extraction-webpack-plugin': 3.2.1 - '@wordpress/element': 4.0.4 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 + '@wordpress/data': 6.2.0 + '@wordpress/dependency-extraction-webpack-plugin': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/icons': 6.2.0 classnames: 2.3.1 concurrently: 6.4.0 fast-json-stable-stringify: 2.1.0 @@ -735,12 +769,12 @@ importers: '@automattic/jetpack-analytics': link:../../js-packages/analytics '@automattic/jetpack-api': link:../../js-packages/api '@automattic/jetpack-components': link:../../js-packages/components - '@wordpress/base-styles': 4.0.4 - '@wordpress/block-editor': 8.0.12_b4e1ce88a10f1ab0bbeb2b9720317029 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.1.1 - '@wordpress/element': 4.0.4 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 + '@wordpress/base-styles': 4.1.0 + '@wordpress/block-editor': 8.1.0_aae888dfa296766acacf1a733aa50b3a + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/element': 4.1.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/icons': 6.2.0 classnames: 2.3.1 fast-json-stable-stringify: 2.1.0 gridicons: 3.3.1_react@17.0.2 @@ -768,7 +802,7 @@ importers: '@testing-library/jest-dom': 5.14.1 '@testing-library/preact': 2.0.1_preact@10.5.15 '@wordpress/browserslist-config': 4.1.0 - '@wordpress/dependency-extraction-webpack-plugin': 3.2.1_webpack@5.65.0 + '@wordpress/dependency-extraction-webpack-plugin': 3.3.0_webpack@5.65.0 concurrently: 6.4.0 jest: 27.3.1 jest-environment-jsdom: 27.3.1 @@ -781,21 +815,21 @@ importers: projects/plugins/backup: specifiers: - '@automattic/jetpack-api': workspace:^0.8.3-alpha - '@automattic/jetpack-base-styles': workspace:^0.1.7-alpha - '@automattic/jetpack-components': workspace:^0.10.3-alpha - '@automattic/jetpack-connection': workspace:^0.14.0-alpha - '@automattic/jetpack-webpack-config': workspace:^1.0.3-alpha + '@automattic/jetpack-api': workspace:^0.8.4-alpha + '@automattic/jetpack-base-styles': workspace:^0.1.8-alpha + '@automattic/jetpack-components': workspace:^0.10.5-alpha + '@automattic/jetpack-connection': workspace:^0.15.1-alpha + '@automattic/jetpack-webpack-config': workspace:^1.1.2-alpha '@babel/core': 7.16.0 '@babel/preset-env': 7.16.4 '@babel/register': 7.16.0 '@babel/runtime': 7.16.3 - '@wordpress/api-fetch': 5.2.6 + '@wordpress/api-fetch': 6.0.0 '@wordpress/browserslist-config': 4.1.0 - '@wordpress/data': 6.1.5 - '@wordpress/date': 4.2.3 - '@wordpress/element': 4.0.4 - '@wordpress/i18n': 4.2.4 + '@wordpress/data': 6.2.0 + '@wordpress/date': 4.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/i18n': 4.3.0 concurrently: 6.0.2 react: 17.0.2 react-dom: 17.0.2 @@ -807,11 +841,11 @@ importers: '@automattic/jetpack-api': link:../../js-packages/api '@automattic/jetpack-components': link:../../js-packages/components '@automattic/jetpack-connection': link:../../js-packages/connection - '@wordpress/api-fetch': 5.2.6 - '@wordpress/data': 6.1.5_react@17.0.2 - '@wordpress/date': 4.2.3 - '@wordpress/element': 4.0.4 - '@wordpress/i18n': 4.2.4 + '@wordpress/api-fetch': 6.0.0 + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/date': 4.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/i18n': 4.3.0 react: 17.0.2 react-dom: 17.0.2_react@17.0.2 devDependencies: @@ -837,12 +871,12 @@ importers: '@rollup/plugin-typescript': 8.2.5 '@sveltejs/eslint-config': github:sveltejs/eslint-config '@tsconfig/svelte': 2.0.1 - '@typescript-eslint/eslint-plugin': 4.33.0 - '@typescript-eslint/parser': 4.33.0 - '@wordpress/components': 19.1.6 - '@wordpress/e2e-test-utils': 5.4.10 - '@wordpress/element': 4.0.4 - '@wordpress/i18n': 4.2.4 + '@typescript-eslint/eslint-plugin': 5.10.2 + '@typescript-eslint/parser': 5.10.2 + '@wordpress/components': 19.3.0 + '@wordpress/e2e-test-utils': 6.0.0 + '@wordpress/element': 4.1.0 + '@wordpress/i18n': 4.3.0 eslint-plugin-import: 2.25.4 eslint-plugin-svelte3: 3.2.1 jetpack-boost-critical-css-gen: github:automattic/jetpack-boost-critical-css-gen#release-0.0.2 @@ -863,8 +897,8 @@ importers: tslib: 2.3.1 typescript: 4.3.5 dependencies: - '@wordpress/components': 19.1.6_@babel+core@7.16.0 - '@wordpress/element': 4.0.4 + '@wordpress/components': 19.3.0_@babel+core@7.16.0 + '@wordpress/element': 4.1.0 jetpack-boost-critical-css-gen: github.com/automattic/jetpack-boost-critical-css-gen/0232a05d6681315f40365143c7ed93707933f7e3 devDependencies: '@babel/core': 7.16.0 @@ -872,12 +906,12 @@ importers: '@rollup/plugin-commonjs': 19.0.2_rollup@2.56.3 '@rollup/plugin-node-resolve': 13.0.6_rollup@2.56.3 '@rollup/plugin-typescript': 8.2.5_fb60d1099d0f1062e1f455c5bc85cce0 - '@sveltejs/eslint-config': github.com/sveltejs/eslint-config/8a67624e4080bd7997606eb34981aa3346bc8de2_0ca1a0e6c61895213d3918b4d67bc4f3 + '@sveltejs/eslint-config': github.com/sveltejs/eslint-config/8a67624e4080bd7997606eb34981aa3346bc8de2_948a3e55fb7525b40c6fc4d3c0529949 '@tsconfig/svelte': 2.0.1 - '@typescript-eslint/eslint-plugin': 4.33.0_8c654464cf7de6904a251c0e456613ed - '@typescript-eslint/parser': 4.33.0_typescript@4.3.5 - '@wordpress/e2e-test-utils': 5.4.10 - '@wordpress/i18n': 4.2.4 + '@typescript-eslint/eslint-plugin': 5.10.2_9b53d4b455d21bf3af38fdac900301d2 + '@typescript-eslint/parser': 5.10.2_typescript@4.3.5 + '@wordpress/e2e-test-utils': 6.0.0 + '@wordpress/i18n': 4.3.0 eslint-plugin-import: 2.25.4 eslint-plugin-svelte3: 3.2.1_svelte@3.42.4 node-wp-i18n: 1.2.6 @@ -903,16 +937,16 @@ importers: '@automattic/color-studio': 2.5.0 '@automattic/components': 1.0.0-alpha.3 '@automattic/format-currency': 1.0.0-alpha.0 - '@automattic/jetpack-analytics': workspace:^0.1.7-alpha - '@automattic/jetpack-api': workspace:^0.8.3-alpha - '@automattic/jetpack-base-styles': workspace:^0.1.7-alpha - '@automattic/jetpack-components': workspace:^0.10.3-alpha - '@automattic/jetpack-connection': workspace:^0.14.0-alpha - '@automattic/jetpack-licensing': workspace:^0.4.4-alpha - '@automattic/jetpack-partner-coupon': workspace:^0.1.6-alpha - '@automattic/jetpack-webpack-config': workspace:^1.0.3-alpha + '@automattic/jetpack-analytics': workspace:^0.1.7 + '@automattic/jetpack-api': workspace:^0.8.4-alpha + '@automattic/jetpack-base-styles': workspace:^0.1.8-alpha + '@automattic/jetpack-components': workspace:^0.10.5-alpha + '@automattic/jetpack-connection': workspace:^0.15.1-alpha + '@automattic/jetpack-licensing': workspace:^0.4.6-alpha + '@automattic/jetpack-partner-coupon': workspace:^0.1.8-alpha + '@automattic/jetpack-webpack-config': workspace:^1.1.2-alpha '@automattic/popup-monitor': 1.0.0 - '@automattic/remove-asset-webpack-plugin': workspace:^1.0.3-alpha + '@automattic/remove-asset-webpack-plugin': workspace:^1.0.3 '@automattic/request-external-access': 1.0.0 '@automattic/social-previews': 1.1.1 '@automattic/viewport': 1.0.0 @@ -932,26 +966,26 @@ importers: '@testing-library/react': 11.2.7 '@testing-library/react-hooks': 4.0.1 '@testing-library/user-event': 12.8.3 - '@wordpress/annotations': 2.2.8 + '@wordpress/annotations': 2.3.0 '@wordpress/babel-plugin-import-jsx-pragma': 3.1.0 - '@wordpress/base-styles': 4.0.4 - '@wordpress/block-editor': 8.0.12 - '@wordpress/blocks': 11.1.5 + '@wordpress/base-styles': 4.1.0 + '@wordpress/block-editor': 8.1.0 + '@wordpress/blocks': 11.2.0 '@wordpress/browserslist-config': 4.1.0 - '@wordpress/components': 19.1.6 - '@wordpress/compose': 5.0.7 - '@wordpress/core-data': 4.0.9 - '@wordpress/data': 6.1.5 - '@wordpress/date': 4.2.3 - '@wordpress/dependency-extraction-webpack-plugin': 3.2.1 - '@wordpress/editor': 12.0.15 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/server-side-render': 3.0.16 - '@wordpress/url': 3.3.1 - '@wordpress/viewport': 4.0.7 + '@wordpress/components': 19.3.0 + '@wordpress/compose': 5.1.0 + '@wordpress/core-data': 4.1.0 + '@wordpress/data': 6.2.0 + '@wordpress/date': 4.3.0 + '@wordpress/dependency-extraction-webpack-plugin': 3.3.0 + '@wordpress/editor': 12.1.0 + '@wordpress/element': 4.1.0 + '@wordpress/hooks': 3.3.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/icons': 6.2.0 + '@wordpress/server-side-render': 3.1.0 + '@wordpress/url': 3.4.0 + '@wordpress/viewport': 4.1.0 bounding-client-rect: 1.0.5 chai: 4.3.4 chalk: 4.1.2 @@ -970,7 +1004,7 @@ importers: email-validator: 2.0.4 enzyme: 3.11.0 enzyme-to-json: 3.6.2 - eslint: 7.32.0 + eslint: 8.8.0 fancy-log: 1.3.3 fast-json-stable-stringify: 2.1.0 focus-trap: 6.3.0 @@ -1058,22 +1092,22 @@ importers: '@automattic/jetpack-partner-coupon': link:../../js-packages/partner-coupon '@automattic/popup-monitor': 1.0.0 '@automattic/request-external-access': 1.0.0 - '@automattic/social-previews': 1.1.1_b23a2df06df1cb7d0e5a2ce752eda4cf + '@automattic/social-previews': 1.1.1_d6aa0d5b77ebdc587ad2683e8fb8389a '@automattic/viewport': 1.0.0 - '@wordpress/annotations': 2.2.8_react@17.0.2+redux@4.0.5 - '@wordpress/base-styles': 4.0.4 - '@wordpress/block-editor': 8.0.12_595f56c80e7e5fab2a648c0f724c83ea - '@wordpress/blocks': 11.1.5_react@17.0.2+redux@4.0.5 + '@wordpress/annotations': 2.3.0_react@17.0.2 + '@wordpress/base-styles': 4.1.0 + '@wordpress/block-editor': 8.1.0_aae888dfa296766acacf1a733aa50b3a + '@wordpress/blocks': 11.2.0_react@17.0.2 '@wordpress/browserslist-config': 4.1.0 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.0.5 - '@wordpress/date': 4.2.3 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/url': 3.3.1 - '@wordpress/viewport': 4.0.7_react@17.0.2+redux@4.0.5 + '@wordpress/compose': 5.1.0_react@17.0.2 + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/date': 4.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/hooks': 3.3.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/icons': 6.2.0 + '@wordpress/url': 3.4.0 + '@wordpress/viewport': 4.1.0_react@17.0.2 bounding-client-rect: 1.0.5 classnames: 2.3.1 click-outside: 2.0.2 @@ -1159,11 +1193,11 @@ importers: '@testing-library/react-hooks': 4.0.1_509016fd322278d497c1e58f6164ce1d '@testing-library/user-event': 12.8.3_@testing-library+dom@7.31.2 '@wordpress/babel-plugin-import-jsx-pragma': 3.1.0_@babel+core@7.16.0 - '@wordpress/components': 19.1.6_595f56c80e7e5fab2a648c0f724c83ea - '@wordpress/core-data': 4.0.9_react@17.0.2+redux@4.0.5 - '@wordpress/dependency-extraction-webpack-plugin': 3.2.1_webpack@5.65.0 - '@wordpress/editor': 12.0.15_595f56c80e7e5fab2a648c0f724c83ea - '@wordpress/server-side-render': 3.0.16_595f56c80e7e5fab2a648c0f724c83ea + '@wordpress/components': 19.3.0_aae888dfa296766acacf1a733aa50b3a + '@wordpress/core-data': 4.1.0_react@17.0.2 + '@wordpress/dependency-extraction-webpack-plugin': 3.3.0_webpack@5.65.0 + '@wordpress/editor': 12.1.0_aae888dfa296766acacf1a733aa50b3a + '@wordpress/server-side-render': 3.1.0_aae888dfa296766acacf1a733aa50b3a chai: 4.3.4 chalk: 4.1.2 commander: 7.2.0 @@ -1171,7 +1205,7 @@ importers: css-loader: 6.5.1_webpack@5.65.0 enzyme: 3.11.0 enzyme-to-json: 3.6.2_enzyme@3.11.0 - eslint: 7.32.0 + eslint: 8.8.0 fs-extra: 10.0.0 glob: 7.1.6 jest: 27.3.1 @@ -1210,17 +1244,22 @@ importers: envfile: 6.17.0 execa: 5.0.0 glob: 7.1.6 + ignore: 5.1.8 inquirer: 7.3.3 js-yaml: 4.1.0 listr: 0.14.3 + listr-silent-renderer: 1.1.1 listr-update-renderer: 0.5.0 listr-verbose-renderer: 0.6.0 mocha: 8.4.0 + p-limit: 4.0.0 path-name: 1.0.0 pluralize: 8.0.0 process: 0.11.10 + semver: 7.3.5 simple-git: 2.37.0 sinon: 9.2.4 + sprintf-js: 1.1.2 yargs: 16.2.0 yargs-parser: 20.2.4 dependencies: @@ -1231,15 +1270,20 @@ importers: envfile: 6.17.0 execa: 5.0.0 glob: 7.1.6 + ignore: 5.1.8 inquirer: 7.3.3 js-yaml: 4.1.0 listr: 0.14.3 + listr-silent-renderer: 1.1.1 listr-update-renderer: 0.5.0_listr@0.14.3 listr-verbose-renderer: 0.6.0 + p-limit: 4.0.0 path-name: 1.0.0 pluralize: 8.0.0 process: 0.11.10 + semver: 7.3.5 simple-git: 2.37.0 + sprintf-js: 1.1.2 yargs: 16.2.0 devDependencies: chai: 4.3.4 @@ -1261,7 +1305,7 @@ importers: '@testing-library/react-hooks': 4.0.1 '@testing-library/user-event': 12.8.3 '@wojtekmaj/enzyme-adapter-react-17': 0.6.3 - '@wordpress/jest-preset-default': 7.1.3 + '@wordpress/jest-preset-default': 8.0.0 babel-jest: 27.3.1 chai: 4.3.4 chai-dom: 1.11.0 @@ -1289,7 +1333,7 @@ importers: '@testing-library/react-hooks': 4.0.1 '@testing-library/user-event': 12.8.3_@testing-library+dom@8.11.1 '@wojtekmaj/enzyme-adapter-react-17': 0.6.3_enzyme@3.11.0 - '@wordpress/jest-preset-default': 7.1.3_@babel+core@7.16.0+jest@27.3.1 + '@wordpress/jest-preset-default': 8.0.0_@babel+core@7.16.0+jest@27.3.1 babel-jest: 27.3.1_@babel+core@7.16.0 chai: 4.3.4 chai-dom: 1.11.0_chai@4.3.4+mocha@8.4.0 @@ -1313,20 +1357,20 @@ importers: '@babel/eslint-parser': 7.16.3 '@octokit/auth-token': 2.4.5 '@octokit/rest': 18.6.7 - '@wordpress/eslint-plugin': 9.3.0 + '@wordpress/eslint-plugin': 10.0.0 chalk: 4.1.2 debug: 4.3.3 - eslint: 7.32.0 + eslint: 8.8.0 eslint-config-prettier: 8.3.0 eslint-config-wpcalypso: 6.1.0 eslint-plugin-es: 4.1.0 eslint-plugin-es5: 1.5.0 - eslint-plugin-inclusive-language: 1.2.1 - eslint-plugin-jest: 24.7.0 - eslint-plugin-jsdoc: 36.1.1 + eslint-plugin-inclusive-language: 2.2.0 + eslint-plugin-jest: 26.0.0 + eslint-plugin-jsdoc: 37.7.0 eslint-plugin-jsx-a11y: 6.5.1 eslint-plugin-lodash: 7.3.0 - eslint-plugin-prettier: 3.4.1 + eslint-plugin-prettier: 4.0.0 eslint-plugin-react: 7.28.0 eslint-plugin-react-hooks: 4.3.0 eslint-plugin-wpcalypso: 5.0.0 @@ -1344,26 +1388,26 @@ importers: '@automattic/eslint-changed': link:../../projects/js-packages/eslint-changed '@automattic/eslint-config-target-es': link:../../projects/js-packages/eslint-config-target-es '@babel/core': 7.16.0 - '@babel/eslint-parser': 7.16.3_@babel+core@7.16.0+eslint@7.32.0 + '@babel/eslint-parser': 7.16.3_@babel+core@7.16.0+eslint@8.8.0 '@octokit/auth-token': 2.4.5 '@octokit/rest': 18.6.7 - '@wordpress/eslint-plugin': 9.3.0_@babel+core@7.16.0+eslint@7.32.0 + '@wordpress/eslint-plugin': 10.0.0_@babel+core@7.16.0+eslint@8.8.0 chalk: 4.1.2 debug: 4.3.3 - eslint: 7.32.0 - eslint-config-prettier: 8.3.0_eslint@7.32.0 - eslint-config-wpcalypso: 6.1.0_3eb42fe7d0610a71481faeb55adacf83 - eslint-plugin-es: 4.1.0_eslint@7.32.0 - eslint-plugin-es5: 1.5.0_eslint@7.32.0 - eslint-plugin-inclusive-language: 1.2.1 - eslint-plugin-jest: 24.7.0_eslint@7.32.0 - eslint-plugin-jsdoc: 36.1.1_eslint@7.32.0 - eslint-plugin-jsx-a11y: 6.5.1_eslint@7.32.0 - eslint-plugin-lodash: 7.3.0_eslint@7.32.0 - eslint-plugin-prettier: 3.4.1_b003eb7dfbbe32a2afc96a18053e1e13 - eslint-plugin-react: 7.28.0_eslint@7.32.0 - eslint-plugin-react-hooks: 4.3.0_eslint@7.32.0 - eslint-plugin-wpcalypso: 5.0.0_eslint@7.32.0 + eslint: 8.8.0 + eslint-config-prettier: 8.3.0_eslint@8.8.0 + eslint-config-wpcalypso: 6.1.0_11dfa443dfb9bfd86a5486c959f4047a + eslint-plugin-es: 4.1.0_eslint@8.8.0 + eslint-plugin-es5: 1.5.0_eslint@8.8.0 + eslint-plugin-inclusive-language: 2.2.0 + eslint-plugin-jest: 26.0.0_eslint@8.8.0 + eslint-plugin-jsdoc: 37.7.0_eslint@8.8.0 + eslint-plugin-jsx-a11y: 6.5.1_eslint@8.8.0 + eslint-plugin-lodash: 7.3.0_eslint@8.8.0 + eslint-plugin-prettier: 4.0.0_5208900944bd53d50aafd0e7d193e6c3 + eslint-plugin-react: 7.28.0_eslint@8.8.0 + eslint-plugin-react-hooks: 4.3.0_eslint@8.8.0 + eslint-plugin-wpcalypso: 5.0.0_eslint@8.8.0 glob: 7.1.6 ignore: 5.1.8 inquirer: 7.3.3 @@ -1459,13 +1503,13 @@ packages: '@automattic/popup-monitor': 1.0.0 dev: false - /@automattic/social-previews/1.1.1_b23a2df06df1cb7d0e5a2ce752eda4cf: + /@automattic/social-previews/1.1.1_d6aa0d5b77ebdc587ad2683e8fb8389a: resolution: {integrity: sha512-yt15yIatJcGRJKhDVGpj7i7Q6l4uQnMvzjgoOU3uUC/wwLZRji+0tRrD8xfsq12hXwnx1cEkEQeSoSozZzsAtA==} peerDependencies: react: ^16.12.0 dependencies: '@babel/runtime': 7.16.3 - '@wordpress/components': 12.0.9_b23a2df06df1cb7d0e5a2ce752eda4cf + '@wordpress/components': 12.0.9_d6aa0d5b77ebdc587ad2683e8fb8389a '@wordpress/i18n': 3.20.0 classnames: 2.3.1 lodash: 4.17.21 @@ -1499,12 +1543,6 @@ packages: '@babel/highlight': 7.16.7 dev: true - /@babel/code-frame/7.12.11: - resolution: {integrity: sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==} - dependencies: - '@babel/highlight': 7.16.7 - dev: true - /@babel/code-frame/7.16.7: resolution: {integrity: sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==} engines: {node: '>=6.9.0'} @@ -1583,7 +1621,7 @@ packages: transitivePeerDependencies: - supports-color - /@babel/eslint-parser/7.16.3_@babel+core@7.16.0+eslint@7.32.0: + /@babel/eslint-parser/7.16.3_@babel+core@7.16.0+eslint@8.8.0: resolution: {integrity: sha512-iB4ElZT0jAt7PKVaeVulOECdGe6UnmA/O0P9jlF5g5GBOwDVbna8AXhHRu4s27xQf6OkveyA8iTDv1jHdDejgQ==} engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} peerDependencies: @@ -1591,7 +1629,7 @@ packages: eslint: ^7.5.0 || ^8.0.0 dependencies: '@babel/core': 7.16.0 - eslint: 7.32.0 + eslint: 8.8.0 eslint-scope: 5.1.1 eslint-visitor-keys: 2.1.0 semver: 6.3.0 @@ -1672,6 +1710,24 @@ packages: transitivePeerDependencies: - supports-color + /@babel/helper-create-class-features-plugin/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-kIFozAvVfK05DM4EVQYKK+zteWvY85BFdGBRQBytRyY3y+6PX0DkDOn/CZ3lEuczCfrCxEzwt0YtP/87YPTWSw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-annotate-as-pure': 7.16.7 + '@babel/helper-environment-visitor': 7.16.7 + '@babel/helper-function-name': 7.16.7 + '@babel/helper-member-expression-to-functions': 7.16.7 + '@babel/helper-optimise-call-expression': 7.16.7 + '@babel/helper-replace-supers': 7.16.7 + '@babel/helper-split-export-declaration': 7.16.7 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/helper-create-regexp-features-plugin/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-fk5A6ymfp+O5+p2yCkXAu5Kyj6v0xh0RBeNcAkYUMDvvAAoxvSKXn+Jb37t/yWFiQVDFK1ELpUTD8/aLhCPu+g==} engines: {node: '>=6.9.0'} @@ -1682,6 +1738,17 @@ packages: '@babel/helper-annotate-as-pure': 7.16.7 regexpu-core: 4.8.0 + /@babel/helper-create-regexp-features-plugin/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-fk5A6ymfp+O5+p2yCkXAu5Kyj6v0xh0RBeNcAkYUMDvvAAoxvSKXn+Jb37t/yWFiQVDFK1ELpUTD8/aLhCPu+g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-annotate-as-pure': 7.16.7 + regexpu-core: 4.8.0 + dev: true + /@babel/helper-define-polyfill-provider/0.1.5_@babel+core@7.16.0: resolution: {integrity: sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==} peerDependencies: @@ -1700,6 +1767,24 @@ packages: - supports-color dev: true + /@babel/helper-define-polyfill-provider/0.1.5_@babel+core@7.16.7: + resolution: {integrity: sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==} + peerDependencies: + '@babel/core': ^7.4.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.16.7 + '@babel/helper-module-imports': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/traverse': 7.16.3 + debug: 4.3.3 + lodash.debounce: 4.0.8 + resolve: 1.21.0 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/helper-define-polyfill-provider/0.3.0_@babel+core@7.16.0: resolution: {integrity: sha512-7hfT8lUljl/tM3h+izTX/pO3W3frz2ok6Pk+gzys8iJqDfZrZy2pXjRTZAvG2YmfHun1X4q8/UZRLatMfqc5Tg==} peerDependencies: @@ -1717,6 +1802,24 @@ packages: transitivePeerDependencies: - supports-color + /@babel/helper-define-polyfill-provider/0.3.0_@babel+core@7.16.7: + resolution: {integrity: sha512-7hfT8lUljl/tM3h+izTX/pO3W3frz2ok6Pk+gzys8iJqDfZrZy2pXjRTZAvG2YmfHun1X4q8/UZRLatMfqc5Tg==} + peerDependencies: + '@babel/core': ^7.4.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.16.7 + '@babel/helper-module-imports': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/traverse': 7.16.7 + debug: 4.3.3 + lodash.debounce: 4.0.8 + resolve: 1.21.0 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/helper-environment-visitor/7.16.7: resolution: {integrity: sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==} engines: {node: '>=6.9.0'} @@ -1881,6 +1984,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==} engines: {node: '>=6.9.0'} @@ -1892,6 +2005,18 @@ packages: '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.16.0 + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 + '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.16.7 + dev: true + /@babel/plugin-proposal-async-generator-functions/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-TTXBT3A5c11eqRzaC6beO6rlFT3Mo9C2e8eB44tTr52ESXSK2CIc2fOp1ynpAwQA8HhBMho+WXhMHWlAe3xkpw==} engines: {node: '>=6.9.0'} @@ -1905,6 +2030,20 @@ packages: transitivePeerDependencies: - supports-color + /@babel/plugin-proposal-async-generator-functions/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-TTXBT3A5c11eqRzaC6beO6rlFT3Mo9C2e8eB44tTr52ESXSK2CIc2fOp1ynpAwQA8HhBMho+WXhMHWlAe3xkpw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-remap-async-to-generator': 7.16.7 + '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.16.7 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/plugin-proposal-class-properties/7.16.0_@babel+core@7.16.0: resolution: {integrity: sha512-mCF3HcuZSY9Fcx56Lbn+CGdT44ioBMMvjNVldpKtj8tpniETdLjnxdHI1+sDWXIM1nNt+EanJOZ3IG9lzVjs7A==} engines: {node: '>=6.9.0'} @@ -1930,6 +2069,19 @@ packages: transitivePeerDependencies: - supports-color + /@babel/plugin-proposal-class-properties/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-create-class-features-plugin': 7.16.7_@babel+core@7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/plugin-proposal-class-static-block/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw==} engines: {node: '>=6.9.0'} @@ -1943,6 +2095,20 @@ packages: transitivePeerDependencies: - supports-color + /@babel/plugin-proposal-class-static-block/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-create-class-features-plugin': 7.16.7_@babel+core@7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.16.7 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/plugin-proposal-decorators/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-DoEpnuXK14XV9btI1k8tzNGCutMclpj4yru8aXKoHlVmbO1s+2A+g2+h4JhcjrxkFJqzbymnLG6j/niOf3iFXQ==} engines: {node: '>=6.9.0'} @@ -1957,6 +2123,20 @@ packages: - supports-color dev: true + /@babel/plugin-proposal-decorators/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-DoEpnuXK14XV9btI1k8tzNGCutMclpj4yru8aXKoHlVmbO1s+2A+g2+h4JhcjrxkFJqzbymnLG6j/niOf3iFXQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-create-class-features-plugin': 7.16.7_@babel+core@7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-decorators': 7.16.7_@babel+core@7.16.7 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/plugin-proposal-dynamic-import/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==} engines: {node: '>=6.9.0'} @@ -1967,6 +2147,17 @@ packages: '@babel/helper-plugin-utils': 7.16.7 '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.16.0 + /@babel/plugin-proposal-dynamic-import/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.16.7 + dev: true + /@babel/plugin-proposal-export-default-from/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-+cENpW1rgIjExn+o5c8Jw/4BuH4eGKKYvkMB8/0ZxFQ9mC0t4z09VsPIwNg6waF69QYC81zxGeAsREGuqQoKeg==} engines: {node: '>=6.9.0'} @@ -1978,6 +2169,17 @@ packages: '@babel/plugin-syntax-export-default-from': 7.16.7_@babel+core@7.16.0 dev: true + /@babel/plugin-proposal-export-default-from/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-+cENpW1rgIjExn+o5c8Jw/4BuH4eGKKYvkMB8/0ZxFQ9mC0t4z09VsPIwNg6waF69QYC81zxGeAsREGuqQoKeg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-export-default-from': 7.16.7_@babel+core@7.16.7 + dev: true + /@babel/plugin-proposal-export-namespace-from/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==} engines: {node: '>=6.9.0'} @@ -1988,6 +2190,17 @@ packages: '@babel/helper-plugin-utils': 7.16.7 '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.16.0 + /@babel/plugin-proposal-export-namespace-from/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.16.7 + dev: true + /@babel/plugin-proposal-json-strings/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==} engines: {node: '>=6.9.0'} @@ -1998,6 +2211,17 @@ packages: '@babel/helper-plugin-utils': 7.16.7 '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.16.0 + /@babel/plugin-proposal-json-strings/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.16.7 + dev: true + /@babel/plugin-proposal-logical-assignment-operators/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==} engines: {node: '>=6.9.0'} @@ -2008,6 +2232,17 @@ packages: '@babel/helper-plugin-utils': 7.16.7 '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.16.0 + /@babel/plugin-proposal-logical-assignment-operators/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.16.7 + dev: true + /@babel/plugin-proposal-nullish-coalescing-operator/7.16.0_@babel+core@7.16.0: resolution: {integrity: sha512-3bnHA8CAFm7cG93v8loghDYyQ8r97Qydf63BeYiGgYbjKKB/XP53W15wfRC7dvKfoiJ34f6Rbyyx2btExc8XsQ==} engines: {node: '>=6.9.0'} @@ -2029,6 +2264,17 @@ packages: '@babel/helper-plugin-utils': 7.16.7 '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.16.0 + /@babel/plugin-proposal-nullish-coalescing-operator/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.16.7 + dev: true + /@babel/plugin-proposal-numeric-separator/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==} engines: {node: '>=6.9.0'} @@ -2039,6 +2285,17 @@ packages: '@babel/helper-plugin-utils': 7.16.7 '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.16.0 + /@babel/plugin-proposal-numeric-separator/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.16.7 + dev: true + /@babel/plugin-proposal-object-rest-spread/7.12.1_@babel+core@7.12.9: resolution: {integrity: sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==} peerDependencies: @@ -2063,6 +2320,20 @@ packages: '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.16.0 '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.16.0 + /@babel/plugin-proposal-object-rest-spread/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-3O0Y4+dw94HA86qSg9IHfyPktgR7q3gpNVAeiKQd+8jBKFaU5NQS1Yatgo4wY+UFNuLjvxcSmzcsHqrhgTyBUA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.16.4 + '@babel/core': 7.16.7 + '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.16.7 + '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.16.7 + dev: true + /@babel/plugin-proposal-optional-catch-binding/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==} engines: {node: '>=6.9.0'} @@ -2073,6 +2344,17 @@ packages: '@babel/helper-plugin-utils': 7.16.7 '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.16.0 + /@babel/plugin-proposal-optional-catch-binding/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.16.7 + dev: true + /@babel/plugin-proposal-optional-chaining/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==} engines: {node: '>=6.9.0'} @@ -2084,6 +2366,18 @@ packages: '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.16.0 + /@babel/plugin-proposal-optional-chaining/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 + '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.16.7 + dev: true + /@babel/plugin-proposal-private-methods/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-7twV3pzhrRxSwHeIvFE6coPgvo+exNDOiGUMg39o2LiLo1Y+4aKpfkcLGcg1UHonzorCt7SNXnoMyCnnIOA8Sw==} engines: {node: '>=6.9.0'} @@ -2096,6 +2390,19 @@ packages: transitivePeerDependencies: - supports-color + /@babel/plugin-proposal-private-methods/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-7twV3pzhrRxSwHeIvFE6coPgvo+exNDOiGUMg39o2LiLo1Y+4aKpfkcLGcg1UHonzorCt7SNXnoMyCnnIOA8Sw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-create-class-features-plugin': 7.16.7_@babel+core@7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/plugin-proposal-private-property-in-object/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==} engines: {node: '>=6.9.0'} @@ -2110,6 +2417,21 @@ packages: transitivePeerDependencies: - supports-color + /@babel/plugin-proposal-private-property-in-object/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-annotate-as-pure': 7.16.7 + '@babel/helper-create-class-features-plugin': 7.16.7_@babel+core@7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.16.7 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/plugin-proposal-unicode-property-regex/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==} engines: {node: '>=4'} @@ -2120,6 +2442,17 @@ packages: '@babel/helper-create-regexp-features-plugin': 7.16.7_@babel+core@7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-proposal-unicode-property-regex/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==} + engines: {node: '>=4'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-create-regexp-features-plugin': 7.16.7_@babel+core@7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.16.0: resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} peerDependencies: @@ -2178,6 +2511,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-syntax-class-static-block/7.14.5_@babel+core@7.16.7: + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-syntax-decorators/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-vQ+PxL+srA7g6Rx6I1e15m55gftknl2X8GCUW1JTlkTaXZLJOS0UcaY0eK9jYT7IYf4awn6qwyghVHLDz1WyMw==} engines: {node: '>=6.9.0'} @@ -2188,6 +2531,16 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true + /@babel/plugin-syntax-decorators/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-vQ+PxL+srA7g6Rx6I1e15m55gftknl2X8GCUW1JTlkTaXZLJOS0UcaY0eK9jYT7IYf4awn6qwyghVHLDz1WyMw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-syntax-dynamic-import/7.8.3_@babel+core@7.16.0: resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} peerDependencies: @@ -2196,6 +2549,15 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-syntax-dynamic-import/7.8.3_@babel+core@7.16.7: + resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-syntax-export-default-from/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-4C3E4NsrLOgftKaTYTULhHsuQrGv3FHrBzOMDiS7UYKIpgGBkAdawg4h+EI8zPeK9M0fiIIh72hIwsI24K7MbA==} engines: {node: '>=6.9.0'} @@ -2206,6 +2568,16 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true + /@babel/plugin-syntax-export-default-from/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-4C3E4NsrLOgftKaTYTULhHsuQrGv3FHrBzOMDiS7UYKIpgGBkAdawg4h+EI8zPeK9M0fiIIh72hIwsI24K7MbA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-syntax-export-namespace-from/7.8.3_@babel+core@7.16.0: resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} peerDependencies: @@ -2214,6 +2586,15 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-syntax-export-namespace-from/7.8.3_@babel+core@7.16.7: + resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-syntax-flow/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-UDo3YGQO0jH6ytzVwgSLv9i/CzMcUjbKenL67dTrAZPPv6GFAtDhe6jqnvmoKzC/7htNTohhos+onPtDMqJwaQ==} engines: {node: '>=6.9.0'} @@ -2294,6 +2675,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-syntax-jsx/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.16.0: resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} peerDependencies: @@ -2408,6 +2799,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-syntax-private-property-in-object/7.14.5_@babel+core@7.16.7: + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.16.0: resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} engines: {node: '>=6.9.0'} @@ -2453,6 +2854,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-arrow-functions/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-async-to-generator/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-pFEfjnK4DfXCfAlA5I98BYdDJD8NltMzx19gt6DAmfE+2lXRfPUoa0/5SUjT4+TDE1W/rcxU/1lgN55vpAjjdg==} engines: {node: '>=6.9.0'} @@ -2466,6 +2877,20 @@ packages: transitivePeerDependencies: - supports-color + /@babel/plugin-transform-async-to-generator/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-pFEfjnK4DfXCfAlA5I98BYdDJD8NltMzx19gt6DAmfE+2lXRfPUoa0/5SUjT4+TDE1W/rcxU/1lgN55vpAjjdg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-module-imports': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-remap-async-to-generator': 7.16.7 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/plugin-transform-block-scoped-functions/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==} engines: {node: '>=6.9.0'} @@ -2475,6 +2900,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-block-scoped-functions/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-block-scoping/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==} engines: {node: '>=6.9.0'} @@ -2484,6 +2919,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-block-scoping/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-classes/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==} engines: {node: '>=6.9.0'} @@ -2502,6 +2947,25 @@ packages: transitivePeerDependencies: - supports-color + /@babel/plugin-transform-classes/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-annotate-as-pure': 7.16.7 + '@babel/helper-environment-visitor': 7.16.7 + '@babel/helper-function-name': 7.16.7 + '@babel/helper-optimise-call-expression': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-replace-supers': 7.16.7 + '@babel/helper-split-export-declaration': 7.16.7 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/plugin-transform-computed-properties/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==} engines: {node: '>=6.9.0'} @@ -2511,6 +2975,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-computed-properties/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-destructuring/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-VqAwhTHBnu5xBVDCvrvqJbtLUa++qZaWC0Fgr2mqokBlulZARGyIvZDoqbPlPaKImQ9dKAcCzbv+ul//uqu70A==} engines: {node: '>=6.9.0'} @@ -2520,6 +2994,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-destructuring/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-VqAwhTHBnu5xBVDCvrvqJbtLUa++qZaWC0Fgr2mqokBlulZARGyIvZDoqbPlPaKImQ9dKAcCzbv+ul//uqu70A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-dotall-regex/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==} engines: {node: '>=6.9.0'} @@ -2530,6 +3014,17 @@ packages: '@babel/helper-create-regexp-features-plugin': 7.16.7_@babel+core@7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-dotall-regex/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-create-regexp-features-plugin': 7.16.7_@babel+core@7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-duplicate-keys/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==} engines: {node: '>=6.9.0'} @@ -2539,6 +3034,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-duplicate-keys/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-exponentiation-operator/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==} engines: {node: '>=6.9.0'} @@ -2549,6 +3054,17 @@ packages: '@babel/helper-builder-binary-assignment-operator-visitor': 7.16.7 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-exponentiation-operator/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-builder-binary-assignment-operator-visitor': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-flow-strip-types/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-mzmCq3cNsDpZZu9FADYYyfZJIOrSONmHcop2XEKPdBNMa4PDC4eEvcOvzZaCNcjKu72v0XQlA5y1g58aLRXdYg==} engines: {node: '>=6.9.0'} @@ -2569,6 +3085,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-for-of/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-function-name/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==} engines: {node: '>=6.9.0'} @@ -2580,6 +3106,18 @@ packages: '@babel/helper-function-name': 7.16.7 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-function-name/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.16.7 + '@babel/helper-function-name': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-literals/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==} engines: {node: '>=6.9.0'} @@ -2589,6 +3127,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-literals/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-member-expression-literals/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==} engines: {node: '>=6.9.0'} @@ -2598,6 +3146,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-member-expression-literals/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-modules-amd/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==} engines: {node: '>=6.9.0'} @@ -2611,23 +3169,52 @@ packages: transitivePeerDependencies: - supports-color - /@babel/plugin-transform-modules-commonjs/7.16.7_@babel+core@7.16.0: - resolution: {integrity: sha512-h2RP2kE7He1ZWKyAlanMZrAbdv+Acw1pA8dQZhE025WJZE2z0xzFADAinXA9fxd5bn7JnM+SdOGcndGx1ARs9w==} + /@babel/plugin-transform-modules-amd/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 + '@babel/core': 7.16.7 '@babel/helper-module-transforms': 7.16.7 '@babel/helper-plugin-utils': 7.16.7 - '@babel/helper-simple-access': 7.16.7 babel-plugin-dynamic-import-node: 2.3.3 transitivePeerDependencies: - supports-color + dev: true - /@babel/plugin-transform-modules-systemjs/7.16.7_@babel+core@7.16.0: - resolution: {integrity: sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==} - engines: {node: '>=6.9.0'} + /@babel/plugin-transform-modules-commonjs/7.16.7_@babel+core@7.16.0: + resolution: {integrity: sha512-h2RP2kE7He1ZWKyAlanMZrAbdv+Acw1pA8dQZhE025WJZE2z0xzFADAinXA9fxd5bn7JnM+SdOGcndGx1ARs9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.0 + '@babel/helper-module-transforms': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-simple-access': 7.16.7 + babel-plugin-dynamic-import-node: 2.3.3 + transitivePeerDependencies: + - supports-color + + /@babel/plugin-transform-modules-commonjs/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-h2RP2kE7He1ZWKyAlanMZrAbdv+Acw1pA8dQZhE025WJZE2z0xzFADAinXA9fxd5bn7JnM+SdOGcndGx1ARs9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-module-transforms': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-simple-access': 7.16.7 + babel-plugin-dynamic-import-node: 2.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-modules-systemjs/7.16.7_@babel+core@7.16.0: + resolution: {integrity: sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: @@ -2640,6 +3227,22 @@ packages: transitivePeerDependencies: - supports-color + /@babel/plugin-transform-modules-systemjs/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-hoist-variables': 7.16.7 + '@babel/helper-module-transforms': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-validator-identifier': 7.16.7 + babel-plugin-dynamic-import-node: 2.3.3 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/plugin-transform-modules-umd/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==} engines: {node: '>=6.9.0'} @@ -2652,6 +3255,19 @@ packages: transitivePeerDependencies: - supports-color + /@babel/plugin-transform-modules-umd/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-module-transforms': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/plugin-transform-named-capturing-groups-regex/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-kFy35VwmwIQwCjwrAQhl3+c/kr292i4KdLPKp5lPH03Ltc51qnFlIADoyPxc/6Naz3ok3WdYKg+KK6AH+D4utg==} engines: {node: '>=6.9.0'} @@ -2661,6 +3277,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-create-regexp-features-plugin': 7.16.7_@babel+core@7.16.0 + /@babel/plugin-transform-named-capturing-groups-regex/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-kFy35VwmwIQwCjwrAQhl3+c/kr292i4KdLPKp5lPH03Ltc51qnFlIADoyPxc/6Naz3ok3WdYKg+KK6AH+D4utg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-create-regexp-features-plugin': 7.16.7_@babel+core@7.16.7 + dev: true + /@babel/plugin-transform-new-target/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==} engines: {node: '>=6.9.0'} @@ -2670,6 +3296,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-new-target/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-object-super/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==} engines: {node: '>=6.9.0'} @@ -2682,6 +3318,19 @@ packages: transitivePeerDependencies: - supports-color + /@babel/plugin-transform-object-super/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-replace-supers': 7.16.7 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/plugin-transform-parameters/7.16.7_@babel+core@7.12.9: resolution: {integrity: sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==} engines: {node: '>=6.9.0'} @@ -2701,6 +3350,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-parameters/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-property-literals/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==} engines: {node: '>=6.9.0'} @@ -2710,6 +3369,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-property-literals/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-react-display-name/7.16.7: resolution: {integrity: sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==} engines: {node: '>=6.9.0'} @@ -2728,6 +3397,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-react-display-name/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-react-jsx-development/7.16.7: resolution: {integrity: sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==} engines: {node: '>=6.9.0'} @@ -2746,6 +3425,16 @@ packages: '@babel/core': 7.16.0 '@babel/plugin-transform-react-jsx': 7.16.7_@babel+core@7.16.0 + /@babel/plugin-transform-react-jsx-development/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/plugin-transform-react-jsx': 7.16.7_@babel+core@7.16.7 + dev: true + /@babel/plugin-transform-react-jsx/7.16.0_@babel+core@7.16.0: resolution: {integrity: sha512-rqDgIbukZ44pqq7NIRPGPGNklshPkvlmvqjdx3OZcGPk4zGIenYkxDTvl3LsSL8gqcc3ZzGmXPE6hR/u/voNOw==} engines: {node: '>=6.9.0'} @@ -2786,6 +3475,20 @@ packages: '@babel/plugin-syntax-jsx': 7.16.7_@babel+core@7.16.0 '@babel/types': 7.16.7 + /@babel/plugin-transform-react-jsx/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-8D16ye66fxiE8m890w0BpPpngG9o9OVBBy0gH2E+2AR7qMR2ZpTYJEqLxAsoroenMId0p/wMW+Blc0meDgu0Ag==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-annotate-as-pure': 7.16.7 + '@babel/helper-module-imports': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-jsx': 7.16.7_@babel+core@7.16.7 + '@babel/types': 7.16.7 + dev: true + /@babel/plugin-transform-react-pure-annotations/7.16.7: resolution: {integrity: sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==} engines: {node: '>=6.9.0'} @@ -2806,6 +3509,17 @@ packages: '@babel/helper-annotate-as-pure': 7.16.7 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-react-pure-annotations/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-annotate-as-pure': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-regenerator/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==} engines: {node: '>=6.9.0'} @@ -2815,6 +3529,16 @@ packages: '@babel/core': 7.16.0 regenerator-transform: 0.14.5 + /@babel/plugin-transform-regenerator/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + regenerator-transform: 0.14.5 + dev: true + /@babel/plugin-transform-reserved-words/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==} engines: {node: '>=6.9.0'} @@ -2824,6 +3548,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-reserved-words/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-runtime/7.16.4_@babel+core@7.16.0: resolution: {integrity: sha512-pru6+yHANMTukMtEZGC4fs7XPwg35v8sj5CIEmE+gEkFljFiVJxEWxx/7ZDkTK+iZRYo1bFXBtfIN95+K3cJ5A==} engines: {node: '>=6.9.0'} @@ -2840,18 +3574,18 @@ packages: transitivePeerDependencies: - supports-color - /@babel/plugin-transform-runtime/7.16.7_@babel+core@7.16.0: + /@babel/plugin-transform-runtime/7.16.7_@babel+core@7.16.7: resolution: {integrity: sha512-2FoHiSAWkdq4L06uaDN3rS43i6x28desUVxq+zAFuE6kbWYQeiLPJI5IC7Sg9xKYVcrBKSQkVUfH6aeQYbl9QA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 + '@babel/core': 7.16.7 '@babel/helper-module-imports': 7.16.7 '@babel/helper-plugin-utils': 7.16.7 - babel-plugin-polyfill-corejs2: 0.3.0_@babel+core@7.16.0 - babel-plugin-polyfill-corejs3: 0.4.0_@babel+core@7.16.0 - babel-plugin-polyfill-regenerator: 0.3.0_@babel+core@7.16.0 + babel-plugin-polyfill-corejs2: 0.3.0_@babel+core@7.16.7 + babel-plugin-polyfill-corejs3: 0.4.0_@babel+core@7.16.7 + babel-plugin-polyfill-regenerator: 0.3.0_@babel+core@7.16.7 semver: 6.3.0 transitivePeerDependencies: - supports-color @@ -2866,6 +3600,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-shorthand-properties/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-spread/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==} engines: {node: '>=6.9.0'} @@ -2876,6 +3620,17 @@ packages: '@babel/helper-plugin-utils': 7.16.7 '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 + /@babel/plugin-transform-spread/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 + dev: true + /@babel/plugin-transform-sticky-regex/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==} engines: {node: '>=6.9.0'} @@ -2885,6 +3640,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-sticky-regex/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-template-literals/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==} engines: {node: '>=6.9.0'} @@ -2894,6 +3659,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-template-literals/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-typeof-symbol/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==} engines: {node: '>=6.9.0'} @@ -2903,6 +3678,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-typeof-symbol/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-typescript/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-Hzx1lvBtOCWuCEwMmYOfpQpO7joFeXLgoPuzZZBtTxXqSqUGUubvFGZv2ygo1tB5Bp9q6PXV3H0E/kf7KM0RLA==} engines: {node: '>=6.9.0'} @@ -2916,6 +3701,20 @@ packages: transitivePeerDependencies: - supports-color + /@babel/plugin-transform-typescript/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-Hzx1lvBtOCWuCEwMmYOfpQpO7joFeXLgoPuzZZBtTxXqSqUGUubvFGZv2ygo1tB5Bp9q6PXV3H0E/kf7KM0RLA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-create-class-features-plugin': 7.16.7_@babel+core@7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-typescript': 7.16.7_@babel+core@7.16.7 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/plugin-transform-unicode-escapes/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==} engines: {node: '>=6.9.0'} @@ -2925,6 +3724,16 @@ packages: '@babel/core': 7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-unicode-escapes/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/plugin-transform-unicode-regex/7.16.7_@babel+core@7.16.0: resolution: {integrity: sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==} engines: {node: '>=6.9.0'} @@ -2935,6 +3744,17 @@ packages: '@babel/helper-create-regexp-features-plugin': 7.16.7_@babel+core@7.16.0 '@babel/helper-plugin-utils': 7.16.7 + /@babel/plugin-transform-unicode-regex/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-create-regexp-features-plugin': 7.16.7_@babel+core@7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + dev: true + /@babel/preset-env/7.16.4_@babel+core@7.16.0: resolution: {integrity: sha512-v0QtNd81v/xKj4gNKeuAerQ/azeNn/G1B1qMLeXOcV8+4TWlD2j3NV1u8q29SDFBXx/NBq5kyEAO+0mpRgacjA==} engines: {node: '>=6.9.0'} @@ -3104,21 +3924,106 @@ packages: - supports-color dev: true - /@babel/preset-flow/7.16.7_@babel+core@7.16.0: - resolution: {integrity: sha512-6ceP7IyZdUYQ3wUVqyRSQXztd1YmFHWI4Xv11MIqAlE4WqxBSd/FZ61V9k+TS5Gd4mkHOtQtPp9ymRpxH4y1Ug==} + /@babel/preset-env/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-urX3Cee4aOZbRWOSa3mKPk0aqDikfILuo+C7qq7HY0InylGNZ1fekq9jmlr3pLWwZHF4yD7heQooc2Pow2KMyQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 + '@babel/compat-data': 7.16.4 + '@babel/core': 7.16.7 + '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.16.7 '@babel/helper-plugin-utils': 7.16.7 '@babel/helper-validator-option': 7.16.7 - '@babel/plugin-transform-flow-strip-types': 7.16.7_@babel+core@7.16.0 - dev: true - - /@babel/preset-modules/0.1.5_@babel+core@7.16.0: - resolution: {integrity: sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==} - peerDependencies: + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-async-generator-functions': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-class-properties': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-class-static-block': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-dynamic-import': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-export-namespace-from': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-json-strings': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-logical-assignment-operators': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-numeric-separator': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-object-rest-spread': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-optional-catch-binding': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-private-methods': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-private-property-in-object': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-unicode-property-regex': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.16.7 + '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.16.7 + '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.16.7 + '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.16.7 + '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.16.7 + '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.16.7 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.16.7 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.16.7 + '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.16.7 + '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.16.7 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.16.7 + '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.16.7 + '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.16.7 + '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.16.7 + '@babel/plugin-transform-arrow-functions': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-async-to-generator': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-block-scoped-functions': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-block-scoping': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-classes': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-computed-properties': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-destructuring': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-dotall-regex': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-duplicate-keys': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-exponentiation-operator': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-for-of': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-function-name': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-literals': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-member-expression-literals': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-modules-amd': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-modules-commonjs': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-modules-systemjs': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-modules-umd': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-named-capturing-groups-regex': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-new-target': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-object-super': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-property-literals': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-regenerator': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-reserved-words': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-shorthand-properties': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-spread': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-sticky-regex': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-template-literals': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-typeof-symbol': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-unicode-escapes': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-unicode-regex': 7.16.7_@babel+core@7.16.7 + '@babel/preset-modules': 0.1.5_@babel+core@7.16.7 + '@babel/types': 7.16.7 + babel-plugin-polyfill-corejs2: 0.3.0_@babel+core@7.16.7 + babel-plugin-polyfill-corejs3: 0.4.0_@babel+core@7.16.7 + babel-plugin-polyfill-regenerator: 0.3.0_@babel+core@7.16.7 + core-js-compat: 3.20.2 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/preset-flow/7.16.7_@babel+core@7.16.0: + resolution: {integrity: sha512-6ceP7IyZdUYQ3wUVqyRSQXztd1YmFHWI4Xv11MIqAlE4WqxBSd/FZ61V9k+TS5Gd4mkHOtQtPp9ymRpxH4y1Ug==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.0 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-validator-option': 7.16.7 + '@babel/plugin-transform-flow-strip-types': 7.16.7_@babel+core@7.16.0 + dev: true + + /@babel/preset-modules/0.1.5_@babel+core@7.16.0: + resolution: {integrity: sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==} + peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.0 @@ -3128,6 +4033,19 @@ packages: '@babel/types': 7.16.7 esutils: 2.0.3 + /@babel/preset-modules/0.1.5_@babel+core@7.16.7: + resolution: {integrity: sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-proposal-unicode-property-regex': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-dotall-regex': 7.16.7_@babel+core@7.16.7 + '@babel/types': 7.16.7 + esutils: 2.0.3 + dev: true + /@babel/preset-react/7.16.0: resolution: {integrity: sha512-d31IFW2bLRB28uL1WoElyro8RH5l6531XfxMtCeCmp6RVAF1uTfxxUA0LH1tXl+psZdwfmIbwoG4U5VwgbhtLw==} engines: {node: '>=6.9.0'} @@ -3171,6 +4089,21 @@ packages: '@babel/plugin-transform-react-pure-annotations': 7.16.7_@babel+core@7.16.0 dev: true + /@babel/preset-react/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-validator-option': 7.16.7 + '@babel/plugin-transform-react-display-name': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-react-jsx': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-react-jsx-development': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-react-pure-annotations': 7.16.7_@babel+core@7.16.7 + dev: true + /@babel/preset-typescript/7.16.0_@babel+core@7.16.0: resolution: {integrity: sha512-txegdrZYgO9DlPbv+9QOVpMnKbOtezsLHWsnsRF4AjbSIsVaujrq1qg8HK0mxQpWv0jnejt0yEoW1uWpvbrDTg==} engines: {node: '>=6.9.0'} @@ -3198,6 +4131,20 @@ packages: - supports-color dev: true + /@babel/preset-typescript/7.16.7_@babel+core@7.16.7: + resolution: {integrity: sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-validator-option': 7.16.7 + '@babel/plugin-transform-typescript': 7.16.7_@babel+core@7.16.7 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/register/7.16.0_@babel+core@7.16.0: resolution: {integrity: sha512-lzl4yfs0zVXnooeLE0AAfYaT7F3SPA8yB2Bj4W1BiZwLbMS3MZH35ZvCWSRHvneUugwuM+Wsnrj7h0F7UmU3NQ==} engines: {node: '>=6.9.0'} @@ -3211,13 +4158,13 @@ packages: pirates: 4.0.4 source-map-support: 0.5.21 - /@babel/register/7.16.7_@babel+core@7.16.0: + /@babel/register/7.16.7_@babel+core@7.16.7: resolution: {integrity: sha512-Ft+cuxorVxFj4RrPDs9TbJNE7ZbuJTyazUC6jLWRvBQT/qIDZPMe7MHgjlrA+11+XDLh+I0Pnx7sxPp4LRhzcA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.0 + '@babel/core': 7.16.7 clone-deep: 4.0.1 find-cache-dir: 2.1.0 make-dir: 2.1.0 @@ -3322,6 +4269,7 @@ packages: dependencies: exec-sh: 0.3.6 minimist: 1.2.5 + dev: true /@discoveryjs/json-ext/0.5.6: resolution: {integrity: sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA==} @@ -3735,26 +4683,26 @@ packages: /@emotion/weak-memoize/0.2.5: resolution: {integrity: sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==} - /@es-joy/jsdoccomment/0.10.8: - resolution: {integrity: sha512-3P1JiGL4xaR9PoTKUHa2N/LKwa2/eUdRqGwijMWWgBqbFEqJUVpmaOi2TcjcemrsRMgFLBzQCK4ToPhrSVDiFQ==} - engines: {node: ^12 || ^14 || ^16} + /@es-joy/jsdoccomment/0.18.0: + resolution: {integrity: sha512-TjT8KJULV4I6ZiwIoKr6eMs+XpRejqwJ/VA+QPDeFGe9j6bZFKmMJ81EeFsGm6JNZhnzm37aoxVROmTh2PZoyA==} + engines: {node: ^12 || ^14 || ^16 || ^17} dependencies: - comment-parser: 1.2.4 + comment-parser: 1.3.0 esquery: 1.4.0 - jsdoc-type-pratt-parser: 1.1.1 + jsdoc-type-pratt-parser: 2.2.2 dev: true - /@eslint/eslintrc/0.4.3: - resolution: {integrity: sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==} - engines: {node: ^10.12.0 || >=12.0.0} + /@eslint/eslintrc/1.0.5: + resolution: {integrity: sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 debug: 4.3.3 - espree: 7.3.1 + espree: 9.3.0 globals: 13.12.0 ignore: 4.0.6 import-fresh: 3.3.0 - js-yaml: 3.14.1 + js-yaml: 4.1.0 minimatch: 3.0.4 strip-json-comments: 3.1.1 transitivePeerDependencies: @@ -3780,8 +4728,8 @@ packages: through2: 2.0.5 dev: false - /@humanwhocodes/config-array/0.5.0: - resolution: {integrity: sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==} + /@humanwhocodes/config-array/0.9.3: + resolution: {integrity: sha512-3xSMlXHh03hCcCmFc0rbKp3Ivt2PFEJnQUJDDMTJQ2wkECZWdq4GePs2ctc5H8zV+cHPaq8k2vU8mrQjA6iHdQ==} engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 1.2.1 @@ -3965,7 +4913,7 @@ packages: resolution: {integrity: sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==} engines: {node: '>= 10.14.2'} dependencies: - '@babel/core': 7.16.0 + '@babel/core': 7.16.7 '@jest/types': 26.6.2 babel-plugin-istanbul: 6.1.1 chalk: 4.1.2 @@ -3982,6 +4930,7 @@ packages: write-file-atomic: 3.0.3 transitivePeerDependencies: - supports-color + dev: true /@jest/transform/27.4.6: resolution: {integrity: sha512-9MsufmJC8t5JTpWEQJ0OcOOAXaH5ioaIX6uHVBLBMoCZPfKKQF+EqP8kACAvCZ0Y1h2Zr3uOccg8re+Dr5jxyw==} @@ -5460,34 +6409,34 @@ packages: typescript: optional: true dependencies: - '@babel/core': 7.16.0 - '@babel/plugin-proposal-class-properties': 7.16.7_@babel+core@7.16.0 - '@babel/plugin-proposal-decorators': 7.16.7_@babel+core@7.16.0 - '@babel/plugin-proposal-export-default-from': 7.16.7_@babel+core@7.16.0 - '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.7_@babel+core@7.16.0 - '@babel/plugin-proposal-object-rest-spread': 7.16.7_@babel+core@7.16.0 - '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.16.0 - '@babel/plugin-proposal-private-methods': 7.16.7_@babel+core@7.16.0 - '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.16.0 - '@babel/plugin-transform-arrow-functions': 7.16.7_@babel+core@7.16.0 - '@babel/plugin-transform-block-scoping': 7.16.7_@babel+core@7.16.0 - '@babel/plugin-transform-classes': 7.16.7_@babel+core@7.16.0 - '@babel/plugin-transform-destructuring': 7.16.7_@babel+core@7.16.0 - '@babel/plugin-transform-for-of': 7.16.7_@babel+core@7.16.0 - '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.16.0 - '@babel/plugin-transform-shorthand-properties': 7.16.7_@babel+core@7.16.0 - '@babel/plugin-transform-spread': 7.16.7_@babel+core@7.16.0 - '@babel/preset-env': 7.16.7_@babel+core@7.16.0 - '@babel/preset-react': 7.16.7_@babel+core@7.16.0 - '@babel/preset-typescript': 7.16.7_@babel+core@7.16.0 - '@babel/register': 7.16.7_@babel+core@7.16.0 + '@babel/core': 7.16.7 + '@babel/plugin-proposal-class-properties': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-decorators': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-export-default-from': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-object-rest-spread': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-proposal-private-methods': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.16.7 + '@babel/plugin-transform-arrow-functions': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-block-scoping': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-classes': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-destructuring': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-for-of': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-shorthand-properties': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-spread': 7.16.7_@babel+core@7.16.7 + '@babel/preset-env': 7.16.7_@babel+core@7.16.7 + '@babel/preset-react': 7.16.7_@babel+core@7.16.7 + '@babel/preset-typescript': 7.16.7_@babel+core@7.16.7 + '@babel/register': 7.16.7_@babel+core@7.16.7 '@storybook/node-logger': 6.4.10 '@storybook/semver': 7.3.2 '@types/node': 14.18.5 '@types/pretty-hrtime': 1.0.1 - babel-loader: 8.2.3_8dd2b11efd9b7265f9b7da54f0e73ab1 + babel-loader: 8.2.3_c391fd7145c194be609b87ed083bbc6a babel-plugin-macros: 3.1.0 - babel-plugin-polyfill-corejs3: 0.1.7_@babel+core@7.16.0 + babel-plugin-polyfill-corejs3: 0.1.7_@babel+core@7.16.7 chalk: 4.1.2 core-js: 3.20.2 express: 4.17.2 @@ -5751,11 +6700,11 @@ packages: /@storybook/csf-tools/6.4.10: resolution: {integrity: sha512-2s6t1lgtHaLkAZZPZJsrU/1IQu8CUa4GpOt+nrRXph4t5vZyETY0LU8ElS1d4V4/+JHGHN6E20r+E+gSjHq+Jw==} dependencies: - '@babel/core': 7.16.0 + '@babel/core': 7.16.7 '@babel/generator': 7.16.7 '@babel/parser': 7.16.7 - '@babel/plugin-transform-react-jsx': 7.16.7_@babel+core@7.16.0 - '@babel/preset-env': 7.16.7_@babel+core@7.16.0 + '@babel/plugin-transform-react-jsx': 7.16.7_@babel+core@7.16.7 + '@babel/preset-env': 7.16.7_@babel+core@7.16.7 '@babel/traverse': 7.16.3 '@babel/types': 7.16.7 '@mdx-js/mdx': 1.6.22 @@ -6573,6 +7522,12 @@ packages: resolution: {integrity: sha512-FIX2AVmPTGP30OUJ+0vadeIFJJ07Mh1m+U0rxfgyW34p3rTlXI+nlenvAxNn4BP36YyI9IJ/+UJ7Wu22N1pI7A==} dependencies: '@types/react': 16.14.21 + dev: false + + /@types/react-dom/17.0.11: + resolution: {integrity: sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==} + dependencies: + '@types/react': 17.0.38 /@types/react-redux/7.1.21: resolution: {integrity: sha512-bLdglUiBSQNzWVVbmNPKGYYjrzp3/YDPwfOH3nLEz99I4awLlaRAPWjo6bZ2POpxztFWtDDXIPxBLVykXqBt+w==} @@ -6600,6 +7555,7 @@ packages: '@types/prop-types': 15.7.4 '@types/scheduler': 0.16.2 csstype: 3.0.10 + dev: false /@types/react/17.0.38: resolution: {integrity: sha512-SI92X1IA+FMnP3qM5m4QReluXzhcmovhZnLNm3pyeQlooi02qI7sLiepEYqT678uNiyc25XfCqxREFpy3W7YhQ==} @@ -6694,22 +7650,23 @@ packages: dev: true optional: true - /@typescript-eslint/eslint-plugin/4.33.0_2951ba233cd46bb4e0f2f0a3f7fe108e: - resolution: {integrity: sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==} - engines: {node: ^10.12.0 || >=12.0.0} + /@typescript-eslint/eslint-plugin/5.10.2_0d682450f1ef58680b7f0316f2e82e26: + resolution: {integrity: sha512-4W/9lLuE+v27O/oe7hXJKjNtBLnZE8tQAFpapdxwSVHqtmIoPB1gph3+ahNwVuNL37BX7YQHyGF9Xv6XCnIX2Q==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: - '@typescript-eslint/parser': ^4.0.0 - eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 + '@typescript-eslint/parser': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: - '@typescript-eslint/experimental-utils': 4.33.0_eslint@7.32.0 - '@typescript-eslint/parser': 4.33.0_eslint@7.32.0 - '@typescript-eslint/scope-manager': 4.33.0 + '@typescript-eslint/parser': 5.10.2_eslint@8.8.0 + '@typescript-eslint/scope-manager': 5.10.2 + '@typescript-eslint/type-utils': 5.10.2_eslint@8.8.0 + '@typescript-eslint/utils': 5.10.2_eslint@8.8.0 debug: 4.3.3 - eslint: 7.32.0 + eslint: 8.8.0 functional-red-black-tree: 1.0.1 ignore: 5.2.0 regexpp: 3.2.0 @@ -6719,20 +7676,21 @@ packages: - supports-color dev: true - /@typescript-eslint/eslint-plugin/4.33.0_8c654464cf7de6904a251c0e456613ed: - resolution: {integrity: sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==} - engines: {node: ^10.12.0 || >=12.0.0} + /@typescript-eslint/eslint-plugin/5.10.2_9b53d4b455d21bf3af38fdac900301d2: + resolution: {integrity: sha512-4W/9lLuE+v27O/oe7hXJKjNtBLnZE8tQAFpapdxwSVHqtmIoPB1gph3+ahNwVuNL37BX7YQHyGF9Xv6XCnIX2Q==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: - '@typescript-eslint/parser': ^4.0.0 - eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 + '@typescript-eslint/parser': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: - '@typescript-eslint/experimental-utils': 4.33.0_typescript@4.3.5 - '@typescript-eslint/parser': 4.33.0_typescript@4.3.5 - '@typescript-eslint/scope-manager': 4.33.0 + '@typescript-eslint/parser': 5.10.2_typescript@4.3.5 + '@typescript-eslint/scope-manager': 5.10.2 + '@typescript-eslint/type-utils': 5.10.2_typescript@4.3.5 + '@typescript-eslint/utils': 5.10.2_typescript@4.3.5 debug: 4.3.3 functional-red-black-tree: 1.0.1 ignore: 5.2.0 @@ -6744,103 +7702,117 @@ packages: - supports-color dev: true - /@typescript-eslint/experimental-utils/4.33.0_eslint@7.32.0: - resolution: {integrity: sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==} - engines: {node: ^10.12.0 || >=12.0.0} + /@typescript-eslint/experimental-utils/5.10.2_eslint@8.8.0: + resolution: {integrity: sha512-stRnIlxDduzxtaVLtEohESoXI1k7J6jvJHGyIkOT2pvXbg5whPM6f9tzJ51bJJxaJTdmvwgVFDNCopFRb2F5Gw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: - eslint: '*' + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - '@types/json-schema': 7.0.9 - '@typescript-eslint/scope-manager': 4.33.0 - '@typescript-eslint/types': 4.33.0 - '@typescript-eslint/typescript-estree': 4.33.0 - eslint: 7.32.0 - eslint-scope: 5.1.1 - eslint-utils: 3.0.0_eslint@7.32.0 + '@typescript-eslint/utils': 5.10.2_eslint@8.8.0 + eslint: 8.8.0 transitivePeerDependencies: - supports-color - typescript dev: true - /@typescript-eslint/experimental-utils/4.33.0_typescript@4.3.5: - resolution: {integrity: sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==} - engines: {node: ^10.12.0 || >=12.0.0} + /@typescript-eslint/parser/5.10.2_eslint@8.8.0: + resolution: {integrity: sha512-JaNYGkaQVhP6HNF+lkdOr2cAs2wdSZBoalE22uYWq8IEv/OVH0RksSGydk+sW8cLoSeYmC+OHvRyv2i4AQ7Czg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: - eslint: '*' + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true dependencies: - '@types/json-schema': 7.0.9 - '@typescript-eslint/scope-manager': 4.33.0 - '@typescript-eslint/types': 4.33.0 - '@typescript-eslint/typescript-estree': 4.33.0_typescript@4.3.5 - eslint-scope: 5.1.1 - eslint-utils: 3.0.0 + '@typescript-eslint/scope-manager': 5.10.2 + '@typescript-eslint/types': 5.10.2 + '@typescript-eslint/typescript-estree': 5.10.2 + debug: 4.3.3 + eslint: 8.8.0 transitivePeerDependencies: - supports-color - - typescript dev: true - /@typescript-eslint/parser/4.33.0_eslint@7.32.0: - resolution: {integrity: sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==} - engines: {node: ^10.12.0 || >=12.0.0} + /@typescript-eslint/parser/5.10.2_typescript@4.3.5: + resolution: {integrity: sha512-JaNYGkaQVhP6HNF+lkdOr2cAs2wdSZBoalE22uYWq8IEv/OVH0RksSGydk+sW8cLoSeYmC+OHvRyv2i4AQ7Czg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: - eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 4.33.0 - '@typescript-eslint/types': 4.33.0 - '@typescript-eslint/typescript-estree': 4.33.0 + '@typescript-eslint/scope-manager': 5.10.2 + '@typescript-eslint/types': 5.10.2 + '@typescript-eslint/typescript-estree': 5.10.2_typescript@4.3.5 debug: 4.3.3 - eslint: 7.32.0 + typescript: 4.3.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser/4.33.0_typescript@4.3.5: - resolution: {integrity: sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==} - engines: {node: ^10.12.0 || >=12.0.0} + /@typescript-eslint/scope-manager/5.10.2: + resolution: {integrity: sha512-39Tm6f4RoZoVUWBYr3ekS75TYgpr5Y+X0xLZxXqcZNDWZdJdYbKd3q2IR4V9y5NxxiPu/jxJ8XP7EgHiEQtFnw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.10.2 + '@typescript-eslint/visitor-keys': 5.10.2 + dev: true + + /@typescript-eslint/type-utils/5.10.2_eslint@8.8.0: + resolution: {integrity: sha512-uRKSvw/Ccs5FYEoXW04Z5VfzF2iiZcx8Fu7DGIB7RHozuP0VbKNzP1KfZkHBTM75pCpsWxIthEH1B33dmGBKHw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: - eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 + eslint: '*' typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 4.33.0 - '@typescript-eslint/types': 4.33.0 - '@typescript-eslint/typescript-estree': 4.33.0_typescript@4.3.5 + '@typescript-eslint/utils': 5.10.2_eslint@8.8.0 debug: 4.3.3 - typescript: 4.3.5 + eslint: 8.8.0 + tsutils: 3.21.0 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/scope-manager/4.33.0: - resolution: {integrity: sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==} - engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} + /@typescript-eslint/type-utils/5.10.2_typescript@4.3.5: + resolution: {integrity: sha512-uRKSvw/Ccs5FYEoXW04Z5VfzF2iiZcx8Fu7DGIB7RHozuP0VbKNzP1KfZkHBTM75pCpsWxIthEH1B33dmGBKHw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true dependencies: - '@typescript-eslint/types': 4.33.0 - '@typescript-eslint/visitor-keys': 4.33.0 + '@typescript-eslint/utils': 5.10.2_typescript@4.3.5 + debug: 4.3.3 + tsutils: 3.21.0_typescript@4.3.5 + typescript: 4.3.5 + transitivePeerDependencies: + - supports-color dev: true - /@typescript-eslint/types/4.33.0: - resolution: {integrity: sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==} - engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} + /@typescript-eslint/types/5.10.2: + resolution: {integrity: sha512-Qfp0qk/5j2Rz3p3/WhWgu4S1JtMcPgFLnmAKAW061uXxKSa7VWKZsDXVaMXh2N60CX9h6YLaBoy9PJAfCOjk3w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@typescript-eslint/typescript-estree/4.33.0: - resolution: {integrity: sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==} - engines: {node: ^10.12.0 || >=12.0.0} + /@typescript-eslint/typescript-estree/5.10.2: + resolution: {integrity: sha512-WHHw6a9vvZls6JkTgGljwCsMkv8wu8XU8WaYKeYhxhWXH/atZeiMW6uDFPLZOvzNOGmuSMvHtZKd6AuC8PrwKQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: - '@typescript-eslint/types': 4.33.0 - '@typescript-eslint/visitor-keys': 4.33.0 + '@typescript-eslint/types': 5.10.2 + '@typescript-eslint/visitor-keys': 5.10.2 debug: 4.3.3 globby: 11.1.0 is-glob: 4.0.3 @@ -6850,17 +7822,17 @@ packages: - supports-color dev: true - /@typescript-eslint/typescript-estree/4.33.0_typescript@4.3.5: - resolution: {integrity: sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==} - engines: {node: ^10.12.0 || >=12.0.0} + /@typescript-eslint/typescript-estree/5.10.2_typescript@4.3.5: + resolution: {integrity: sha512-WHHw6a9vvZls6JkTgGljwCsMkv8wu8XU8WaYKeYhxhWXH/atZeiMW6uDFPLZOvzNOGmuSMvHtZKd6AuC8PrwKQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: - '@typescript-eslint/types': 4.33.0 - '@typescript-eslint/visitor-keys': 4.33.0 + '@typescript-eslint/types': 5.10.2 + '@typescript-eslint/visitor-keys': 5.10.2 debug: 4.3.3 globby: 11.1.0 is-glob: 4.0.3 @@ -6871,12 +7843,47 @@ packages: - supports-color dev: true - /@typescript-eslint/visitor-keys/4.33.0: - resolution: {integrity: sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==} - engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} + /@typescript-eslint/utils/5.10.2_eslint@8.8.0: + resolution: {integrity: sha512-vuJaBeig1NnBRkf7q9tgMLREiYD7zsMrsN1DA3wcoMDvr3BTFiIpKjGiYZoKPllfEwN7spUjv7ZqD+JhbVjEPg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - '@typescript-eslint/types': 4.33.0 - eslint-visitor-keys: 2.1.0 + '@types/json-schema': 7.0.9 + '@typescript-eslint/scope-manager': 5.10.2 + '@typescript-eslint/types': 5.10.2 + '@typescript-eslint/typescript-estree': 5.10.2 + eslint: 8.8.0 + eslint-scope: 5.1.1 + eslint-utils: 3.0.0_eslint@8.8.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/utils/5.10.2_typescript@4.3.5: + resolution: {integrity: sha512-vuJaBeig1NnBRkf7q9tgMLREiYD7zsMrsN1DA3wcoMDvr3BTFiIpKjGiYZoKPllfEwN7spUjv7ZqD+JhbVjEPg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@types/json-schema': 7.0.9 + '@typescript-eslint/scope-manager': 5.10.2 + '@typescript-eslint/types': 5.10.2 + '@typescript-eslint/typescript-estree': 5.10.2_typescript@4.3.5 + eslint-scope: 5.1.1 + eslint-utils: 3.0.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys/5.10.2: + resolution: {integrity: sha512-zHIhYGGGrFJvvyfwHk5M08C5B5K4bewkm+rrvNTKk1/S15YHR+SA/QUF8ZWscXSfEaB8Nn2puZj+iHcoxVOD/Q==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.10.2 + eslint-visitor-keys: 3.2.0 dev: true /@ungap/promise-all-settled/1.1.2: @@ -7038,46 +8045,45 @@ packages: /@wordpress/a11y/2.15.3: resolution: {integrity: sha512-uoCznHY3/TaNWeXutLI6juC198ykaBwZ34P51PNHHQqi3WzVoBhFx6AnAR/9Uupl3tZcekefpkVHy7AJHMAPIA==} dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.16.7 '@wordpress/dom-ready': 2.13.2 '@wordpress/i18n': 3.20.0 dev: false - /@wordpress/a11y/3.2.4: - resolution: {integrity: sha512-RhDZciRy6XUx/hegJdJTgAtC/6i7DjfpUYJdy6McwvWXs56tMmCo+wBYQvC3G//+2VYdYYkwDZ8Z6eVUBSJ17w==} + /@wordpress/a11y/3.3.0: + resolution: {integrity: sha512-PiLX+4M3NZtCY/Nndn8D1naBTBJLVGokL6sFfaAGYhajiXg0KywCYILw19h6aNAxWpLREeBYpwiD3LsDrz+3Wg==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - '@wordpress/dom-ready': 3.2.3 - '@wordpress/i18n': 4.2.4 + '@wordpress/dom-ready': 3.3.0 + '@wordpress/i18n': 4.3.0 - /@wordpress/annotations/2.2.8_react@17.0.2+redux@4.0.5: - resolution: {integrity: sha512-cT+Mk6oEsSYHvaXtxO+JExCsP34Un21GahOIQK74lq1hJUy34TxqzuftbdDLvu9gbrKRnzVlPH9Uv6RHVHkXbg==} + /@wordpress/annotations/2.3.0_react@17.0.2: + resolution: {integrity: sha512-MdvQaQluQlORjPQIwpl5INocqv5q+CZd7XPWh/6tfywbE2cM1nGD2eZjcFEaRHF/akC66kAb9aqb9IE3jg9D0A==} engines: {node: '>=12'} dependencies: - '@babel/runtime': 7.16.3 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.0.5 - '@wordpress/hooks': 3.2.2 - '@wordpress/i18n': 4.2.4 - '@wordpress/rich-text': 5.0.7_react@17.0.2+redux@4.0.5 + '@babel/runtime': 7.16.7 + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/hooks': 3.3.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/rich-text': 5.1.0_react@17.0.2 lodash: 4.17.21 rememo: 3.0.0 uuid: 8.3.2 transitivePeerDependencies: - react - - redux dev: false - /@wordpress/api-fetch/5.2.6: - resolution: {integrity: sha512-AG8KdCHwtYJWR38AAU7nEI+UbumUSqSBthQj3rShLUVyFbYGkQdpwXJJG6vFj7FjIp41zljiyj3K1Fh3cqdaAw==} + /@wordpress/api-fetch/6.0.0: + resolution: {integrity: sha512-pSfqdzaOO7/SrIDkFJDhVDs0DLy1WmrtIxz4rTub+H538MolyHmUh9xs1aIyakgC9PH7DrkzVmj00d8QXBcVcw==} engines: {node: '>=12'} dependencies: - '@babel/runtime': 7.16.3 - '@wordpress/i18n': 4.2.4 - '@wordpress/url': 3.3.1 + '@babel/runtime': 7.16.7 + '@wordpress/i18n': 4.3.0 + '@wordpress/url': 3.4.0 - /@wordpress/autop/3.2.3: - resolution: {integrity: sha512-o66vC+aZPmJGMie+Emqa5gtfQYKbLXqGCESTfingXyMxXEpCa4qOEOi1D6vwX61sf3+k2qJ4bvKwJ5nZXjDaSQ==} + /@wordpress/autop/3.3.0: + resolution: {integrity: sha512-z31raAcFIw2kUqtHXMMI0iei5DoJzVXHlqmbpR6rv3J4BgXKMmvevArvvjoe2SH+M9rrjJD2GIxFsfWZ5Tvccw==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 @@ -7091,118 +8097,78 @@ packages: '@babel/core': 7.16.0 dev: true - /@wordpress/babel-preset-default/6.4.1: - resolution: {integrity: sha512-T0+dPOn0Hus/FSP043H3C2awjGNWLJcSahm7LhLqT5uUtgdg6QD9yf4jSr7G5mpLO/DXgz2ZnaYMUj+d1/gk9w==} + /@wordpress/babel-plugin-import-jsx-pragma/3.1.0_@babel+core@7.16.7: + resolution: {integrity: sha512-518mL3goaSeXtJCQcPK9OYHUUiA0sjXuoGWHBwRalkyTIQZZy5ZZzlwrlSc9ESZcOw9BZ+Uo8CJRjV2OWnx+Zw==} engines: {node: '>=12'} + peerDependencies: + '@babel/core': ^7.12.9 dependencies: - '@babel/core': 7.16.0 - '@babel/plugin-transform-react-jsx': 7.16.7_@babel+core@7.16.0 - '@babel/plugin-transform-runtime': 7.16.7_@babel+core@7.16.0 - '@babel/preset-env': 7.16.7_@babel+core@7.16.0 - '@babel/preset-typescript': 7.16.7_@babel+core@7.16.0 + '@babel/core': 7.16.7 + dev: true + + /@wordpress/babel-preset-default/6.5.0: + resolution: {integrity: sha512-F2bv78gNz8FsSP88tEabNffiynvwgepcfustDCbhXXWZoMQoTmyu+jj1h7sjriH+9lIUmfcJifKy+QstCR1Y4w==} + engines: {node: '>=12'} + dependencies: + '@babel/core': 7.16.7 + '@babel/plugin-transform-react-jsx': 7.16.7_@babel+core@7.16.7 + '@babel/plugin-transform-runtime': 7.16.7_@babel+core@7.16.7 + '@babel/preset-env': 7.16.7_@babel+core@7.16.7 + '@babel/preset-typescript': 7.16.7_@babel+core@7.16.7 '@babel/runtime': 7.16.7 - '@wordpress/babel-plugin-import-jsx-pragma': 3.1.0_@babel+core@7.16.0 + '@wordpress/babel-plugin-import-jsx-pragma': 3.1.0_@babel+core@7.16.7 '@wordpress/browserslist-config': 4.1.0 - '@wordpress/element': 4.0.4 - '@wordpress/warning': 2.2.2 + '@wordpress/element': 4.1.0 + '@wordpress/warning': 2.3.0 browserslist: 4.19.1 core-js: 3.20.2 transitivePeerDependencies: - supports-color dev: true - /@wordpress/base-styles/4.0.4: - resolution: {integrity: sha512-qXiIhWLdTHWxBWawcqigJUUMeb2jkn9ElUEUC/Cn3DK2i62jiUWXOLp6tFIaf5eQMNXsYqtp5r7n2F/OllngQA==} + /@wordpress/base-styles/4.1.0: + resolution: {integrity: sha512-rjyMWFs0WWE16w77sHffaXBFosg15iUUVpQr/H4eEElHE/JpXFZJczMbM3yx5tSH+72S3sPFVn5NYn4qHLP7Rg==} - /@wordpress/blob/3.2.2: - resolution: {integrity: sha512-uzOlmwcTtxZFBoQc6nDYdkTvPnd6QMK5GEmmrHt6Q1OYOZ6V2vOdC6w0IdynbQYpuNnaWwhyfcsTRh/+97UoRg==} + /@wordpress/blob/3.3.0: + resolution: {integrity: sha512-5kwl/Wv+LuF9sTzCCbmavlV34Vl9o+eFdwb4ILgvixxSgUzyTL02/ZcC6zcEq6wPtIzkpRm87iU5Y4SLIFZh0g==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - /@wordpress/block-editor/8.0.12_595f56c80e7e5fab2a648c0f724c83ea: - resolution: {integrity: sha512-wif8ntsph9N9s6wAh6xfEOQMzXg0uTnqaczoK01K+5gou01JILvGwaApTbWucgPDrLvU3CVW1Mt8USvBB2ujhw==} - engines: {node: '>=12'} - dependencies: - '@babel/runtime': 7.16.7 - '@react-spring/web': 9.4.1_react-dom@17.0.2+react@17.0.2 - '@wordpress/a11y': 3.2.4 - '@wordpress/api-fetch': 5.2.6 - '@wordpress/blob': 3.2.2 - '@wordpress/block-serialization-default-parser': 4.2.3 - '@wordpress/blocks': 11.1.5_react@17.0.2+redux@4.0.5 - '@wordpress/components': 19.2.0_595f56c80e7e5fab2a648c0f724c83ea - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.0.5 - '@wordpress/deprecated': 3.2.3 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/html-entities': 3.2.3 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keyboard-shortcuts': 3.0.7_react@17.0.2+redux@4.0.5 - '@wordpress/keycodes': 3.2.4 - '@wordpress/notices': 3.2.8_react@17.0.2+redux@4.0.5 - '@wordpress/rich-text': 5.0.7_react@17.0.2+redux@4.0.5 - '@wordpress/shortcode': 3.2.3 - '@wordpress/token-list': 2.2.2 - '@wordpress/url': 3.3.1 - '@wordpress/warning': 2.2.2 - '@wordpress/wordcount': 3.2.3 - classnames: 2.3.1 - colord: 2.9.2 - css-mediaquery: 0.1.2 - diff: 4.0.2 - dom-scroll-into-view: 1.2.1 - inherits: 2.0.4 - lodash: 4.17.21 - memize: 1.1.0 - react-autosize-textarea: 7.1.0_react-dom@17.0.2+react@17.0.2 - react-easy-crop: 3.5.3_react-dom@17.0.2+react@17.0.2 - redux-multi: 0.1.12 - rememo: 3.0.0 - traverse: 0.6.6 - transitivePeerDependencies: - - '@babel/core' - - '@types/react' - - react - - react-dom - - reakit-utils - - redux - - /@wordpress/block-editor/8.0.12_@babel+core@7.16.0+react@17.0.2: - resolution: {integrity: sha512-wif8ntsph9N9s6wAh6xfEOQMzXg0uTnqaczoK01K+5gou01JILvGwaApTbWucgPDrLvU3CVW1Mt8USvBB2ujhw==} + /@wordpress/block-editor/8.1.0_@babel+core@7.16.0+react@17.0.2: + resolution: {integrity: sha512-/Qw/N2e8OuEZoh1Wt7LfeiNNGIjQ0nuo/lfO0HfJnAyspQSfB3fVByAl7cODPOLxmFbbfRg00JVyyybguueyrg==} engines: {node: '>=12'} + peerDependencies: + react: ^17.0.0 + react-dom: ^17.0.0 dependencies: '@babel/runtime': 7.16.7 '@react-spring/web': 9.4.1_react@17.0.2 - '@wordpress/a11y': 3.2.4 - '@wordpress/api-fetch': 5.2.6 - '@wordpress/blob': 3.2.2 - '@wordpress/block-serialization-default-parser': 4.2.3 - '@wordpress/blocks': 11.1.5_react@17.0.2 - '@wordpress/components': 19.2.0_@babel+core@7.16.0+react@17.0.2 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2 - '@wordpress/deprecated': 3.2.3 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/html-entities': 3.2.3 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keyboard-shortcuts': 3.0.7_react@17.0.2 - '@wordpress/keycodes': 3.2.4 - '@wordpress/notices': 3.2.8_react@17.0.2 - '@wordpress/rich-text': 5.0.7_react@17.0.2 - '@wordpress/shortcode': 3.2.3 - '@wordpress/token-list': 2.2.2 - '@wordpress/url': 3.3.1 - '@wordpress/warning': 2.2.2 - '@wordpress/wordcount': 3.2.3 + '@wordpress/a11y': 3.3.0 + '@wordpress/api-fetch': 6.0.0 + '@wordpress/blob': 3.3.0 + '@wordpress/block-serialization-default-parser': 4.3.0 + '@wordpress/blocks': 11.2.0_react@17.0.2 + '@wordpress/components': 19.3.0_@babel+core@7.16.0+react@17.0.2 + '@wordpress/compose': 5.1.0_react@17.0.2 + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/deprecated': 3.3.0 + '@wordpress/dom': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/hooks': 3.3.0 + '@wordpress/html-entities': 3.3.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/icons': 6.2.0 + '@wordpress/is-shallow-equal': 4.3.0 + '@wordpress/keyboard-shortcuts': 3.1.0_react@17.0.2 + '@wordpress/keycodes': 3.3.0 + '@wordpress/notices': 3.3.0_react@17.0.2 + '@wordpress/rich-text': 5.1.0_react@17.0.2 + '@wordpress/shortcode': 3.3.0 + '@wordpress/token-list': 2.3.0 + '@wordpress/url': 3.4.0 + '@wordpress/warning': 2.3.0 + '@wordpress/wordcount': 3.3.0 classnames: 2.3.1 colord: 2.9.2 css-mediaquery: 0.1.2 @@ -7211,6 +8177,7 @@ packages: inherits: 2.0.4 lodash: 4.17.21 memize: 1.1.0 + react: 17.0.2 react-autosize-textarea: 7.1.0_react@17.0.2 react-easy-crop: 3.5.3_react@17.0.2 redux-multi: 0.1.12 @@ -7219,96 +8186,42 @@ packages: transitivePeerDependencies: - '@babel/core' - '@types/react' - - react - - react-dom - - reakit-utils - - redux dev: true - /@wordpress/block-editor/8.0.12_b4e1ce88a10f1ab0bbeb2b9720317029: - resolution: {integrity: sha512-wif8ntsph9N9s6wAh6xfEOQMzXg0uTnqaczoK01K+5gou01JILvGwaApTbWucgPDrLvU3CVW1Mt8USvBB2ujhw==} - engines: {node: '>=12'} - dependencies: - '@babel/runtime': 7.16.7 - '@react-spring/web': 9.4.1_react-dom@17.0.2+react@17.0.2 - '@wordpress/a11y': 3.2.4 - '@wordpress/api-fetch': 5.2.6 - '@wordpress/blob': 3.2.2 - '@wordpress/block-serialization-default-parser': 4.2.3 - '@wordpress/blocks': 11.1.5_react@17.0.2+redux@4.1.1 - '@wordpress/components': 19.2.0_b4e1ce88a10f1ab0bbeb2b9720317029 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.1.1 - '@wordpress/deprecated': 3.2.3 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/html-entities': 3.2.3 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keyboard-shortcuts': 3.0.7_react@17.0.2+redux@4.1.1 - '@wordpress/keycodes': 3.2.4 - '@wordpress/notices': 3.2.8_react@17.0.2+redux@4.1.1 - '@wordpress/rich-text': 5.0.7_react@17.0.2+redux@4.1.1 - '@wordpress/shortcode': 3.2.3 - '@wordpress/token-list': 2.2.2 - '@wordpress/url': 3.3.1 - '@wordpress/warning': 2.2.2 - '@wordpress/wordcount': 3.2.3 - classnames: 2.3.1 - colord: 2.9.2 - css-mediaquery: 0.1.2 - diff: 4.0.2 - dom-scroll-into-view: 1.2.1 - inherits: 2.0.4 - lodash: 4.17.21 - memize: 1.1.0 - react-autosize-textarea: 7.1.0_react-dom@17.0.2+react@17.0.2 - react-easy-crop: 3.5.3_react-dom@17.0.2+react@17.0.2 - redux-multi: 0.1.12 - rememo: 3.0.0 - traverse: 0.6.6 - transitivePeerDependencies: - - '@babel/core' - - '@types/react' - - react - - react-dom - - reakit-utils - - redux - dev: false - - /@wordpress/block-editor/8.0.13_595f56c80e7e5fab2a648c0f724c83ea: - resolution: {integrity: sha512-U/0Hj6wwayOFqBZg8ObR6XaDMpEnq1PXsNemxKp4BhLixiBDKMC0eXC0kBQJYm6BouMVwiw2r0StIyvl+XFovA==} + /@wordpress/block-editor/8.1.0_aae888dfa296766acacf1a733aa50b3a: + resolution: {integrity: sha512-/Qw/N2e8OuEZoh1Wt7LfeiNNGIjQ0nuo/lfO0HfJnAyspQSfB3fVByAl7cODPOLxmFbbfRg00JVyyybguueyrg==} engines: {node: '>=12'} + peerDependencies: + react: ^17.0.0 + react-dom: ^17.0.0 dependencies: '@babel/runtime': 7.16.7 '@react-spring/web': 9.4.1_react-dom@17.0.2+react@17.0.2 - '@wordpress/a11y': 3.2.4 - '@wordpress/api-fetch': 5.2.6 - '@wordpress/blob': 3.2.2 - '@wordpress/block-serialization-default-parser': 4.2.3 - '@wordpress/blocks': 11.1.5_react@17.0.2+redux@4.0.5 - '@wordpress/components': 19.2.0_595f56c80e7e5fab2a648c0f724c83ea - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.0.5 - '@wordpress/deprecated': 3.2.3 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/html-entities': 3.2.3 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keyboard-shortcuts': 3.0.7_react@17.0.2+redux@4.0.5 - '@wordpress/keycodes': 3.2.4 - '@wordpress/notices': 3.2.8_react@17.0.2+redux@4.0.5 - '@wordpress/rich-text': 5.0.7_react@17.0.2+redux@4.0.5 - '@wordpress/shortcode': 3.2.3 - '@wordpress/token-list': 2.2.2 - '@wordpress/url': 3.3.1 - '@wordpress/warning': 2.2.2 - '@wordpress/wordcount': 3.2.3 + '@wordpress/a11y': 3.3.0 + '@wordpress/api-fetch': 6.0.0 + '@wordpress/blob': 3.3.0 + '@wordpress/block-serialization-default-parser': 4.3.0 + '@wordpress/blocks': 11.2.0_react@17.0.2 + '@wordpress/components': 19.3.0_aae888dfa296766acacf1a733aa50b3a + '@wordpress/compose': 5.1.0_react@17.0.2 + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/deprecated': 3.3.0 + '@wordpress/dom': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/hooks': 3.3.0 + '@wordpress/html-entities': 3.3.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/icons': 6.2.0 + '@wordpress/is-shallow-equal': 4.3.0 + '@wordpress/keyboard-shortcuts': 3.1.0_react@17.0.2 + '@wordpress/keycodes': 3.3.0 + '@wordpress/notices': 3.3.0_react@17.0.2 + '@wordpress/rich-text': 5.1.0_react@17.0.2 + '@wordpress/shortcode': 3.3.0 + '@wordpress/token-list': 2.3.0 + '@wordpress/url': 3.4.0 + '@wordpress/warning': 2.3.0 + '@wordpress/wordcount': 3.3.0 classnames: 2.3.1 colord: 2.9.2 css-mediaquery: 0.1.2 @@ -7317,7 +8230,9 @@ packages: inherits: 2.0.4 lodash: 4.17.21 memize: 1.1.0 + react: 17.0.2 react-autosize-textarea: 7.1.0_react-dom@17.0.2+react@17.0.2 + react-dom: 17.0.2_react@17.0.2 react-easy-crop: 3.5.3_react-dom@17.0.2+react@17.0.2 redux-multi: 0.1.12 rememo: 3.0.0 @@ -7325,99 +8240,40 @@ packages: transitivePeerDependencies: - '@babel/core' - '@types/react' - - react - - react-dom - - reakit-utils - - redux - dev: true - - /@wordpress/block-editor/8.0.13_@babel+core@7.16.0+react@17.0.2: - resolution: {integrity: sha512-U/0Hj6wwayOFqBZg8ObR6XaDMpEnq1PXsNemxKp4BhLixiBDKMC0eXC0kBQJYm6BouMVwiw2r0StIyvl+XFovA==} - engines: {node: '>=12'} - dependencies: - '@babel/runtime': 7.16.7 - '@react-spring/web': 9.4.1_react@17.0.2 - '@wordpress/a11y': 3.2.4 - '@wordpress/api-fetch': 5.2.6 - '@wordpress/blob': 3.2.2 - '@wordpress/block-serialization-default-parser': 4.2.3 - '@wordpress/blocks': 11.1.5_react@17.0.2 - '@wordpress/components': 19.2.0_@babel+core@7.16.0+react@17.0.2 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2 - '@wordpress/deprecated': 3.2.3 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/html-entities': 3.2.3 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keyboard-shortcuts': 3.0.7_react@17.0.2 - '@wordpress/keycodes': 3.2.4 - '@wordpress/notices': 3.2.8_react@17.0.2 - '@wordpress/rich-text': 5.0.7_react@17.0.2 - '@wordpress/shortcode': 3.2.3 - '@wordpress/token-list': 2.2.2 - '@wordpress/url': 3.3.1 - '@wordpress/warning': 2.2.2 - '@wordpress/wordcount': 3.2.3 - classnames: 2.3.1 - colord: 2.9.2 - css-mediaquery: 0.1.2 - diff: 4.0.2 - dom-scroll-into-view: 1.2.1 - inherits: 2.0.4 - lodash: 4.17.21 - memize: 1.1.0 - react-autosize-textarea: 7.1.0_react@17.0.2 - react-easy-crop: 3.5.3_react@17.0.2 - redux-multi: 0.1.12 - rememo: 3.0.0 - traverse: 0.6.6 - transitivePeerDependencies: - - '@babel/core' - - '@types/react' - - react - - react-dom - - reakit-utils - - redux - dev: true - /@wordpress/block-library/6.0.17_@babel+core@7.16.0+react@17.0.2: - resolution: {integrity: sha512-/YC1eOHcb5ZokSODx04rcA5Qco3EDi3nIVZVyx1VMeJHxWB+qaYb49dnliqvnG/A5DoaEJeV5YsOMMbHbz914Q==} + /@wordpress/block-library/6.1.0_@babel+core@7.16.0+react@17.0.2: + resolution: {integrity: sha512-HFN/ZFOd2ZFoIz6a34q9jLWVXqZRkuv0aYO0CDRLxMfuULMRYuCOwHvEVSF5ObaKX2+0Z0czy1V08vKANb/UVA==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - '@wordpress/a11y': 3.2.4 - '@wordpress/api-fetch': 5.2.6 - '@wordpress/autop': 3.2.3 - '@wordpress/blob': 3.2.2 - '@wordpress/block-editor': 8.0.12_@babel+core@7.16.0+react@17.0.2 - '@wordpress/blocks': 11.1.5_react@17.0.2 - '@wordpress/components': 19.1.6_@babel+core@7.16.0+react@17.0.2 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/core-data': 4.0.9_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2 - '@wordpress/date': 4.2.3 - '@wordpress/deprecated': 3.2.3 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/escape-html': 2.2.3 - '@wordpress/hooks': 3.2.2 - '@wordpress/html-entities': 3.2.3 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/interface': 4.1.15_@babel+core@7.16.0+react@17.0.2 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keycodes': 3.2.4 - '@wordpress/notices': 3.2.8_react@17.0.2 - '@wordpress/primitives': 3.0.4 - '@wordpress/reusable-blocks': 3.0.19_@babel+core@7.16.0+react@17.0.2 - '@wordpress/rich-text': 5.0.7_react@17.0.2 - '@wordpress/server-side-render': 3.0.17_@babel+core@7.16.0+react@17.0.2 - '@wordpress/url': 3.3.1 - '@wordpress/viewport': 4.0.7_react@17.0.2 + '@wordpress/a11y': 3.3.0 + '@wordpress/api-fetch': 6.0.0 + '@wordpress/autop': 3.3.0 + '@wordpress/blob': 3.3.0 + '@wordpress/block-editor': 8.1.0_@babel+core@7.16.0+react@17.0.2 + '@wordpress/blocks': 11.2.0_react@17.0.2 + '@wordpress/components': 19.3.0_@babel+core@7.16.0+react@17.0.2 + '@wordpress/compose': 5.1.0_react@17.0.2 + '@wordpress/core-data': 4.1.0_react@17.0.2 + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/date': 4.3.0 + '@wordpress/deprecated': 3.3.0 + '@wordpress/dom': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/escape-html': 2.3.0 + '@wordpress/hooks': 3.3.0 + '@wordpress/html-entities': 3.3.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/icons': 6.2.0 + '@wordpress/is-shallow-equal': 4.3.0 + '@wordpress/keycodes': 3.3.0 + '@wordpress/notices': 3.3.0_react@17.0.2 + '@wordpress/primitives': 3.1.0 + '@wordpress/reusable-blocks': 3.1.0_@babel+core@7.16.0+react@17.0.2 + '@wordpress/rich-text': 5.1.0_react@17.0.2 + '@wordpress/server-side-render': 3.1.0_@babel+core@7.16.0+react@17.0.2 + '@wordpress/url': 3.4.0 + '@wordpress/viewport': 4.1.0_react@17.0.2 classnames: 2.3.1 colord: 2.9.2 fast-average-color: 4.3.0 @@ -7430,93 +8286,32 @@ packages: - '@types/react' - react - react-dom - - reakit-utils - - redux dev: true - /@wordpress/block-serialization-default-parser/4.2.3: - resolution: {integrity: sha512-VAgRRijd/gZ0ET7lXXEG4/efK5zaBH4RqFV2VJsnuNDQe8CmtmHoCxQC2cUHHhnm9KpubffvVtK+R0mscSmH2Q==} + /@wordpress/block-serialization-default-parser/4.3.0: + resolution: {integrity: sha512-7wydVvSKp3ZOaYxrzZBWZXr+/yQQyNKaxarmoHsa4aF9Vu6YMMzrF38IUJrHsaFX1pYK/zq/nleEq+HUDi6isQ==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - /@wordpress/blocks/11.1.5_react@17.0.2: - resolution: {integrity: sha512-r4xNTQPpUqJ7vqsJqH4D5+GeRQVOLF+9dkeNxkKQnJSFZ5y6POd28d0gMsOcTdGtAzXN6sak104DaKry2SWQNA==} - engines: {node: '>=12'} - dependencies: - '@babel/runtime': 7.16.3 - '@wordpress/autop': 3.2.3 - '@wordpress/blob': 3.2.2 - '@wordpress/block-serialization-default-parser': 4.2.3 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2 - '@wordpress/deprecated': 3.2.3 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/html-entities': 3.2.3 - '@wordpress/i18n': 4.2.4 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/shortcode': 3.2.3 - colord: 2.9.2 - hpq: 1.3.0 - lodash: 4.17.21 - rememo: 3.0.0 - showdown: 1.9.1 - simple-html-tokenizer: 0.5.11 - uuid: 8.3.2 - transitivePeerDependencies: - - react - - redux - dev: true - - /@wordpress/blocks/11.1.5_react@17.0.2+redux@4.0.5: - resolution: {integrity: sha512-r4xNTQPpUqJ7vqsJqH4D5+GeRQVOLF+9dkeNxkKQnJSFZ5y6POd28d0gMsOcTdGtAzXN6sak104DaKry2SWQNA==} - engines: {node: '>=12'} - dependencies: - '@babel/runtime': 7.16.3 - '@wordpress/autop': 3.2.3 - '@wordpress/blob': 3.2.2 - '@wordpress/block-serialization-default-parser': 4.2.3 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.0.5 - '@wordpress/deprecated': 3.2.3 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/html-entities': 3.2.3 - '@wordpress/i18n': 4.2.4 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/shortcode': 3.2.3 - colord: 2.9.2 - hpq: 1.3.0 - lodash: 4.17.21 - rememo: 3.0.0 - showdown: 1.9.1 - simple-html-tokenizer: 0.5.11 - uuid: 8.3.2 - transitivePeerDependencies: - - react - - redux - - /@wordpress/blocks/11.1.5_react@17.0.2+redux@4.1.1: - resolution: {integrity: sha512-r4xNTQPpUqJ7vqsJqH4D5+GeRQVOLF+9dkeNxkKQnJSFZ5y6POd28d0gMsOcTdGtAzXN6sak104DaKry2SWQNA==} + /@wordpress/blocks/11.2.0_react@17.0.2: + resolution: {integrity: sha512-8/ES5wm38/Ydo7Zol4lZT4xlLxE05fLrgjysE14hMBZUYUivqJFRhYxoSrMHW03LBmUUi2fYcdrCh+JRLGbLuw==} engines: {node: '>=12'} dependencies: - '@babel/runtime': 7.16.3 - '@wordpress/autop': 3.2.3 - '@wordpress/blob': 3.2.2 - '@wordpress/block-serialization-default-parser': 4.2.3 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.1.1 - '@wordpress/deprecated': 3.2.3 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/html-entities': 3.2.3 - '@wordpress/i18n': 4.2.4 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/shortcode': 3.2.3 + '@babel/runtime': 7.16.7 + '@wordpress/autop': 3.3.0 + '@wordpress/blob': 3.3.0 + '@wordpress/block-serialization-default-parser': 4.3.0 + '@wordpress/compose': 5.1.0_react@17.0.2 + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/deprecated': 3.3.0 + '@wordpress/dom': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/hooks': 3.3.0 + '@wordpress/html-entities': 3.3.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/is-shallow-equal': 4.3.0 + '@wordpress/shortcode': 3.3.0 colord: 2.9.2 hpq: 1.3.0 lodash: 4.17.21 @@ -7526,349 +8321,142 @@ packages: uuid: 8.3.2 transitivePeerDependencies: - react - - redux - dev: false /@wordpress/browserslist-config/4.1.0: resolution: {integrity: sha512-RSJhgY2xmz6yAdDNhz/NvAO6JS+91vv9cVL7VDG2CftbyjTXBef05vWt3FzZhfeF0xUrYdpZL1PVpxmJiKvbEg==} engines: {node: '>=12'} - /@wordpress/components/12.0.9_b23a2df06df1cb7d0e5a2ce752eda4cf: + /@wordpress/components/12.0.9_d6aa0d5b77ebdc587ad2683e8fb8389a: resolution: {integrity: sha512-J6uM20Jpchr/NywQmAeVqx/LohwKizi2F8HylqN1Xt2mYzuOrDirlEhQT1wmfqiEqEt0l+mefZEBlxeknMfBag==} dependencies: '@babel/runtime': 7.16.3 '@emotion/core': 10.3.1_react@17.0.2 - '@emotion/css': 10.0.27 - '@emotion/native': 10.0.27_316248eb6686a2fd4fbadcfd00de37f3 - '@emotion/styled': 10.3.0_316248eb6686a2fd4fbadcfd00de37f3 - '@wordpress/a11y': 2.15.3 - '@wordpress/compose': 3.25.3_react@17.0.2 - '@wordpress/date': 3.15.1 - '@wordpress/deprecated': 2.12.3 - '@wordpress/dom': 2.18.0 - '@wordpress/element': 2.20.3 - '@wordpress/hooks': 2.12.3 - '@wordpress/i18n': 3.20.0 - '@wordpress/icons': 2.10.3 - '@wordpress/is-shallow-equal': 3.1.3 - '@wordpress/keycodes': 2.19.3 - '@wordpress/primitives': 1.12.3 - '@wordpress/rich-text': 3.25.3_react@17.0.2 - '@wordpress/warning': 1.4.2 - '@wp-g2/components': 0.0.140_39aa9b824a3099e0a8f080749de9ea5d - '@wp-g2/context': 0.0.140_a53271638ee60ee853e0b95b95bb3a79 - '@wp-g2/styles': 0.0.140_a53271638ee60ee853e0b95b95bb3a79 - '@wp-g2/utils': 0.0.140_react-dom@17.0.2+react@17.0.2 - classnames: 2.3.1 - dom-scroll-into-view: 1.2.1 - downshift: 6.1.7_react@17.0.2 - gradient-parser: 0.1.5 - highlight-words-core: 1.2.2 - lodash: 4.17.21 - memize: 1.1.0 - moment: 2.29.1 - re-resizable: 6.9.1_react-dom@17.0.2+react@17.0.2 - react-dates: 17.2.0_d0804d3726ad84366bcc42e494508e1e - react-merge-refs: 1.1.0 - react-resize-aware: 3.1.1_react@17.0.2 - react-spring: 8.0.27_react-dom@17.0.2+react@17.0.2 - react-use-gesture: 9.1.3_react@17.0.2 - reakit: 1.3.11_react-dom@17.0.2+react@17.0.2 - rememo: 3.0.0 - tinycolor2: 1.4.2 - uuid: 8.3.2 - transitivePeerDependencies: - - '@types/react' - - '@wordpress/data' - - react - - react-dom - - react-native - dev: false - - /@wordpress/components/19.1.6_595f56c80e7e5fab2a648c0f724c83ea: - resolution: {integrity: sha512-+Vmj+w7aLudXUzBdAOA/1a/RKoFvVSckGfuF/qpsFCVv80t2a22sgG8ZVnjm6f+L5dcCQdr3xgvqyRgE4lOvqQ==} - engines: {node: '>=12'} - peerDependencies: - reakit-utils: ^0.15.1 - dependencies: - '@babel/runtime': 7.16.7 - '@emotion/cache': 11.7.1 - '@emotion/css': 11.7.1_@babel+core@7.16.0 - '@emotion/react': 11.7.1_@babel+core@7.16.0+react@17.0.2 - '@emotion/styled': 11.6.0_0ab14c9fee32f6b27cdf64a62c8d8465 - '@emotion/utils': 1.0.0 - '@wordpress/a11y': 3.2.4 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/date': 4.2.3 - '@wordpress/deprecated': 3.2.3 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keycodes': 3.2.4 - '@wordpress/primitives': 3.0.4 - '@wordpress/rich-text': 5.0.7_react@17.0.2+redux@4.0.5 - '@wordpress/warning': 2.2.2 - classnames: 2.3.1 - colord: 2.9.2 - dom-scroll-into-view: 1.2.1 - downshift: 6.1.7_react@17.0.2 - framer-motion: 4.1.17_react-dom@17.0.2+react@17.0.2 - gradient-parser: 0.1.5 - highlight-words-core: 1.2.2 - lodash: 4.17.21 - memize: 1.1.0 - moment: 2.29.1 - re-resizable: 6.9.1_react-dom@17.0.2+react@17.0.2 - react-colorful: 5.5.1_react-dom@17.0.2+react@17.0.2 - react-dates: 17.2.0_d0804d3726ad84366bcc42e494508e1e - react-resize-aware: 3.1.1_react@17.0.2 - react-use-gesture: 9.1.3_react@17.0.2 - reakit: 1.3.11_react-dom@17.0.2+react@17.0.2 - rememo: 3.0.0 - uuid: 8.3.2 - transitivePeerDependencies: - - '@babel/core' - - '@types/react' - - react - - react-dom - - redux - dev: true - - /@wordpress/components/19.1.6_@babel+core@7.16.0: - resolution: {integrity: sha512-+Vmj+w7aLudXUzBdAOA/1a/RKoFvVSckGfuF/qpsFCVv80t2a22sgG8ZVnjm6f+L5dcCQdr3xgvqyRgE4lOvqQ==} - engines: {node: '>=12'} - peerDependencies: - reakit-utils: ^0.15.1 - dependencies: - '@babel/runtime': 7.16.7 - '@emotion/cache': 11.7.1 - '@emotion/css': 11.7.1_@babel+core@7.16.0 - '@emotion/react': 11.7.1_@babel+core@7.16.0 - '@emotion/styled': 11.6.0_6ec88188b67a9243b8ff91fb3d96cf5c - '@emotion/utils': 1.0.0 - '@wordpress/a11y': 3.2.4 - '@wordpress/compose': 5.0.7 - '@wordpress/date': 4.2.3 - '@wordpress/deprecated': 3.2.3 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keycodes': 3.2.4 - '@wordpress/primitives': 3.0.4 - '@wordpress/rich-text': 5.0.7 - '@wordpress/warning': 2.2.2 - classnames: 2.3.1 - colord: 2.9.2 - dom-scroll-into-view: 1.2.1 - downshift: 6.1.7 - framer-motion: 4.1.17 - gradient-parser: 0.1.5 - highlight-words-core: 1.2.2 - lodash: 4.17.21 - memize: 1.1.0 - moment: 2.29.1 - re-resizable: 6.9.1 - react-colorful: 5.5.1 - react-dates: 17.2.0_moment@2.29.1 - react-resize-aware: 3.1.1 - react-use-gesture: 9.1.3 - reakit: 1.3.11 - rememo: 3.0.0 - uuid: 8.3.2 - transitivePeerDependencies: - - '@babel/core' - - '@types/react' - - react - - react-dom - - redux - dev: false - - /@wordpress/components/19.1.6_@babel+core@7.16.0+react@17.0.2: - resolution: {integrity: sha512-+Vmj+w7aLudXUzBdAOA/1a/RKoFvVSckGfuF/qpsFCVv80t2a22sgG8ZVnjm6f+L5dcCQdr3xgvqyRgE4lOvqQ==} - engines: {node: '>=12'} - peerDependencies: - reakit-utils: ^0.15.1 - dependencies: - '@babel/runtime': 7.16.7 - '@emotion/cache': 11.7.1 - '@emotion/css': 11.7.1_@babel+core@7.16.0 - '@emotion/react': 11.7.1_@babel+core@7.16.0+react@17.0.2 - '@emotion/styled': 11.6.0_0ab14c9fee32f6b27cdf64a62c8d8465 - '@emotion/utils': 1.0.0 - '@wordpress/a11y': 3.2.4 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/date': 4.2.3 - '@wordpress/deprecated': 3.2.3 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keycodes': 3.2.4 - '@wordpress/primitives': 3.0.4 - '@wordpress/rich-text': 5.0.7_react@17.0.2 - '@wordpress/warning': 2.2.2 - classnames: 2.3.1 - colord: 2.9.2 - dom-scroll-into-view: 1.2.1 - downshift: 6.1.7_react@17.0.2 - framer-motion: 4.1.17_react@17.0.2 - gradient-parser: 0.1.5 - highlight-words-core: 1.2.2 - lodash: 4.17.21 - memize: 1.1.0 - moment: 2.29.1 - re-resizable: 6.9.1_react@17.0.2 - react-colorful: 5.5.1_react@17.0.2 - react-dates: 17.2.0_moment@2.29.1+react@17.0.2 - react-resize-aware: 3.1.1_react@17.0.2 - react-use-gesture: 9.1.3_react@17.0.2 - reakit: 1.3.11_react@17.0.2 - rememo: 3.0.0 - uuid: 8.3.2 - transitivePeerDependencies: - - '@babel/core' - - '@types/react' - - react - - react-dom - - redux - - /@wordpress/components/19.1.6_aae888dfa296766acacf1a733aa50b3a: - resolution: {integrity: sha512-+Vmj+w7aLudXUzBdAOA/1a/RKoFvVSckGfuF/qpsFCVv80t2a22sgG8ZVnjm6f+L5dcCQdr3xgvqyRgE4lOvqQ==} - engines: {node: '>=12'} - peerDependencies: - reakit-utils: ^0.15.1 - dependencies: - '@babel/runtime': 7.16.7 - '@emotion/cache': 11.7.1 - '@emotion/css': 11.7.1_@babel+core@7.16.0 - '@emotion/react': 11.7.1_@babel+core@7.16.0+react@17.0.2 - '@emotion/styled': 11.6.0_0ab14c9fee32f6b27cdf64a62c8d8465 - '@emotion/utils': 1.0.0 - '@wordpress/a11y': 3.2.4 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/date': 4.2.3 - '@wordpress/deprecated': 3.2.3 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keycodes': 3.2.4 - '@wordpress/primitives': 3.0.4 - '@wordpress/rich-text': 5.0.7_react@17.0.2 - '@wordpress/warning': 2.2.2 + '@emotion/css': 10.0.27 + '@emotion/native': 10.0.27_316248eb6686a2fd4fbadcfd00de37f3 + '@emotion/styled': 10.3.0_316248eb6686a2fd4fbadcfd00de37f3 + '@wordpress/a11y': 2.15.3 + '@wordpress/compose': 3.25.3_react@17.0.2 + '@wordpress/date': 3.15.1 + '@wordpress/deprecated': 2.12.3 + '@wordpress/dom': 2.18.0 + '@wordpress/element': 2.20.3 + '@wordpress/hooks': 2.12.3 + '@wordpress/i18n': 3.20.0 + '@wordpress/icons': 2.10.3 + '@wordpress/is-shallow-equal': 3.1.3 + '@wordpress/keycodes': 2.19.3 + '@wordpress/primitives': 1.12.3 + '@wordpress/rich-text': 3.25.3_react@17.0.2 + '@wordpress/warning': 1.4.2 + '@wp-g2/components': 0.0.140_cbbf6db973bdf4a4a0954a832637d63f + '@wp-g2/context': 0.0.140_9be7e7b1381639c021accc00fc2a2b0f + '@wp-g2/styles': 0.0.140_9be7e7b1381639c021accc00fc2a2b0f + '@wp-g2/utils': 0.0.140_react-dom@17.0.2+react@17.0.2 classnames: 2.3.1 - colord: 2.9.2 dom-scroll-into-view: 1.2.1 downshift: 6.1.7_react@17.0.2 - framer-motion: 4.1.17_react-dom@17.0.2+react@17.0.2 gradient-parser: 0.1.5 highlight-words-core: 1.2.2 lodash: 4.17.21 memize: 1.1.0 moment: 2.29.1 re-resizable: 6.9.1_react-dom@17.0.2+react@17.0.2 - react-colorful: 5.5.1_react-dom@17.0.2+react@17.0.2 react-dates: 17.2.0_d0804d3726ad84366bcc42e494508e1e + react-merge-refs: 1.1.0 react-resize-aware: 3.1.1_react@17.0.2 + react-spring: 8.0.27_react-dom@17.0.2+react@17.0.2 react-use-gesture: 9.1.3_react@17.0.2 reakit: 1.3.11_react-dom@17.0.2+react@17.0.2 rememo: 3.0.0 + tinycolor2: 1.4.2 uuid: 8.3.2 transitivePeerDependencies: - - '@babel/core' - '@types/react' + - '@wordpress/data' - react - react-dom - - redux + - react-native dev: false - /@wordpress/components/19.2.0_595f56c80e7e5fab2a648c0f724c83ea: - resolution: {integrity: sha512-IFvbH7Jo9jqbH+ZXCMm+tLaJDn95Q783aNtm9GVA+z3nJSyh4Dl2MXsRfOSE/mLd2iToPDCrpuHi51hr/lrGcw==} + /@wordpress/components/19.3.0_@babel+core@7.16.0: + resolution: {integrity: sha512-uzw6LMPVQUC25NKNqcgC4Xe6pD/Jz9LwA+U3IVbpzE2OIPj6Ko+ghfpQpknc+ZS7+8wtePLlA/YaQrI8R7X2vA==} engines: {node: '>=12'} peerDependencies: - reakit-utils: ^0.15.1 + react: ^17.0.0 + react-dom: ^17.0.0 dependencies: '@babel/runtime': 7.16.7 '@emotion/cache': 11.7.1 '@emotion/css': 11.7.1_@babel+core@7.16.0 - '@emotion/react': 11.7.1_@babel+core@7.16.0+react@17.0.2 - '@emotion/styled': 11.6.0_0ab14c9fee32f6b27cdf64a62c8d8465 + '@emotion/react': 11.7.1_@babel+core@7.16.0 + '@emotion/serialize': 1.0.2 + '@emotion/styled': 11.6.0_6ec88188b67a9243b8ff91fb3d96cf5c '@emotion/utils': 1.0.0 - '@wordpress/a11y': 3.2.4 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/date': 4.2.3 - '@wordpress/deprecated': 3.2.3 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keycodes': 3.2.4 - '@wordpress/primitives': 3.0.4 - '@wordpress/rich-text': 5.0.7_react@17.0.2+redux@4.0.5 - '@wordpress/warning': 2.2.2 + '@wordpress/a11y': 3.3.0 + '@wordpress/compose': 5.1.0 + '@wordpress/date': 4.3.0 + '@wordpress/deprecated': 3.3.0 + '@wordpress/dom': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/hooks': 3.3.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/icons': 6.2.0 + '@wordpress/is-shallow-equal': 4.3.0 + '@wordpress/keycodes': 3.3.0 + '@wordpress/primitives': 3.1.0 + '@wordpress/rich-text': 5.1.0 + '@wordpress/warning': 2.3.0 classnames: 2.3.1 colord: 2.9.2 dom-scroll-into-view: 1.2.1 - downshift: 6.1.7_react@17.0.2 - framer-motion: 4.1.17_react-dom@17.0.2+react@17.0.2 + downshift: 6.1.7 + framer-motion: 4.1.17 gradient-parser: 0.1.5 highlight-words-core: 1.2.2 lodash: 4.17.21 memize: 1.1.0 moment: 2.29.1 - re-resizable: 6.9.1_react-dom@17.0.2+react@17.0.2 - react-colorful: 5.5.1_react-dom@17.0.2+react@17.0.2 - react-dates: 17.2.0_d0804d3726ad84366bcc42e494508e1e - react-resize-aware: 3.1.1_react@17.0.2 - react-use-gesture: 9.1.3_react@17.0.2 - reakit: 1.3.11_react-dom@17.0.2+react@17.0.2 + re-resizable: 6.9.1 + react-colorful: 5.5.1 + react-dates: 17.2.0_moment@2.29.1 + react-resize-aware: 3.1.1 + react-use-gesture: 9.1.3 + reakit: 1.3.11 rememo: 3.0.0 uuid: 8.3.2 transitivePeerDependencies: - '@babel/core' - '@types/react' - - react - - react-dom - - redux + dev: false - /@wordpress/components/19.2.0_@babel+core@7.16.0+react@17.0.2: - resolution: {integrity: sha512-IFvbH7Jo9jqbH+ZXCMm+tLaJDn95Q783aNtm9GVA+z3nJSyh4Dl2MXsRfOSE/mLd2iToPDCrpuHi51hr/lrGcw==} + /@wordpress/components/19.3.0_@babel+core@7.16.0+react@17.0.2: + resolution: {integrity: sha512-uzw6LMPVQUC25NKNqcgC4Xe6pD/Jz9LwA+U3IVbpzE2OIPj6Ko+ghfpQpknc+ZS7+8wtePLlA/YaQrI8R7X2vA==} engines: {node: '>=12'} peerDependencies: - reakit-utils: ^0.15.1 + react: ^17.0.0 + react-dom: ^17.0.0 dependencies: '@babel/runtime': 7.16.7 '@emotion/cache': 11.7.1 '@emotion/css': 11.7.1_@babel+core@7.16.0 '@emotion/react': 11.7.1_@babel+core@7.16.0+react@17.0.2 + '@emotion/serialize': 1.0.2 '@emotion/styled': 11.6.0_0ab14c9fee32f6b27cdf64a62c8d8465 '@emotion/utils': 1.0.0 - '@wordpress/a11y': 3.2.4 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/date': 4.2.3 - '@wordpress/deprecated': 3.2.3 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keycodes': 3.2.4 - '@wordpress/primitives': 3.0.4 - '@wordpress/rich-text': 5.0.7_react@17.0.2 - '@wordpress/warning': 2.2.2 + '@wordpress/a11y': 3.3.0 + '@wordpress/compose': 5.1.0_react@17.0.2 + '@wordpress/date': 4.3.0 + '@wordpress/deprecated': 3.3.0 + '@wordpress/dom': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/hooks': 3.3.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/icons': 6.2.0 + '@wordpress/is-shallow-equal': 4.3.0 + '@wordpress/keycodes': 3.3.0 + '@wordpress/primitives': 3.1.0 + '@wordpress/rich-text': 5.1.0_react@17.0.2 + '@wordpress/warning': 2.3.0 classnames: 2.3.1 colord: 2.9.2 dom-scroll-into-view: 1.2.1 @@ -7880,6 +8468,7 @@ packages: memize: 1.1.0 moment: 2.29.1 re-resizable: 6.9.1_react@17.0.2 + react: 17.0.2 react-colorful: 5.5.1_react@17.0.2 react-dates: 17.2.0_moment@2.29.1+react@17.0.2 react-resize-aware: 3.1.1_react@17.0.2 @@ -7890,37 +8479,35 @@ packages: transitivePeerDependencies: - '@babel/core' - '@types/react' - - react - - react-dom - - redux - dev: true - /@wordpress/components/19.2.0_b4e1ce88a10f1ab0bbeb2b9720317029: - resolution: {integrity: sha512-IFvbH7Jo9jqbH+ZXCMm+tLaJDn95Q783aNtm9GVA+z3nJSyh4Dl2MXsRfOSE/mLd2iToPDCrpuHi51hr/lrGcw==} + /@wordpress/components/19.3.0_aae888dfa296766acacf1a733aa50b3a: + resolution: {integrity: sha512-uzw6LMPVQUC25NKNqcgC4Xe6pD/Jz9LwA+U3IVbpzE2OIPj6Ko+ghfpQpknc+ZS7+8wtePLlA/YaQrI8R7X2vA==} engines: {node: '>=12'} peerDependencies: - reakit-utils: ^0.15.1 + react: ^17.0.0 + react-dom: ^17.0.0 dependencies: '@babel/runtime': 7.16.7 '@emotion/cache': 11.7.1 '@emotion/css': 11.7.1_@babel+core@7.16.0 '@emotion/react': 11.7.1_@babel+core@7.16.0+react@17.0.2 + '@emotion/serialize': 1.0.2 '@emotion/styled': 11.6.0_0ab14c9fee32f6b27cdf64a62c8d8465 '@emotion/utils': 1.0.0 - '@wordpress/a11y': 3.2.4 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/date': 4.2.3 - '@wordpress/deprecated': 3.2.3 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keycodes': 3.2.4 - '@wordpress/primitives': 3.0.4 - '@wordpress/rich-text': 5.0.7_react@17.0.2+redux@4.1.1 - '@wordpress/warning': 2.2.2 + '@wordpress/a11y': 3.3.0 + '@wordpress/compose': 5.1.0_react@17.0.2 + '@wordpress/date': 4.3.0 + '@wordpress/deprecated': 3.3.0 + '@wordpress/dom': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/hooks': 3.3.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/icons': 6.2.0 + '@wordpress/is-shallow-equal': 4.3.0 + '@wordpress/keycodes': 3.3.0 + '@wordpress/primitives': 3.1.0 + '@wordpress/rich-text': 5.1.0_react@17.0.2 + '@wordpress/warning': 2.3.0 classnames: 2.3.1 colord: 2.9.2 dom-scroll-into-view: 1.2.1 @@ -7932,8 +8519,10 @@ packages: memize: 1.1.0 moment: 2.29.1 re-resizable: 6.9.1_react-dom@17.0.2+react@17.0.2 + react: 17.0.2 react-colorful: 5.5.1_react-dom@17.0.2+react@17.0.2 react-dates: 17.2.0_d0804d3726ad84366bcc42e494508e1e + react-dom: 17.0.2_react@17.0.2 react-resize-aware: 3.1.1_react@17.0.2 react-use-gesture: 9.1.3_react@17.0.2 reakit: 1.3.11_react-dom@17.0.2+react@17.0.2 @@ -7942,10 +8531,6 @@ packages: transitivePeerDependencies: - '@babel/core' - '@types/react' - - react - - react-dom - - redux - dev: false /@wordpress/compose/3.25.3_react@17.0.2: resolution: {integrity: sha512-tCO2EnJCkCH548OqA0uU8V1k/1skz2QwBlHs8ZQSpimqUS4OWWsAlndCEFe4U4vDTqFt2ow7tzAir+05Cw8MAg==} @@ -7967,112 +8552,88 @@ packages: - react dev: false - /@wordpress/compose/5.0.7: - resolution: {integrity: sha512-5PJmxW85tlw4lteiXKKycloZ3tNzcKSCYpnZa07XHKHYvq5aoKRrHwh+t3oSnLjjavczVd6Lcd7EQPpD18MSbw==} + /@wordpress/compose/5.1.0: + resolution: {integrity: sha512-brQWd3WXB+uUjMOdqmwM4Laxts6Kt+bObPDSsFg5mwiWUvD/12DkucGMuYbJaqxexbdvYzfr++lGvEcmi6V/aA==} engines: {node: '>=12'} + peerDependencies: + react: ^17.0.0 dependencies: '@babel/runtime': 7.16.7 '@types/lodash': 4.14.178 '@types/mousetrap': 1.6.9 - '@wordpress/deprecated': 3.2.3 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keycodes': 3.2.4 - '@wordpress/priority-queue': 2.2.3 + '@wordpress/deprecated': 3.3.0 + '@wordpress/dom': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/is-shallow-equal': 4.3.0 + '@wordpress/keycodes': 3.3.0 + '@wordpress/priority-queue': 2.3.0 clipboard: 2.0.8 lodash: 4.17.21 mousetrap: 1.6.5 react-resize-aware: 3.1.1 use-memo-one: 1.1.2 - transitivePeerDependencies: - - react dev: false - /@wordpress/compose/5.0.7_react@17.0.2: - resolution: {integrity: sha512-5PJmxW85tlw4lteiXKKycloZ3tNzcKSCYpnZa07XHKHYvq5aoKRrHwh+t3oSnLjjavczVd6Lcd7EQPpD18MSbw==} + /@wordpress/compose/5.1.0_react@17.0.2: + resolution: {integrity: sha512-brQWd3WXB+uUjMOdqmwM4Laxts6Kt+bObPDSsFg5mwiWUvD/12DkucGMuYbJaqxexbdvYzfr++lGvEcmi6V/aA==} engines: {node: '>=12'} + peerDependencies: + react: ^17.0.0 dependencies: '@babel/runtime': 7.16.7 '@types/lodash': 4.14.178 '@types/mousetrap': 1.6.9 - '@wordpress/deprecated': 3.2.3 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keycodes': 3.2.4 - '@wordpress/priority-queue': 2.2.3 + '@wordpress/deprecated': 3.3.0 + '@wordpress/dom': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/is-shallow-equal': 4.3.0 + '@wordpress/keycodes': 3.3.0 + '@wordpress/priority-queue': 2.3.0 clipboard: 2.0.8 lodash: 4.17.21 mousetrap: 1.6.5 + react: 17.0.2 react-resize-aware: 3.1.1_react@17.0.2 use-memo-one: 1.1.2_react@17.0.2 - transitivePeerDependencies: - - react - - /@wordpress/core-data/4.0.9_react@17.0.2: - resolution: {integrity: sha512-BCHqGWLre2GBClI901ar9+S5T0EmNQ56wdYqPE6aZJlTV3/QWgFoL241NqGvjAJ6ipC9+clpwwndX7JFG3juKw==} - engines: {node: '>=12'} - dependencies: - '@babel/runtime': 7.16.3 - '@wordpress/api-fetch': 5.2.6 - '@wordpress/blocks': 11.1.5_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2 - '@wordpress/deprecated': 3.2.3 - '@wordpress/element': 4.0.4 - '@wordpress/html-entities': 3.2.3 - '@wordpress/i18n': 4.2.4 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/url': 3.3.1 - equivalent-key-map: 0.2.2 - lodash: 4.17.21 - rememo: 3.0.0 - uuid: 8.3.2 - transitivePeerDependencies: - - react - - redux - dev: true - /@wordpress/core-data/4.0.9_react@17.0.2+redux@4.0.5: - resolution: {integrity: sha512-BCHqGWLre2GBClI901ar9+S5T0EmNQ56wdYqPE6aZJlTV3/QWgFoL241NqGvjAJ6ipC9+clpwwndX7JFG3juKw==} + /@wordpress/core-data/4.1.0_react@17.0.2: + resolution: {integrity: sha512-8bwgLAAk8bctPUXMToO78sHEOUQzGe4dTq1/72lzHcHB+Whb2wVCcgAVbzvu12s0KHkrLWwNIhW3pe323Ok3BQ==} engines: {node: '>=12'} dependencies: - '@babel/runtime': 7.16.3 - '@wordpress/api-fetch': 5.2.6 - '@wordpress/blocks': 11.1.5_react@17.0.2+redux@4.0.5 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.0.5 - '@wordpress/deprecated': 3.2.3 - '@wordpress/element': 4.0.4 - '@wordpress/html-entities': 3.2.3 - '@wordpress/i18n': 4.2.4 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/url': 3.3.1 + '@babel/runtime': 7.16.7 + '@wordpress/api-fetch': 6.0.0 + '@wordpress/blocks': 11.2.0_react@17.0.2 + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/deprecated': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/html-entities': 3.3.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/is-shallow-equal': 4.3.0 + '@wordpress/url': 3.4.0 equivalent-key-map: 0.2.2 lodash: 4.17.21 rememo: 3.0.0 uuid: 8.3.2 transitivePeerDependencies: - react - - redux dev: true - /@wordpress/data-controls/2.2.8_react@17.0.2+redux@4.0.5: - resolution: {integrity: sha512-hoaYLeZEmgUBJvHsv5SeGUKx433HfQfJ5sPu/8PiouUK/vr+8rMGM02ydTye6saWAMOHxvOxa08rzIWvWnZg/w==} + /@wordpress/data-controls/2.3.0_react@17.0.2: + resolution: {integrity: sha512-qA0tpZuebJO5i/qgdL49OGKov9CfGwxoMPq4TOhY2lxCqHBHqoccIB9G83uatH1MZiAHbiZtcdywPUvNclmmtg==} engines: {node: '>=12'} dependencies: - '@babel/runtime': 7.16.3 - '@wordpress/api-fetch': 5.2.6 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.0.5 - '@wordpress/deprecated': 3.2.3 + '@babel/runtime': 7.16.7 + '@wordpress/api-fetch': 6.0.0 + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/deprecated': 3.3.0 transitivePeerDependencies: - react - - redux dev: true /@wordpress/data/4.27.3_react@17.0.2: resolution: {integrity: sha512-5763NgNV9IIa1CC3Q80dAvrH6108tJtj3IrHfUCZmUk1atSNsOMBCkLdQ7tGTTi2JFejeGEMg1LJI22JD5zM6Q==} dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.16.7 '@wordpress/compose': 3.25.3_react@17.0.2 '@wordpress/deprecated': 2.12.3 '@wordpress/element': 2.20.3 @@ -8090,147 +8651,98 @@ packages: - react dev: false - /@wordpress/data/6.1.5: - resolution: {integrity: sha512-v31NAUpDUqlCma2FYqP45cUrCz5EfMH4m6X50c4lbuAV2ScVsWCRxb5X8mgHjZjDhKcp97fbknviCAD/pFEOng==} + /@wordpress/data/6.2.0: + resolution: {integrity: sha512-GQaZtJ4kXCoHc2H/Gb43kWDmrY2KLUkNnWeDE+xZLD7nXkgZ5AuZZ0CF1FFQUGFzzhltySNTpe/itdJakXn6DA==} engines: {node: '>=12'} peerDependencies: - redux: ^4.1.0 + react: ^17.0.0 dependencies: '@babel/runtime': 7.16.7 - '@wordpress/compose': 5.0.7 - '@wordpress/deprecated': 3.2.3 - '@wordpress/element': 4.0.4 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/priority-queue': 2.2.3 - '@wordpress/redux-routine': 4.2.2 + '@wordpress/compose': 5.1.0 + '@wordpress/deprecated': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/is-shallow-equal': 4.3.0 + '@wordpress/priority-queue': 2.3.0 + '@wordpress/redux-routine': 4.3.0_redux@4.1.2 equivalent-key-map: 0.2.2 is-promise: 4.0.0 lodash: 4.17.21 memize: 1.1.0 + redux: 4.1.2 turbo-combine-reducers: 1.0.2 use-memo-one: 1.1.2 - transitivePeerDependencies: - - react dev: false - /@wordpress/data/6.1.5_react@17.0.2: - resolution: {integrity: sha512-v31NAUpDUqlCma2FYqP45cUrCz5EfMH4m6X50c4lbuAV2ScVsWCRxb5X8mgHjZjDhKcp97fbknviCAD/pFEOng==} - engines: {node: '>=12'} - peerDependencies: - redux: ^4.1.0 - dependencies: - '@babel/runtime': 7.16.7 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/deprecated': 3.2.3 - '@wordpress/element': 4.0.4 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/priority-queue': 2.2.3 - '@wordpress/redux-routine': 4.2.2 - equivalent-key-map: 0.2.2 - is-promise: 4.0.0 - lodash: 4.17.21 - memize: 1.1.0 - redux: 4.0.5 - turbo-combine-reducers: 1.0.2 - use-memo-one: 1.1.2_react@17.0.2 - transitivePeerDependencies: - - react - - /@wordpress/data/6.1.5_react@17.0.2+redux@4.0.5: - resolution: {integrity: sha512-v31NAUpDUqlCma2FYqP45cUrCz5EfMH4m6X50c4lbuAV2ScVsWCRxb5X8mgHjZjDhKcp97fbknviCAD/pFEOng==} - engines: {node: '>=12'} - peerDependencies: - redux: ^4.1.0 - dependencies: - '@babel/runtime': 7.16.7 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/deprecated': 3.2.3 - '@wordpress/element': 4.0.4 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/priority-queue': 2.2.3 - '@wordpress/redux-routine': 4.2.2 - equivalent-key-map: 0.2.2 - is-promise: 4.0.0 - lodash: 4.17.21 - memize: 1.1.0 - redux: 4.0.5 - turbo-combine-reducers: 1.0.2 - use-memo-one: 1.1.2_react@17.0.2 - transitivePeerDependencies: - - react - - /@wordpress/data/6.1.5_react@17.0.2+redux@4.1.1: - resolution: {integrity: sha512-v31NAUpDUqlCma2FYqP45cUrCz5EfMH4m6X50c4lbuAV2ScVsWCRxb5X8mgHjZjDhKcp97fbknviCAD/pFEOng==} + /@wordpress/data/6.2.0_react@17.0.2: + resolution: {integrity: sha512-GQaZtJ4kXCoHc2H/Gb43kWDmrY2KLUkNnWeDE+xZLD7nXkgZ5AuZZ0CF1FFQUGFzzhltySNTpe/itdJakXn6DA==} engines: {node: '>=12'} peerDependencies: - redux: ^4.1.0 + react: ^17.0.0 dependencies: '@babel/runtime': 7.16.7 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/deprecated': 3.2.3 - '@wordpress/element': 4.0.4 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/priority-queue': 2.2.3 - '@wordpress/redux-routine': 4.2.2 + '@wordpress/compose': 5.1.0_react@17.0.2 + '@wordpress/deprecated': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/is-shallow-equal': 4.3.0 + '@wordpress/priority-queue': 2.3.0 + '@wordpress/redux-routine': 4.3.0_redux@4.1.2 equivalent-key-map: 0.2.2 is-promise: 4.0.0 lodash: 4.17.21 memize: 1.1.0 - redux: 4.1.1 + react: 17.0.2 + redux: 4.1.2 turbo-combine-reducers: 1.0.2 use-memo-one: 1.1.2_react@17.0.2 - transitivePeerDependencies: - - react - dev: false /@wordpress/date/3.15.1: resolution: {integrity: sha512-SuHiObvjbegL8RpaSQ6JqFnG+QyGP+oUhx1FZDMdt1nOQA9HE7D5ssVlZFlMEAdo6iS8xMuW+4SgJN3Eo1fb4w==} dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.16.7 moment: 2.29.1 moment-timezone: 0.5.34 dev: false - /@wordpress/date/4.2.3: - resolution: {integrity: sha512-5hZDhFwTtKcbJGZdqvIzoLsW/QgBjUjf4ohgDqRlMBX8Zi6/n11O8LDRPOpmJLVSnIx1fgNSGkzXOzzQmbWuqQ==} + /@wordpress/date/4.3.0: + resolution: {integrity: sha512-c2A3HZa9Sr0QfdIkqps/Ox2e9Xd4txFp2S8WqW0K9ZXpFhSZ5ieeomKvrzWBCsYuoDItMYGNB3N8EeY/aJUsOQ==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 moment: 2.29.1 moment-timezone: 0.5.34 - /@wordpress/dependency-extraction-webpack-plugin/3.2.1_webpack@5.65.0: - resolution: {integrity: sha512-Ltd+1CJb7PMh6iN2Mse+3yN/oMORug5qXSj/3xmuZERzZO2SO6xNEJGml8yK9ev747cbHktEpitK4H+8VO3Ekg==} + /@wordpress/dependency-extraction-webpack-plugin/3.3.0_webpack@5.65.0: + resolution: {integrity: sha512-bUBRkT1keDoD+Mv+YBkJGB5DPLes+zK1e34/SyrX+NIGOEngxsoUOdKPyX/Hex/t/0w6Bhqb5+2lYaNR6ar8IQ==} engines: {node: '>=12'} peerDependencies: webpack: ^4.8.3 || ^5.0.0 dependencies: json2php: 0.0.4 webpack: 5.65.0 - webpack-sources: 2.3.1 + webpack-sources: 3.2.2 /@wordpress/deprecated/2.12.3: resolution: {integrity: sha512-qr+yDfTQfI3M4h6oY6IeHWwoHr4jxbILjSlV+Ht6Jjto9Owap6OuzSqR13Ev4xqIoG4C7b5B3gZXVfwVDae1zg==} dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.16.7 '@wordpress/hooks': 2.12.3 dev: false - /@wordpress/deprecated/3.2.3: - resolution: {integrity: sha512-YoJos/hW216PIlxbtNyb24kPR3TUFTSsfeVT23SxudW4jhmwM12vkl3KY1RDbhD/qi89OE4k+8xsBo5cM3lCSw==} + /@wordpress/deprecated/3.3.0: + resolution: {integrity: sha512-roTwhqAi+55tTMkDtbGnC6x7MXcO1l+sN2iUQRMSYv7Rpb3YW/6oR3VKeoRxcH/tKNByROreciPL3OQueB2TpA==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - '@wordpress/hooks': 3.2.2 + '@wordpress/hooks': 3.3.0 /@wordpress/dom-ready/2.13.2: resolution: {integrity: sha512-COH7n2uZfBq4FtluSbl37N3nCEcdMXzV42ETCWKUcumiP1Zd3qnkfQKcsxTaHWY8aVt/358RvJ7ghWe3xAd+fg==} dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.16.7 dev: false - /@wordpress/dom-ready/3.2.3: - resolution: {integrity: sha512-AvHrfYFflycWRX8CIU7UGty05aXrKvILwrNT2YRXmOmgh+POud98QQU54hitwL2cyVkWUt8dvCNRK4nnjBqqJQ==} + /@wordpress/dom-ready/3.3.0: + resolution: {integrity: sha512-iQD0/oCJPohKabnheW7TQCWrhzRIVLoytUYoyiLPa7OJnFS0PucJs9I4NpY5oNx3uMySc0QGTsOdPEeHiWXKeQ==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 @@ -8238,28 +8750,28 @@ packages: /@wordpress/dom/2.18.0: resolution: {integrity: sha512-tM2WeQuSObl3nzWjUTF0/dyLnA7sdl/MXaSe32D64OF89bjSyJvjUipI7gjKzI3kJ7ddGhwcTggGvSB06MOoCQ==} dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.16.7 lodash: 4.17.21 dev: false - /@wordpress/dom/3.2.7: - resolution: {integrity: sha512-/e7sFaiwKHWmgqUFsClYw9YI6Wq/eZ1iBsxtGgqX5zrU8KyFJaziNeHDE8tTZLkiURS1vlBQm0mY6bX7Bo4CEA==} + /@wordpress/dom/3.3.0: + resolution: {integrity: sha512-gxgSXu32X7IxPD52uJqtuzBnd89g4ytlAVq1qbu8Zi23VbYXe8dCE6ml9VFbVUdFuHsNrXYewqklks9q8FdPqA==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 lodash: 4.17.21 - /@wordpress/e2e-test-utils/5.4.10: - resolution: {integrity: sha512-JRp1f7uQ9INpN3t0x4X07P3uBMwaitou9lvYWpDwVsHRcDn21NyFpVYbsX/T63ADIpvcqIhql58RnkVJRUWYxg==} + /@wordpress/e2e-test-utils/6.0.0: + resolution: {integrity: sha512-cG2zUkf4/GE4rvYhzD5BeW7+6RnlbgV/TPnYfzm+yhuuEn5jwXQKOgzLQzmF31PFRz1OTDasrZqnqzhlm5GAXA==} engines: {node: '>=12'} peerDependencies: - jest: '>=26' - puppeteer: '>=1.19.0' + jest: '>=27' + puppeteer-core: '>=11' dependencies: '@babel/runtime': 7.16.7 - '@wordpress/api-fetch': 5.2.6 - '@wordpress/keycodes': 3.2.4 - '@wordpress/url': 3.3.1 + '@wordpress/api-fetch': 6.0.0 + '@wordpress/keycodes': 3.3.0 + '@wordpress/url': 3.4.0 form-data: 4.0.0 lodash: 4.17.21 node-fetch: 2.6.7 @@ -8267,57 +8779,58 @@ packages: - encoding dev: true - /@wordpress/editor/12.0.15_595f56c80e7e5fab2a648c0f724c83ea: - resolution: {integrity: sha512-eJ2ne6GYHnso6GPbRVRRhwTz3Eg4sp/HfV5bacfiKsdN4yd/3Ci1ABvhJD4JtFq2vXZPfE02sWhjRXgSpbcY1w==} + /@wordpress/editor/12.1.0_aae888dfa296766acacf1a733aa50b3a: + resolution: {integrity: sha512-HLu/WZjuKeyZhTyquOzQY3CFRU1E42UKLGqLem+ZBa4o8rLmOpHglaAk8sARY2yc3jLbHbEcW9EZ3gM0s+4Cag==} engines: {node: '>=12'} + peerDependencies: + react: ^17.0.0 + react-dom: ^17.0.0 dependencies: - '@babel/runtime': 7.16.3 - '@wordpress/a11y': 3.2.4 - '@wordpress/api-fetch': 5.2.6 - '@wordpress/autop': 3.2.3 - '@wordpress/blob': 3.2.2 - '@wordpress/block-editor': 8.0.12_595f56c80e7e5fab2a648c0f724c83ea - '@wordpress/blocks': 11.1.5_react@17.0.2+redux@4.0.5 - '@wordpress/components': 19.1.6_595f56c80e7e5fab2a648c0f724c83ea - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/core-data': 4.0.9_react@17.0.2+redux@4.0.5 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.0.5 - '@wordpress/data-controls': 2.2.8_react@17.0.2+redux@4.0.5 - '@wordpress/date': 4.2.3 - '@wordpress/deprecated': 3.2.3 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/html-entities': 3.2.3 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keyboard-shortcuts': 3.0.7_react@17.0.2+redux@4.0.5 - '@wordpress/keycodes': 3.2.4 - '@wordpress/media-utils': 3.0.5 - '@wordpress/notices': 3.2.8_react@17.0.2+redux@4.0.5 - '@wordpress/reusable-blocks': 3.0.19_595f56c80e7e5fab2a648c0f724c83ea - '@wordpress/rich-text': 5.0.7_react@17.0.2+redux@4.0.5 - '@wordpress/server-side-render': 3.0.16_595f56c80e7e5fab2a648c0f724c83ea - '@wordpress/url': 3.3.1 - '@wordpress/wordcount': 3.2.3 + '@babel/runtime': 7.16.7 + '@wordpress/a11y': 3.3.0 + '@wordpress/api-fetch': 6.0.0 + '@wordpress/autop': 3.3.0 + '@wordpress/blob': 3.3.0 + '@wordpress/block-editor': 8.1.0_aae888dfa296766acacf1a733aa50b3a + '@wordpress/blocks': 11.2.0_react@17.0.2 + '@wordpress/components': 19.3.0_aae888dfa296766acacf1a733aa50b3a + '@wordpress/compose': 5.1.0_react@17.0.2 + '@wordpress/core-data': 4.1.0_react@17.0.2 + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/data-controls': 2.3.0_react@17.0.2 + '@wordpress/date': 4.3.0 + '@wordpress/deprecated': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/hooks': 3.3.0 + '@wordpress/html-entities': 3.3.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/icons': 6.2.0 + '@wordpress/is-shallow-equal': 4.3.0 + '@wordpress/keyboard-shortcuts': 3.1.0_react@17.0.2 + '@wordpress/keycodes': 3.3.0 + '@wordpress/media-utils': 3.1.0 + '@wordpress/notices': 3.3.0_react@17.0.2 + '@wordpress/reusable-blocks': 3.1.0_aae888dfa296766acacf1a733aa50b3a + '@wordpress/rich-text': 5.1.0_react@17.0.2 + '@wordpress/server-side-render': 3.1.0_aae888dfa296766acacf1a733aa50b3a + '@wordpress/url': 3.4.0 + '@wordpress/wordcount': 3.3.0 classnames: 2.3.1 lodash: 4.17.21 memize: 1.1.0 + react: 17.0.2 react-autosize-textarea: 7.1.0_react-dom@17.0.2+react@17.0.2 + react-dom: 17.0.2_react@17.0.2 rememo: 3.0.0 transitivePeerDependencies: - '@babel/core' - '@types/react' - - react - - react-dom - - reakit-utils - - redux dev: true /@wordpress/element/2.20.3: resolution: {integrity: sha512-f4ZPTDf9CxiiOXiMxc4v1K7jcBMT4dsiehVOpkKzCDKboNXp4qVf8oe5PE23VGZNEjcOj5Mkg9hB57R0nqvMTw==} dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.16.7 '@types/react': 16.14.21 '@types/react-dom': 16.9.14 '@wordpress/escape-html': 1.12.2 @@ -8326,14 +8839,14 @@ packages: react-dom: 16.14.0_react@16.14.0 dev: false - /@wordpress/element/4.0.4: - resolution: {integrity: sha512-GbYVSZrHitOmupQCjb7cSlewVigXHorpZUBpvWnkU3rhyh1tF/N9qve3fgg7Q3s2szjtTP+eEutB+4mmkwHQOA==} + /@wordpress/element/4.1.0: + resolution: {integrity: sha512-Q63OGOExHthL1TGJOaQKYXr2vEvkIk3jBlcMuPuY/6JhKx3h0G6GDE3J0mc9HQyydkv6XWDyATWjfP5naMjM/Q==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - '@types/react': 16.14.21 - '@types/react-dom': 16.9.14 - '@wordpress/escape-html': 2.2.3 + '@types/react': 17.0.38 + '@types/react-dom': 17.0.11 + '@wordpress/escape-html': 2.3.0 lodash: 4.17.21 react: 17.0.2 react-dom: 17.0.2_react@17.0.2 @@ -8341,89 +8854,90 @@ packages: /@wordpress/escape-html/1.12.2: resolution: {integrity: sha512-FabgSwznhdaUwe6hr1CsGpgxQbzqEoGevv73WIL1B9GvlZ6csRWodgHfWh4P6fYqpzxFL4WYB8wPJ1PdO32XFA==} dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.16.7 dev: false - /@wordpress/escape-html/2.2.3: - resolution: {integrity: sha512-nYIwT8WzHfAzjjwHLiwDQWrzn4/gUNr5zud465XQszM2cAItN2wnC26/ovSpPomDGkvjcG0YltgnSqc1T62olA==} + /@wordpress/escape-html/2.3.0: + resolution: {integrity: sha512-QD5uid5Le3sZkKGKiXcudQKILxrSEeGltYVyQoNwbeBIhUE19DW7J0S1zqKkaaHks0jEERPIfzNThiyUh1IrVg==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - /@wordpress/eslint-plugin/9.3.0_@babel+core@7.16.0+eslint@7.32.0: - resolution: {integrity: sha512-9F7B60gHAjiTIi9vBw5ZoH0MZW3UnmbuKols4kWpJVdgsvG4X1Wj6XXTLmQKrzh/Em7mD1CCIbCSyWknEzIOLw==} + /@wordpress/eslint-plugin/10.0.0_@babel+core@7.16.0+eslint@8.8.0: + resolution: {integrity: sha512-OMPyXLwjvnDio/f1l2+FkwwtNO2hpHkTdJe8D1ie5QpUFQgVz7n59w9USMxdJ/XR2eDDLjVv1alwXEow1go+mg==} engines: {node: '>=12', npm: '>=6.9'} peerDependencies: - eslint: ^6 || ^7 - typescript: ^4 + '@babel/core': '>=7' + eslint: '>=8' + typescript: '>=4' peerDependenciesMeta: typescript: optional: true dependencies: - '@babel/eslint-parser': 7.16.3_@babel+core@7.16.0+eslint@7.32.0 - '@typescript-eslint/eslint-plugin': 4.33.0_2951ba233cd46bb4e0f2f0a3f7fe108e - '@typescript-eslint/parser': 4.33.0_eslint@7.32.0 + '@babel/core': 7.16.0 + '@babel/eslint-parser': 7.16.3_@babel+core@7.16.0+eslint@8.8.0 + '@typescript-eslint/eslint-plugin': 5.10.2_0d682450f1ef58680b7f0316f2e82e26 + '@typescript-eslint/parser': 5.10.2_eslint@8.8.0 + '@wordpress/babel-preset-default': 6.5.0 '@wordpress/prettier-config': 1.1.1 cosmiconfig: 7.0.1 - eslint: 7.32.0 - eslint-config-prettier: 7.2.0_eslint@7.32.0 - eslint-plugin-import: 2.25.4_eslint@7.32.0 - eslint-plugin-jest: 24.7.0_d3b4c2d4ac51f4275548d5d796aee5d5 - eslint-plugin-jsdoc: 36.1.1_eslint@7.32.0 - eslint-plugin-jsx-a11y: 6.5.1_eslint@7.32.0 - eslint-plugin-prettier: 3.4.1_34b707f3a53b0942f3919c1ff656ce36 - eslint-plugin-react: 7.28.0_eslint@7.32.0 - eslint-plugin-react-hooks: 4.3.0_eslint@7.32.0 - globals: 12.4.0 + eslint: 8.8.0 + eslint-config-prettier: 8.3.0_eslint@8.8.0 + eslint-plugin-import: 2.25.4_eslint@8.8.0 + eslint-plugin-jest: 25.7.0_2710175b8e1738b8f39f06cfa9aa7159 + eslint-plugin-jsdoc: 37.7.0_eslint@8.8.0 + eslint-plugin-jsx-a11y: 6.5.1_eslint@8.8.0 + eslint-plugin-prettier: 3.4.1_5208900944bd53d50aafd0e7d193e6c3 + eslint-plugin-react: 7.28.0_eslint@8.8.0 + eslint-plugin-react-hooks: 4.3.0_eslint@8.8.0 + globals: 13.12.0 prettier: /wp-prettier/2.2.1-beta-1 requireindex: 1.2.0 transitivePeerDependencies: - - '@babel/core' + - jest - supports-color dev: true - /@wordpress/format-library/3.0.18_@babel+core@7.16.0+react@17.0.2: - resolution: {integrity: sha512-HWuCsG4/tDLRunEC5U4I6SqUGRe1jWPAO/62QFewRI/zxDi5tCi6pYl9N1Sn6rOCKWfcKKkEZcno6IN4H4g9Dw==} + /@wordpress/format-library/3.1.0_@babel+core@7.16.0+react@17.0.2: + resolution: {integrity: sha512-RQIzh5IzpbApavgmJt1PrdlE3el92NLkktyd1c2tDIEDPGLZ5RlULliKMi8nr558opxxTfMf5wHjU4OC8ysViA==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - '@wordpress/a11y': 3.2.4 - '@wordpress/block-editor': 8.0.12_@babel+core@7.16.0+react@17.0.2 - '@wordpress/components': 19.1.6_@babel+core@7.16.0+react@17.0.2 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/html-entities': 3.2.3 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/keycodes': 3.2.4 - '@wordpress/rich-text': 5.0.7_react@17.0.2 - '@wordpress/url': 3.3.1 + '@wordpress/a11y': 3.3.0 + '@wordpress/block-editor': 8.1.0_@babel+core@7.16.0+react@17.0.2 + '@wordpress/components': 19.3.0_@babel+core@7.16.0+react@17.0.2 + '@wordpress/compose': 5.1.0_react@17.0.2 + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/dom': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/html-entities': 3.3.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/icons': 6.2.0 + '@wordpress/keycodes': 3.3.0 + '@wordpress/rich-text': 5.1.0_react@17.0.2 + '@wordpress/url': 3.4.0 lodash: 4.17.21 transitivePeerDependencies: - '@babel/core' - '@types/react' - react - react-dom - - reakit-utils - - redux dev: true /@wordpress/hooks/2.12.3: resolution: {integrity: sha512-LmKiwKldZt6UYqOxV/a6+eUFXdvALFnB/pQx3RmrMvO64sgFhfR6dhrlv+uVbuuezSuv8dce1jx8lUWAT0krMA==} dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.16.7 dev: false - /@wordpress/hooks/3.2.2: - resolution: {integrity: sha512-MlFWyu2ttJhmzDFBVWPRwZwIMqQdHFZTjFWFWm50NlzUzIJ3gEtNA95mHNtav1Fone24N+I2YkaYMNb6PEPTyA==} + /@wordpress/hooks/3.3.0: + resolution: {integrity: sha512-RSOZS5cr9h830VHE7XQ/NbgIfQQXtuSWrb2mX+4uN4qK6ua2hUfZS/twW4af2H2beistK/rUDPpUVO9x7XSQ5w==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - /@wordpress/html-entities/3.2.3: - resolution: {integrity: sha512-406VUz8CuKgKGrW/wjRB877soSqGhGDwK4sSuNoIC1FvpfniZ0ijpqfsdhJOOynWdz+RYN1wAsfogBpzuREJOg==} + /@wordpress/html-entities/3.3.0: + resolution: {integrity: sha512-KyzQTP+tPyIHUQKaRV8FXUTtIf4pyOSFSnhYA9UZtTa+797B+zSzkj+NCObnxcwbfCqajxlAwxvqKa2OISr74A==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 @@ -8432,7 +8946,7 @@ packages: resolution: {integrity: sha512-SIoOJFB4UrrYAScS4H91CYCLW9dX3Ghv8pBKc/yHGculb1AdGr6gRMlmJxZV62Cn3CZ4Ga86c+FfR+GiBu0JPg==} hasBin: true dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.16.7 '@wordpress/hooks': 2.12.3 gettext-parser: 1.4.0 lodash: 4.17.21 @@ -8441,13 +8955,13 @@ packages: tannin: 1.2.0 dev: false - /@wordpress/i18n/4.2.4: - resolution: {integrity: sha512-36PnV7wTaLKCb+JZoapR3AtfrLTluhO5bIR6cUTG+QBBJ+g3gjRAdNFihnV8kz66FANu8PqDMI0T1jow/mrbYw==} + /@wordpress/i18n/4.3.0: + resolution: {integrity: sha512-VN0fPhhphX1EkVcCMxirLkwVhvdLNDTg5uYfLeK/e3OSUrKhlFFiI+JyfOXZOrD7LLRz6c6wzCPrCw3ehjmkrg==} engines: {node: '>=12'} hasBin: true dependencies: '@babel/runtime': 7.16.7 - '@wordpress/hooks': 3.2.2 + '@wordpress/hooks': 3.3.0 gettext-parser: 1.4.0 lodash: 4.17.21 memize: 1.1.0 @@ -8457,221 +8971,121 @@ packages: /@wordpress/icons/2.10.3: resolution: {integrity: sha512-hVXArGOHLE5pL1G3rHNzsUEuTR4/G6lB+enKYwhYSSIqWuSbyXbZq3nvibxpepPrLy9B3d5t6aR6QUmjMVzIcQ==} dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.16.7 '@wordpress/element': 2.20.3 '@wordpress/primitives': 1.12.3 dev: false - /@wordpress/icons/6.1.1: - resolution: {integrity: sha512-UaFAOF8hqlEhjTm5kba0JwSDDeEgPSJToDJNADoz8jkxt22kEG5ACi9IaS0BRIy1X7kR6QaCE394v9+GkToE+g==} - engines: {node: '>=12'} - dependencies: - '@babel/runtime': 7.16.7 - '@wordpress/element': 4.0.4 - '@wordpress/primitives': 3.0.4 - - /@wordpress/interface/4.1.15_@babel+core@7.16.0+react@17.0.2: - resolution: {integrity: sha512-11vTvDG08A0QMicNc4hJBNMFDATRxWPEEEiB0g2pZRyZ09kMXcJ4Je9SdZz5jl2Bz/x8oEeTYeLqyvioq928cw==} + /@wordpress/icons/6.2.0: + resolution: {integrity: sha512-4TDeF6kRtxRzGx9P+55noNtd3uOkbtXwmXzn5kiOOxeMaOkr8H81ZMYDkIJ/B+ppnLL2GQVMEqJIilPK172x4w==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - '@wordpress/a11y': 3.2.4 - '@wordpress/components': 19.2.0_@babel+core@7.16.0+react@17.0.2 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2 - '@wordpress/deprecated': 3.2.3 - '@wordpress/element': 4.0.4 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/plugins': 4.0.7_react@17.0.2 - '@wordpress/viewport': 4.0.7_react@17.0.2 - classnames: 2.3.1 - lodash: 4.17.21 - transitivePeerDependencies: - - '@babel/core' - - '@types/react' - - react - - react-dom - - reakit-utils - - redux - dev: true + '@wordpress/element': 4.1.0 + '@wordpress/primitives': 3.1.0 /@wordpress/is-shallow-equal/3.1.3: resolution: {integrity: sha512-eDLhfC4aaSgklzqwc6F/F4zmJVpTVTAvhqX+q0SP/8LPcP2HuKErPHVrEc75PMWqIutja2wJg98YSNPdewrj1w==} dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.16.7 dev: false - /@wordpress/is-shallow-equal/4.2.1: - resolution: {integrity: sha512-XczqD3S6euQcSlLY+RFmmQIOwI/X/R/Q1uXS7vPVOnhz6MH63nrmGOtq4vTTzWv+qyRMPSkq0nmuX31U7DNdRA==} + /@wordpress/is-shallow-equal/4.3.0: + resolution: {integrity: sha512-wPO2iBPZ39kvX28Oj4AYg3eIaNBgvg0tqLBofZWZeZQK03XUxBJqNeX1NHlHFctALCn1c2U7xw+Uikdkibp+gw==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - /@wordpress/jest-console/4.1.1_jest@27.3.1: - resolution: {integrity: sha512-f/DwduxU6k53tULurpCox4TKzp877+IWTHRUxE91+FOXS+2OsnhUPKfMiMEex4nu81a54EArwekPVKxaq4swbA==} + /@wordpress/jest-console/5.0.0_jest@27.3.1: + resolution: {integrity: sha512-jW9TskAlHYbOdA2H/LTDUZ8Db5kigs9haNJtOgRYcgqjp2wioEGOziss69b3/HszRq9s0yAHxdiLEVhuLrFY6Q==} engines: {node: '>=12'} peerDependencies: - jest: '>=26' + jest: '>=27' dependencies: '@babel/runtime': 7.16.7 jest: 27.3.1 - jest-matcher-utils: 26.6.2 + jest-matcher-utils: 27.4.6 lodash: 4.17.21 dev: false - /@wordpress/jest-preset-default/7.1.3_@babel+core@7.16.0+jest@27.3.1: - resolution: {integrity: sha512-rz9V/YRr3TjLdZJQu7DAZHo848PpZ4N5ThtP4Lujy1O/UtcvtKF0r34SZTNDlFQO/G1USZQX/WL6HRhgl57iHA==} + /@wordpress/jest-preset-default/8.0.0_@babel+core@7.16.0+jest@27.3.1: + resolution: {integrity: sha512-7vKskqlEdYL8b+itZGDRf6yceTva9xUV4NK8KZ+HFcLP4ZJuhuosIBCkkSdh1Mlu8LBEQLmgtkUzvxqhJE7NLQ==} engines: {node: '>=12'} peerDependencies: - jest: '>=26' + '@babel/core': '>=7' + jest: '>=27' + react: ^17.0.0 + react-dom: ^17.0.0 dependencies: + '@babel/core': 7.16.0 '@wojtekmaj/enzyme-adapter-react-17': 0.6.3_enzyme@3.11.0 - '@wordpress/jest-console': 4.1.1_jest@27.3.1 - babel-jest: 26.6.3_@babel+core@7.16.0 + '@wordpress/jest-console': 5.0.0_jest@27.3.1 + babel-jest: 27.4.6_@babel+core@7.16.0 enzyme: 3.11.0 enzyme-to-json: 3.6.2_enzyme@3.11.0 jest: 27.3.1 transitivePeerDependencies: - - '@babel/core' - - react - - react-dom - supports-color dev: false - /@wordpress/keyboard-shortcuts/3.0.7_react@17.0.2: - resolution: {integrity: sha512-qBlM4Wa1ntzX7MQM7oifOKnHgH+sWGdynmut4rCuCUqfGqqB6hwBE3nkg3sMMWYKTxA8AtE8wcxPr9bQffnx1w==} - engines: {node: '>=12'} - dependencies: - '@babel/runtime': 7.16.7 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2 - '@wordpress/element': 4.0.4 - '@wordpress/keycodes': 3.2.4 - lodash: 4.17.21 - rememo: 3.0.0 - transitivePeerDependencies: - - react - - redux - dev: true - - /@wordpress/keyboard-shortcuts/3.0.7_react@17.0.2+redux@4.0.5: - resolution: {integrity: sha512-qBlM4Wa1ntzX7MQM7oifOKnHgH+sWGdynmut4rCuCUqfGqqB6hwBE3nkg3sMMWYKTxA8AtE8wcxPr9bQffnx1w==} - engines: {node: '>=12'} - dependencies: - '@babel/runtime': 7.16.7 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.0.5 - '@wordpress/element': 4.0.4 - '@wordpress/keycodes': 3.2.4 - lodash: 4.17.21 - rememo: 3.0.0 - transitivePeerDependencies: - - react - - redux - - /@wordpress/keyboard-shortcuts/3.0.7_react@17.0.2+redux@4.1.1: - resolution: {integrity: sha512-qBlM4Wa1ntzX7MQM7oifOKnHgH+sWGdynmut4rCuCUqfGqqB6hwBE3nkg3sMMWYKTxA8AtE8wcxPr9bQffnx1w==} + /@wordpress/keyboard-shortcuts/3.1.0_react@17.0.2: + resolution: {integrity: sha512-4k4nsy0pGxAlMZApC8ImNt8tdW4sOGDbEP7YB0IeQmitYWXSC2HoS/qvvaEYVopEjh5Z/ifw7SkEOFV77HhPQA==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.1.1 - '@wordpress/element': 4.0.4 - '@wordpress/keycodes': 3.2.4 + '@wordpress/compose': 5.1.0_react@17.0.2 + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/element': 4.1.0 + '@wordpress/keycodes': 3.3.0 lodash: 4.17.21 rememo: 3.0.0 transitivePeerDependencies: - react - - redux - dev: false /@wordpress/keycodes/2.19.3: resolution: {integrity: sha512-8rNdmP5M1ifTgLIL0dt/N1uTGsq/Rx1ydCXy+gg24WdxBRhyu5sudNVCtascVXo26aIfOH9OJRdqRZZTEORhog==} dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.16.7 '@wordpress/i18n': 3.20.0 lodash: 4.17.21 dev: false - /@wordpress/keycodes/3.2.4: - resolution: {integrity: sha512-o6/WFO8Amoyk3r3JtCJ1ctt0bLfvCqyfV7SdA39QDtAe8ufIkDNRwyQOjzaVMbHznNCuBL1FhClPzGy+RH0o9w==} + /@wordpress/keycodes/3.3.0: + resolution: {integrity: sha512-VSAD09mMwAy7wKtWqUMPrzVN2c7oF0h/DXbb/WOCPLpQMaX4M1wYiohEao9CS4WjdvxZgMaXmx9eBWQ3XGEbHA==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - '@wordpress/i18n': 4.2.4 - lodash: 4.17.21 - - /@wordpress/media-utils/3.0.5: - resolution: {integrity: sha512-BshnzzBECsH8JuxU/qgJkRCBoPNPQ/z9PeWzTFMY3hPYtbd23hMtZpPqc9EGkjU+Ovs1AF8qEjNr9wPOCDq3nA==} - engines: {node: '>=12'} - dependencies: - '@babel/runtime': 7.16.3 - '@wordpress/api-fetch': 5.2.6 - '@wordpress/blob': 3.2.2 - '@wordpress/element': 4.0.4 - '@wordpress/i18n': 4.2.4 + '@wordpress/i18n': 4.3.0 lodash: 4.17.21 - dev: true - /@wordpress/notices/3.2.8_react@17.0.2: - resolution: {integrity: sha512-SC7O+L81Xf50ntHSfUGpvnb1FutSV4RZxZQyEDdiRe4Ril1dnm4ddU49AXunPHsQ68VYNUBxs8P30EplXtZp5g==} + /@wordpress/media-utils/3.1.0: + resolution: {integrity: sha512-FMgSrHf5fOstPqRLIRI3lrzL8eIPsK9+F301G5jhar6MlQvyjcj/2CFLUD4MCUjC5aGul1ll1U1Lw7C6+cCBqQ==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - '@wordpress/a11y': 3.2.4 - '@wordpress/data': 6.1.5_react@17.0.2 + '@wordpress/api-fetch': 6.0.0 + '@wordpress/blob': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/i18n': 4.3.0 lodash: 4.17.21 - transitivePeerDependencies: - - react - - redux dev: true - /@wordpress/notices/3.2.8_react@17.0.2+redux@4.0.5: - resolution: {integrity: sha512-SC7O+L81Xf50ntHSfUGpvnb1FutSV4RZxZQyEDdiRe4Ril1dnm4ddU49AXunPHsQ68VYNUBxs8P30EplXtZp5g==} - engines: {node: '>=12'} - dependencies: - '@babel/runtime': 7.16.7 - '@wordpress/a11y': 3.2.4 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.0.5 - lodash: 4.17.21 - transitivePeerDependencies: - - react - - redux - - /@wordpress/notices/3.2.8_react@17.0.2+redux@4.1.1: - resolution: {integrity: sha512-SC7O+L81Xf50ntHSfUGpvnb1FutSV4RZxZQyEDdiRe4Ril1dnm4ddU49AXunPHsQ68VYNUBxs8P30EplXtZp5g==} - engines: {node: '>=12'} - dependencies: - '@babel/runtime': 7.16.7 - '@wordpress/a11y': 3.2.4 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.1.1 - lodash: 4.17.21 - transitivePeerDependencies: - - react - - redux - dev: false - - /@wordpress/plugins/4.0.7_react@17.0.2: - resolution: {integrity: sha512-dSvSOTkGuoJ7kfst/eLJpHNHf12If+UYsB5WuGXy5sk3z5H9EIOe6XC5272ZVrS/5DUGloCxZP7k7m2vG5iXuQ==} + /@wordpress/notices/3.3.0_react@17.0.2: + resolution: {integrity: sha512-sRQKaXbcW/QI9Q6uGVmEkGzlbT+WTFPxG6S9TksrKi1UvplWJmQ7BOq4mWYlMZ5Bnq1kETltf/ToLZdw6hSOyg==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/element': 4.0.4 - '@wordpress/hooks': 3.2.2 - '@wordpress/icons': 6.1.1 + '@wordpress/a11y': 3.3.0 + '@wordpress/data': 6.2.0_react@17.0.2 lodash: 4.17.21 - memize: 1.1.0 transitivePeerDependencies: - react - dev: true - /@wordpress/postcss-plugins-preset/3.2.5: - resolution: {integrity: sha512-R+UKnjSJivvVEZ8rhGrXxsj/BlVeNO2FRXq3IxEOPv5ZRfAS0g8k8EO3xsCIV1RfnozvAApkKEYRClDYXIt+vA==} + /@wordpress/postcss-plugins-preset/3.3.0: + resolution: {integrity: sha512-Yj6t+eATEObTyGUoMaxZfkHtKh9i59lAUKTz1NY47QDmNED+Gq5WBBuQJ7ddFIXeQ7LSJcpN1wWujvNexeVISA==} engines: {node: '>=12'} dependencies: - '@wordpress/base-styles': 4.0.4 + '@wordpress/base-styles': 4.1.0 autoprefixer: 10.4.2 transitivePeerDependencies: - postcss @@ -8685,17 +9099,17 @@ packages: /@wordpress/primitives/1.12.3: resolution: {integrity: sha512-LIF44bVlJS7CJEVmk6TLuV6HZMdj5iwkyM8do4ukGY6qnZIzrXpBablgJeDBcyjzWrWRLn+w+tiZ/8l+2egoVA==} dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.16.7 '@wordpress/element': 2.20.3 classnames: 2.3.1 dev: false - /@wordpress/primitives/3.0.4: - resolution: {integrity: sha512-yu3BEpr09vpPM0QOYGm5Kmwo/tfo7u7Ez4hN5+AL2dT53VNr3QOmDo0Ym7sewI7+GgU18H4VkAi1QOydrc4vDw==} + /@wordpress/primitives/3.1.0: + resolution: {integrity: sha512-VD6sDAV8njme6XhPudRBmH0Y6k/9p7tHIEitd1d1Ze6wIsIPfgldq4Ls3z/rs08VUBw05q8T1ku5hJb+WoSsMw==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - '@wordpress/element': 4.0.4 + '@wordpress/element': 4.1.0 classnames: 2.3.1 /@wordpress/priority-queue/1.11.2: @@ -8704,8 +9118,8 @@ packages: '@babel/runtime': 7.16.7 dev: false - /@wordpress/priority-queue/2.2.3: - resolution: {integrity: sha512-VI1VhkpgNs5b2LkpmlOIfJz7mVHOxMvh+MtG+NsuKc+0t6iOftfq8xxZ+8PbVLspZ8gd7p0rS+oXmSSqr9nc9g==} + /@wordpress/priority-queue/2.3.0: + resolution: {integrity: sha512-IQGE6brycJR5a/7GiJE1B7aTXN5MUE5Rabbc6KFiklkHGMVJUryHf1KETLnMUKJvQewAuGP34ec7N/bkimOJXA==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 @@ -8713,15 +9127,17 @@ packages: /@wordpress/redux-routine/3.14.2: resolution: {integrity: sha512-aqi4UtvMP/+NhULxyCR8ktG0v4BJVTRcMpByAqDg7Oabq2sz2LPuShxd5UY8vxQYQY9t1uUJbslhom4ytcohWg==} dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.16.7 is-promise: 4.0.0 lodash: 4.17.21 rungen: 0.3.2 dev: false - /@wordpress/redux-routine/4.2.2: - resolution: {integrity: sha512-zfL8qsSvwI2lAvgPSVfOFCWDg0f0zusba0+uEIVZjPVstmjJtxO902mRZfWsg5+ooFSYq0T7rieet4nasYJX7g==} + /@wordpress/redux-routine/4.3.0_redux@4.1.2: + resolution: {integrity: sha512-+sO2DDn4V+umx2v4i+8AIhCYJ8XHPeAFntFuxSVeFP6q41PDLNq4uZ5pm53QFuQoQTIE1YwHgXKxQ1lCS0hBxw==} engines: {node: '>=12'} + peerDependencies: + redux: '>=4' dependencies: '@babel/runtime': 7.16.7 is-promise: 4.0.0 @@ -8729,277 +9145,207 @@ packages: redux: 4.1.2 rungen: 0.3.2 - /@wordpress/reusable-blocks/3.0.19_595f56c80e7e5fab2a648c0f724c83ea: - resolution: {integrity: sha512-EU4Vo3ETTTN5DAQCrgh3AOuVRsZCrIJ1LcRgGJfFBSEJe6Sto3pxxj3ZtI+Goc4U553q3M/qpghHZNo1JZcfew==} + /@wordpress/reusable-blocks/3.1.0_@babel+core@7.16.0+react@17.0.2: + resolution: {integrity: sha512-B10rV/r1nPqUUszakFOGJTXjAGhiGxXArtZ0F6DdXzXEhiEOhKe+D0ak9zAP+CE4/MNCDVVjzFZUbiNsdWS9MQ==} engines: {node: '>=12'} dependencies: - '@wordpress/block-editor': 8.0.13_595f56c80e7e5fab2a648c0f724c83ea - '@wordpress/blocks': 11.1.5_react@17.0.2+redux@4.0.5 - '@wordpress/components': 19.2.0_595f56c80e7e5fab2a648c0f724c83ea - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/core-data': 4.0.9_react@17.0.2+redux@4.0.5 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.0.5 - '@wordpress/element': 4.0.4 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/notices': 3.2.8_react@17.0.2+redux@4.0.5 - '@wordpress/url': 3.3.1 + '@wordpress/block-editor': 8.1.0_@babel+core@7.16.0+react@17.0.2 + '@wordpress/blocks': 11.2.0_react@17.0.2 + '@wordpress/components': 19.3.0_@babel+core@7.16.0+react@17.0.2 + '@wordpress/compose': 5.1.0_react@17.0.2 + '@wordpress/core-data': 4.1.0_react@17.0.2 + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/element': 4.1.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/icons': 6.2.0 + '@wordpress/notices': 3.3.0_react@17.0.2 + '@wordpress/url': 3.4.0 lodash: 4.17.21 transitivePeerDependencies: - '@babel/core' - '@types/react' - react - react-dom - - reakit-utils - - redux dev: true - /@wordpress/reusable-blocks/3.0.19_@babel+core@7.16.0+react@17.0.2: - resolution: {integrity: sha512-EU4Vo3ETTTN5DAQCrgh3AOuVRsZCrIJ1LcRgGJfFBSEJe6Sto3pxxj3ZtI+Goc4U553q3M/qpghHZNo1JZcfew==} + /@wordpress/reusable-blocks/3.1.0_aae888dfa296766acacf1a733aa50b3a: + resolution: {integrity: sha512-B10rV/r1nPqUUszakFOGJTXjAGhiGxXArtZ0F6DdXzXEhiEOhKe+D0ak9zAP+CE4/MNCDVVjzFZUbiNsdWS9MQ==} engines: {node: '>=12'} dependencies: - '@wordpress/block-editor': 8.0.13_@babel+core@7.16.0+react@17.0.2 - '@wordpress/blocks': 11.1.5_react@17.0.2 - '@wordpress/components': 19.2.0_@babel+core@7.16.0+react@17.0.2 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/core-data': 4.0.9_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2 - '@wordpress/element': 4.0.4 - '@wordpress/i18n': 4.2.4 - '@wordpress/icons': 6.1.1 - '@wordpress/notices': 3.2.8_react@17.0.2 - '@wordpress/url': 3.3.1 + '@wordpress/block-editor': 8.1.0_aae888dfa296766acacf1a733aa50b3a + '@wordpress/blocks': 11.2.0_react@17.0.2 + '@wordpress/components': 19.3.0_aae888dfa296766acacf1a733aa50b3a + '@wordpress/compose': 5.1.0_react@17.0.2 + '@wordpress/core-data': 4.1.0_react@17.0.2 + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/element': 4.1.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/icons': 6.2.0 + '@wordpress/notices': 3.3.0_react@17.0.2 + '@wordpress/url': 3.4.0 lodash: 4.17.21 transitivePeerDependencies: - '@babel/core' - '@types/react' - react - - react-dom - - reakit-utils - - redux - dev: true - - /@wordpress/rich-text/3.25.3_react@17.0.2: - resolution: {integrity: sha512-FdqL1/rHTsRxZ1gW1UEWuy0URmUEqMzj5hcAbOhHFPO5m0ENrkzC9bBa195KqZBSNSmBmXnDZdHu4UJUolzcZg==} - dependencies: - '@babel/runtime': 7.16.3 - '@wordpress/compose': 3.25.3_react@17.0.2 - '@wordpress/data': 4.27.3_react@17.0.2 - '@wordpress/dom': 2.18.0 - '@wordpress/element': 2.20.3 - '@wordpress/escape-html': 1.12.2 - '@wordpress/is-shallow-equal': 3.1.3 - '@wordpress/keycodes': 2.19.3 - classnames: 2.3.1 - lodash: 4.17.21 - memize: 1.1.0 - rememo: 3.0.0 - transitivePeerDependencies: - - react - dev: false - - /@wordpress/rich-text/5.0.7: - resolution: {integrity: sha512-oroNrJFJw9DNVielMdel/EeJNwD/bGzKPEAL0cp1AbilcS4jNxBW7oR+hOOv/ZQGH+1iDmOhwhOdERP4n78s3A==} - engines: {node: '>=12'} - dependencies: - '@babel/runtime': 7.16.7 - '@wordpress/a11y': 3.2.4 - '@wordpress/compose': 5.0.7 - '@wordpress/data': 6.1.5 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/escape-html': 2.2.3 - '@wordpress/i18n': 4.2.4 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keycodes': 3.2.4 - classnames: 2.3.1 - lodash: 4.17.21 - memize: 1.1.0 - rememo: 3.0.0 - transitivePeerDependencies: - - react - - redux - dev: false + - react-dom + dev: true - /@wordpress/rich-text/5.0.7_react@17.0.2: - resolution: {integrity: sha512-oroNrJFJw9DNVielMdel/EeJNwD/bGzKPEAL0cp1AbilcS4jNxBW7oR+hOOv/ZQGH+1iDmOhwhOdERP4n78s3A==} - engines: {node: '>=12'} + /@wordpress/rich-text/3.25.3_react@17.0.2: + resolution: {integrity: sha512-FdqL1/rHTsRxZ1gW1UEWuy0URmUEqMzj5hcAbOhHFPO5m0ENrkzC9bBa195KqZBSNSmBmXnDZdHu4UJUolzcZg==} dependencies: '@babel/runtime': 7.16.7 - '@wordpress/a11y': 3.2.4 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/escape-html': 2.2.3 - '@wordpress/i18n': 4.2.4 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keycodes': 3.2.4 + '@wordpress/compose': 3.25.3_react@17.0.2 + '@wordpress/data': 4.27.3_react@17.0.2 + '@wordpress/dom': 2.18.0 + '@wordpress/element': 2.20.3 + '@wordpress/escape-html': 1.12.2 + '@wordpress/is-shallow-equal': 3.1.3 + '@wordpress/keycodes': 2.19.3 classnames: 2.3.1 lodash: 4.17.21 memize: 1.1.0 rememo: 3.0.0 transitivePeerDependencies: - react - - redux + dev: false - /@wordpress/rich-text/5.0.7_react@17.0.2+redux@4.0.5: - resolution: {integrity: sha512-oroNrJFJw9DNVielMdel/EeJNwD/bGzKPEAL0cp1AbilcS4jNxBW7oR+hOOv/ZQGH+1iDmOhwhOdERP4n78s3A==} + /@wordpress/rich-text/5.1.0: + resolution: {integrity: sha512-WtOmUqecF4JW9zk+aoT5gO65CbEbknSYNCXm1ZdUIokLqhzC43pgo5qrFscHnSeTRXfZZvUu+4kj3bnHarUuIg==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - '@wordpress/a11y': 3.2.4 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.0.5 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/escape-html': 2.2.3 - '@wordpress/i18n': 4.2.4 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keycodes': 3.2.4 + '@wordpress/a11y': 3.3.0 + '@wordpress/compose': 5.1.0 + '@wordpress/data': 6.2.0 + '@wordpress/dom': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/escape-html': 2.3.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/is-shallow-equal': 4.3.0 + '@wordpress/keycodes': 3.3.0 classnames: 2.3.1 lodash: 4.17.21 memize: 1.1.0 rememo: 3.0.0 transitivePeerDependencies: - react - - redux + dev: false - /@wordpress/rich-text/5.0.7_react@17.0.2+redux@4.1.1: - resolution: {integrity: sha512-oroNrJFJw9DNVielMdel/EeJNwD/bGzKPEAL0cp1AbilcS4jNxBW7oR+hOOv/ZQGH+1iDmOhwhOdERP4n78s3A==} + /@wordpress/rich-text/5.1.0_react@17.0.2: + resolution: {integrity: sha512-WtOmUqecF4JW9zk+aoT5gO65CbEbknSYNCXm1ZdUIokLqhzC43pgo5qrFscHnSeTRXfZZvUu+4kj3bnHarUuIg==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - '@wordpress/a11y': 3.2.4 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.1.1 - '@wordpress/dom': 3.2.7 - '@wordpress/element': 4.0.4 - '@wordpress/escape-html': 2.2.3 - '@wordpress/i18n': 4.2.4 - '@wordpress/is-shallow-equal': 4.2.1 - '@wordpress/keycodes': 3.2.4 + '@wordpress/a11y': 3.3.0 + '@wordpress/compose': 5.1.0_react@17.0.2 + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/dom': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/escape-html': 2.3.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/is-shallow-equal': 4.3.0 + '@wordpress/keycodes': 3.3.0 classnames: 2.3.1 lodash: 4.17.21 memize: 1.1.0 rememo: 3.0.0 transitivePeerDependencies: - react - - redux - dev: false - /@wordpress/server-side-render/3.0.16_595f56c80e7e5fab2a648c0f724c83ea: - resolution: {integrity: sha512-cHuzL9fowuVz8G4Yz+DbbS850h+iUjM8+5jYzRZ9DH04fv/Y/dEGbdxZQ2K/p9wFQrQfnJ4EWUxJV1lUN/HTUw==} + /@wordpress/server-side-render/3.1.0_@babel+core@7.16.0+react@17.0.2: + resolution: {integrity: sha512-oEeonLobAmyLGF1U4MVXFvZpBSbBSCdI0rTPRbA1TFPDyjwypz8D26MZ/E2YhePV+IWerCSBE/VbjxAE1n6SpA==} engines: {node: '>=12'} dependencies: - '@babel/runtime': 7.16.3 - '@wordpress/api-fetch': 5.2.6 - '@wordpress/blocks': 11.1.5_react@17.0.2+redux@4.0.5 - '@wordpress/components': 19.1.6_595f56c80e7e5fab2a648c0f724c83ea - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.0.5 - '@wordpress/deprecated': 3.2.3 - '@wordpress/element': 4.0.4 - '@wordpress/i18n': 4.2.4 - '@wordpress/url': 3.3.1 + '@babel/runtime': 7.16.7 + '@wordpress/api-fetch': 6.0.0 + '@wordpress/blocks': 11.2.0_react@17.0.2 + '@wordpress/components': 19.3.0_@babel+core@7.16.0+react@17.0.2 + '@wordpress/compose': 5.1.0_react@17.0.2 + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/deprecated': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/url': 3.4.0 lodash: 4.17.21 transitivePeerDependencies: - '@babel/core' - '@types/react' - react - react-dom - - reakit-utils - - redux dev: true - /@wordpress/server-side-render/3.0.17_@babel+core@7.16.0+react@17.0.2: - resolution: {integrity: sha512-UIyywGUSlbOVFi1SNwI/uUmHmUJFX+N9XeBCAnS15PmfYflBkiuz9FPmZWoqLoOE4uWTI7K9lAP1tkY80lotIA==} + /@wordpress/server-side-render/3.1.0_aae888dfa296766acacf1a733aa50b3a: + resolution: {integrity: sha512-oEeonLobAmyLGF1U4MVXFvZpBSbBSCdI0rTPRbA1TFPDyjwypz8D26MZ/E2YhePV+IWerCSBE/VbjxAE1n6SpA==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 - '@wordpress/api-fetch': 5.2.6 - '@wordpress/blocks': 11.1.5_react@17.0.2 - '@wordpress/components': 19.2.0_@babel+core@7.16.0+react@17.0.2 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2 - '@wordpress/deprecated': 3.2.3 - '@wordpress/element': 4.0.4 - '@wordpress/i18n': 4.2.4 - '@wordpress/url': 3.3.1 + '@wordpress/api-fetch': 6.0.0 + '@wordpress/blocks': 11.2.0_react@17.0.2 + '@wordpress/components': 19.3.0_aae888dfa296766acacf1a733aa50b3a + '@wordpress/compose': 5.1.0_react@17.0.2 + '@wordpress/data': 6.2.0_react@17.0.2 + '@wordpress/deprecated': 3.3.0 + '@wordpress/element': 4.1.0 + '@wordpress/i18n': 4.3.0 + '@wordpress/url': 3.4.0 lodash: 4.17.21 transitivePeerDependencies: - '@babel/core' - '@types/react' - react - react-dom - - reakit-utils - - redux dev: true - /@wordpress/shortcode/3.2.3: - resolution: {integrity: sha512-zXIg2AbwJhJNCp55roC+wuyZQnMC/GLdgh95pAa5a7Hd+ThXf0hbBg+DP9lo1x+cxAZAEGZ/Bns/+SCUr1boTA==} + /@wordpress/shortcode/3.3.0: + resolution: {integrity: sha512-E0YuuCcdfR2aAFQPoBW/wk47pd1uPgUfTp/4ticDKUfucqHjGvVPrZGtb2p4WFScrxuMYcee+tM4CWT3YqGraQ==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 lodash: 4.17.21 memize: 1.1.0 - /@wordpress/token-list/2.2.2: - resolution: {integrity: sha512-JElgvK1NsQVfSnR51qWDV7cEB/2U7saV+MKDxdmP7mhcwg538AVyKTkOdmzYrx/9fqOEf0bkWOt3WX9xLD35kQ==} + /@wordpress/token-list/2.3.0: + resolution: {integrity: sha512-CyXR6c2pp92ofSXl4BJ77G5AxNlzZS0j6emWP/aae19jDnFYKZE4oNGIw3Tg0LEOCysqk/u7z5AxWc1p6T3icg==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 lodash: 4.17.21 - /@wordpress/url/3.3.1: - resolution: {integrity: sha512-lEuvkNjPoVuzYy0zn6n9gfMdNlHJW36EsPI2yDzMICjIAV5lRv1/uOg2Ls3lbDaRR2vm1FAiMpB2RAMzfR8Nfg==} + /@wordpress/url/3.4.0: + resolution: {integrity: sha512-E4jnotQrNwvrl6Zdo3S3bDBOzVKnTH7xnOr03VuNtjvWtu2ANRS9R/cD9yVXbvDdiBC2jAJHmCrEMVCxGJmuIw==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 lodash: 4.17.21 - /@wordpress/viewport/4.0.7_react@17.0.2: - resolution: {integrity: sha512-huxUrFW6JNhj/hUfvftZeht3B6HF0jk10oyHW3dPcFW57ceecJTDB9BdS7a99B1LBP8AWjdN8x/3SqrMwE4yfg==} - engines: {node: '>=12'} - dependencies: - '@babel/runtime': 7.16.3 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2 - lodash: 4.17.21 - transitivePeerDependencies: - - react - - redux - dev: true - - /@wordpress/viewport/4.0.7_react@17.0.2+redux@4.0.5: - resolution: {integrity: sha512-huxUrFW6JNhj/hUfvftZeht3B6HF0jk10oyHW3dPcFW57ceecJTDB9BdS7a99B1LBP8AWjdN8x/3SqrMwE4yfg==} + /@wordpress/viewport/4.1.0_react@17.0.2: + resolution: {integrity: sha512-WWli8c0Y+w1+CWyZ5GXS0xWJ6fO/mG9y+TfPG8FkPM7/d+QqT73N04dYLe7DVgvjQK6f7v8VegoLKc7Yy0T7VQ==} engines: {node: '>=12'} dependencies: - '@babel/runtime': 7.16.3 - '@wordpress/compose': 5.0.7_react@17.0.2 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.0.5 + '@babel/runtime': 7.16.7 + '@wordpress/compose': 5.1.0_react@17.0.2 + '@wordpress/data': 6.2.0_react@17.0.2 lodash: 4.17.21 transitivePeerDependencies: - react - - redux - dev: false /@wordpress/warning/1.4.2: resolution: {integrity: sha512-MjrkSp6Jyfx+92AE32A83P503noUtGb6//BYUH4GiWzzzSNhDHgbQ0UcOJwJaEYK166DxSNpMk/JXc4YENi1Cw==} dev: false - /@wordpress/warning/2.2.2: - resolution: {integrity: sha512-iG1Hq56RK3N6AJqAD1sRLWRIJatfYn+NrPyrfqRNZNYXHM8Vj/s7ABNMbIU0Y99vXkBE83rvCdbMkugNoI2jXA==} + /@wordpress/warning/2.3.0: + resolution: {integrity: sha512-Is6uEp2wvUPTK1+RtQQdzTdb93BDMAJEYE5UCHvoSFCWpxvEhBP6SY+Nzv/MkFKHZwY66QxEAduThxfINma87Q==} engines: {node: '>=12'} - /@wordpress/wordcount/3.2.3: - resolution: {integrity: sha512-iguvGA4zU1tB0avpzIzVdVrIeH0CbeiOlhbYgtkQ5J2UqdRs6lo7pZFlp/3HAvmtBo8r2iGlbc+QZgKzR6gdJw==} + /@wordpress/wordcount/3.3.0: + resolution: {integrity: sha512-969gA/7yQlhovnLY+XN4NSA3u4T9MAJv6Z5EbxmCFfbXOiHDc7IU2VrKMBnqlcJzriVepujYyPcIQ8krT2nz7Q==} engines: {node: '>=12'} dependencies: '@babel/runtime': 7.16.7 lodash: 4.17.21 - /@wp-g2/components/0.0.140_39aa9b824a3099e0a8f080749de9ea5d: + /@wp-g2/components/0.0.140_cbbf6db973bdf4a4a0954a832637d63f: resolution: {integrity: sha512-bychuhZ3wPSB457CHYcogoPQPlP/eUA9GoTo0Fv0rj7f44Gr9XlPoqVT+GQa3CmPnvSCAl1sjoe75Vkaoo/O1w==} peerDependencies: '@wordpress/i18n': '>=3.17.0' @@ -9010,8 +9356,8 @@ packages: '@popperjs/core': 2.11.2 '@wordpress/i18n': 3.20.0 '@wordpress/icons': 2.10.3 - '@wp-g2/context': 0.0.140_a53271638ee60ee853e0b95b95bb3a79 - '@wp-g2/styles': 0.0.140_a53271638ee60ee853e0b95b95bb3a79 + '@wp-g2/context': 0.0.140_9be7e7b1381639c021accc00fc2a2b0f + '@wp-g2/styles': 0.0.140_9be7e7b1381639c021accc00fc2a2b0f '@wp-g2/utils': 0.0.140_react-dom@17.0.2+react@17.0.2 csstype: 3.0.10 downshift: 6.1.7_react@17.0.2 @@ -9032,13 +9378,13 @@ packages: - '@wordpress/is-shallow-equal' dev: false - /@wp-g2/context/0.0.140_a53271638ee60ee853e0b95b95bb3a79: + /@wp-g2/context/0.0.140_9be7e7b1381639c021accc00fc2a2b0f: resolution: {integrity: sha512-z32fxZ2tCVmYQC+wyyziyrhEvWBPFBQfUhUHF85JmTUPzQQeEPiLC3rgDAT0fUTFlJHinPJQq6871RDqFSwCUA==} peerDependencies: react: ^16.13.1 react-dom: ^16.13.1 dependencies: - '@wp-g2/styles': 0.0.140_a53271638ee60ee853e0b95b95bb3a79 + '@wp-g2/styles': 0.0.140_9be7e7b1381639c021accc00fc2a2b0f '@wp-g2/utils': 0.0.140_react-dom@17.0.2+react@17.0.2 lodash: 4.17.21 react: 17.0.2 @@ -9049,7 +9395,7 @@ packages: - '@wordpress/is-shallow-equal' dev: false - /@wp-g2/create-styles/0.0.140_a53271638ee60ee853e0b95b95bb3a79: + /@wp-g2/create-styles/0.0.140_9be7e7b1381639c021accc00fc2a2b0f: resolution: {integrity: sha512-/60DxWjCAhsoYOqY7aiHVbkTAF+L6qZIyHyH50oNs9FTVkcRLHQFSC0kHgAam+Z9K3eImQ7hM52wfBDqae0q2Q==} peerDependencies: '@wordpress/data': '>=4.26' @@ -9059,7 +9405,7 @@ packages: dependencies: '@emotion/core': 10.3.1_react@17.0.2 '@emotion/is-prop-valid': 0.8.8 - '@wordpress/data': 6.1.5_react@17.0.2+redux@4.0.5 + '@wordpress/data': 6.2.0_react@17.0.2 '@wordpress/is-shallow-equal': 3.1.3 '@wp-g2/utils': 0.0.140_react-dom@17.0.2+react@17.0.2 create-emotion: 10.0.27 @@ -9075,13 +9421,13 @@ packages: - '@types/react' dev: false - /@wp-g2/styles/0.0.140_a53271638ee60ee853e0b95b95bb3a79: + /@wp-g2/styles/0.0.140_9be7e7b1381639c021accc00fc2a2b0f: resolution: {integrity: sha512-wAvtqQOqX2zYpfEdVK4l4abH/hUUgw/+8+E5PvPgrsvqFg8IehNSksnjNF5/IloLRGAH70d8ytjMuMnUK8PVYA==} peerDependencies: react: ^16.13.1 react-dom: ^16.13.1 dependencies: - '@wp-g2/create-styles': 0.0.140_a53271638ee60ee853e0b95b95bb3a79 + '@wp-g2/create-styles': 0.0.140_9be7e7b1381639c021accc00fc2a2b0f '@wp-g2/utils': 0.0.140_react-dom@17.0.2+react@17.0.2 react: 17.0.2 react-dom: 17.0.2_react@17.0.2 @@ -9155,6 +9501,14 @@ packages: acorn: 7.4.1 dev: true + /acorn-jsx/5.3.2_acorn@8.7.0: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.7.0 + dev: true + /acorn-walk/7.2.0: resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} engines: {node: '>=0.4.0'} @@ -9650,11 +10004,6 @@ packages: tslib: 2.3.1 dev: true - /astral-regex/2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - dev: true - /async-done/1.3.2: resolution: {integrity: sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==} engines: {node: '>= 0.10'} @@ -9742,18 +10091,18 @@ packages: resolution: {integrity: sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==} dev: true - /babel-jest/26.6.3_@babel+core@7.16.0: - resolution: {integrity: sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==} - engines: {node: '>= 10.14.2'} + /babel-jest/27.3.1_@babel+core@7.16.0: + resolution: {integrity: sha512-SjIF8hh/ir0peae2D6S6ZKRhUy7q/DnpH7k/V6fT4Bgs/LXXUztOpX4G2tCgq8mLo5HA9mN6NmlFMeYtKmIsTQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} peerDependencies: - '@babel/core': ^7.0.0 + '@babel/core': ^7.8.0 dependencies: '@babel/core': 7.16.0 - '@jest/transform': 26.6.2 - '@jest/types': 26.6.2 + '@jest/transform': 27.4.6 + '@jest/types': 27.4.2 '@types/babel__core': 7.1.18 babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 26.6.2_@babel+core@7.16.0 + babel-preset-jest: 27.4.0_@babel+core@7.16.0 chalk: 4.1.2 graceful-fs: 4.2.9 slash: 3.0.0 @@ -9761,8 +10110,8 @@ packages: - supports-color dev: false - /babel-jest/27.3.1_@babel+core@7.16.0: - resolution: {integrity: sha512-SjIF8hh/ir0peae2D6S6ZKRhUy7q/DnpH7k/V6fT4Bgs/LXXUztOpX4G2tCgq8mLo5HA9mN6NmlFMeYtKmIsTQ==} + /babel-jest/27.4.6_@babel+core@7.16.0: + resolution: {integrity: sha512-qZL0JT0HS1L+lOuH+xC2DVASR3nunZi/ozGhpgauJHgmI7f8rudxf6hUjEHympdQ/J64CdKmPkgfJ+A3U6QCrg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} peerDependencies: '@babel/core': ^7.8.0 @@ -9812,6 +10161,21 @@ packages: schema-utils: 2.7.1 webpack: 5.65.0_webpack-cli@4.9.1 + /babel-loader/8.2.3_c391fd7145c194be609b87ed083bbc6a: + resolution: {integrity: sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw==} + engines: {node: '>= 8.9'} + peerDependencies: + '@babel/core': ^7.0.0 + webpack: '>=2' + dependencies: + '@babel/core': 7.16.7 + find-cache-dir: 3.3.2 + loader-utils: 1.4.0 + make-dir: 3.1.0 + schema-utils: 2.7.1 + webpack: 5.65.0 + dev: true + /babel-plugin-add-react-displayname/0.0.5: resolution: {integrity: sha1-M51M3be2X9YtHfnbn+BN4TQSK9U=} dev: true @@ -9869,16 +10233,6 @@ packages: transitivePeerDependencies: - supports-color - /babel-plugin-jest-hoist/26.6.2: - resolution: {integrity: sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==} - engines: {node: '>= 10.14.2'} - dependencies: - '@babel/template': 7.16.7 - '@babel/types': 7.16.7 - '@types/babel__core': 7.1.18 - '@types/babel__traverse': 7.14.2 - dev: false - /babel-plugin-jest-hoist/27.4.0: resolution: {integrity: sha512-Jcu7qS4OX5kTWBc45Hz7BMmgXuJqRnhatqpUhnzGC3OBYpOmf2tv6jFNwZpwM7wU7MUuv2r9IPS/ZlYOuburVw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9924,6 +10278,19 @@ packages: transitivePeerDependencies: - supports-color + /babel-plugin-polyfill-corejs2/0.3.0_@babel+core@7.16.7: + resolution: {integrity: sha512-wMDoBJ6uG4u4PNFh72Ty6t3EgfA91puCuAwKIazbQlci+ENb/UU9A3xG5lutjUIiXCIn1CY5L15r9LimiJyrSA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.16.4 + '@babel/core': 7.16.7 + '@babel/helper-define-polyfill-provider': 0.3.0_@babel+core@7.16.7 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + /babel-plugin-polyfill-corejs3/0.1.7_@babel+core@7.16.0: resolution: {integrity: sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==} peerDependencies: @@ -9936,6 +10303,18 @@ packages: - supports-color dev: true + /babel-plugin-polyfill-corejs3/0.1.7_@babel+core@7.16.7: + resolution: {integrity: sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-define-polyfill-provider': 0.1.5_@babel+core@7.16.7 + core-js-compat: 3.20.2 + transitivePeerDependencies: + - supports-color + dev: true + /babel-plugin-polyfill-corejs3/0.4.0_@babel+core@7.16.0: resolution: {integrity: sha512-YxFreYwUfglYKdLUGvIF2nJEsGwj+RhWSX/ije3D2vQPOXuyMLMtg/cCGMDpOA7Nd+MwlNdnGODbd2EwUZPlsw==} peerDependencies: @@ -9947,6 +10326,18 @@ packages: transitivePeerDependencies: - supports-color + /babel-plugin-polyfill-corejs3/0.4.0_@babel+core@7.16.7: + resolution: {integrity: sha512-YxFreYwUfglYKdLUGvIF2nJEsGwj+RhWSX/ije3D2vQPOXuyMLMtg/cCGMDpOA7Nd+MwlNdnGODbd2EwUZPlsw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-define-polyfill-provider': 0.3.0_@babel+core@7.16.7 + core-js-compat: 3.20.2 + transitivePeerDependencies: + - supports-color + dev: true + /babel-plugin-polyfill-regenerator/0.3.0_@babel+core@7.16.0: resolution: {integrity: sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg==} peerDependencies: @@ -9957,6 +10348,17 @@ packages: transitivePeerDependencies: - supports-color + /babel-plugin-polyfill-regenerator/0.3.0_@babel+core@7.16.7: + resolution: {integrity: sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.7 + '@babel/helper-define-polyfill-provider': 0.3.0_@babel+core@7.16.7 + transitivePeerDependencies: + - supports-color + dev: true + /babel-plugin-react-docgen/4.2.1: resolution: {integrity: sha512-UQ0NmGHj/HAqi5Bew8WvNfCk8wSsmdgNd8ZdMjBCICtyCJCq9LiqgqvjCYe570/Wg7AQArSq1VQ60Dd/CHN7mQ==} dependencies: @@ -10022,17 +10424,6 @@ packages: '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.16.7 '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.16.7 - /babel-preset-jest/26.6.2_@babel+core@7.16.0: - resolution: {integrity: sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ==} - engines: {node: '>= 10.14.2'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.16.0 - babel-plugin-jest-hoist: 26.6.2 - babel-preset-current-node-syntax: 1.0.1_@babel+core@7.16.0 - dev: false - /babel-preset-jest/27.4.0_@babel+core@7.16.0: resolution: {integrity: sha512-NK4jGYpnBvNxcGo7/ZpZJr51jCGT+3bwwpVIDY2oNfTxJJldRtB4VAcYdgp1loDE50ODuTu+yBjpMAswv5tlpg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -10475,6 +10866,7 @@ packages: engines: {node: 6.* || 8.* || >= 10.*} dependencies: rsvp: 4.8.5 + dev: true /case-sensitive-paths-webpack-plugin/2.4.0: resolution: {integrity: sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==} @@ -10677,6 +11069,7 @@ packages: /ci-info/2.0.0: resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} + dev: true /ci-info/3.3.0: resolution: {integrity: sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==} @@ -10953,8 +11346,8 @@ packages: engines: {node: '>= 12'} dev: true - /comment-parser/1.2.4: - resolution: {integrity: sha512-pm0b+qv+CkWNriSTMsfnjChF9kH0kxz55y44Wo5le9qLxMj5xDQAaEd9ZN1ovSuk9CsrncWaFwgpOMg7ClJwkw==} + /comment-parser/1.3.0: + resolution: {integrity: sha512-hRpmWIKgzd81vn0ydoWoyPoALEOnF4wt8yKD35Ib1D6XC2siLiYaiqfGkYrunuKdsXGwpBpHU3+9r+RVw2NZfA==} engines: {node: '>= 12.0.0'} dev: true @@ -11281,6 +11674,7 @@ packages: semver: 5.7.1 shebang-command: 1.2.0 which: 1.3.1 + dev: true /cross-spawn/7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} @@ -11810,11 +12204,6 @@ packages: resolution: {integrity: sha512-daj+rzR3QSxsPRy5vjjthn58axO8c11j58uY0lG5vvlJk/EiOdCWOptGdkXDjtuRHr78emKq0udHCXM4trhoDQ==} dev: true - /diff-sequences/26.6.2: - resolution: {integrity: sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==} - engines: {node: '>= 10.14.2'} - dev: false - /diff-sequences/27.4.0: resolution: {integrity: sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -12150,13 +12539,6 @@ packages: graceful-fs: 4.2.9 tapable: 2.2.1 - /enquirer/2.3.6: - resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} - engines: {node: '>=8.6'} - dependencies: - ansi-colors: 4.1.1 - dev: true - /entities/1.1.2: resolution: {integrity: sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==} dev: false @@ -12400,25 +12782,16 @@ packages: optionalDependencies: source-map: 0.6.1 - /eslint-config-prettier/7.2.0_eslint@7.32.0: - resolution: {integrity: sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - dependencies: - eslint: 7.32.0 - dev: true - - /eslint-config-prettier/8.3.0_eslint@7.32.0: + /eslint-config-prettier/8.3.0_eslint@8.8.0: resolution: {integrity: sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 7.32.0 + eslint: 8.8.0 dev: true - /eslint-config-wpcalypso/6.1.0_3eb42fe7d0610a71481faeb55adacf83: + /eslint-config-wpcalypso/6.1.0_11dfa443dfb9bfd86a5486c959f4047a: resolution: {integrity: sha512-FMdXC+jjS4vPI2zJ6b+C0cevn75SBC35DDgOgrRd6a4KriIQAiKhXQz14d7ivFyT48nOX6rEfJQqb4keKD5z/w==} peerDependencies: eslint: ^7.0.0 @@ -12426,11 +12799,11 @@ packages: eslint-plugin-jsdoc: ^18.0.0 eslint-plugin-wpcalypso: ^3.4.1 || ^4.0.0 dependencies: - eslint: 7.32.0 - eslint-plugin-inclusive-language: 1.2.1 - eslint-plugin-jsdoc: 36.1.1_eslint@7.32.0 - eslint-plugin-react-hooks: 4.3.0_eslint@7.32.0 - eslint-plugin-wpcalypso: 5.0.0_eslint@7.32.0 + eslint: 8.8.0 + eslint-plugin-inclusive-language: 2.2.0 + eslint-plugin-jsdoc: 37.7.0_eslint@8.8.0 + eslint-plugin-react-hooks: 4.3.0_eslint@8.8.0 + eslint-plugin-wpcalypso: 5.0.0_eslint@8.8.0 dev: true /eslint-import-resolver-node/0.3.6: @@ -12448,23 +12821,23 @@ packages: find-up: 2.1.0 dev: true - /eslint-plugin-es/4.1.0_eslint@7.32.0: + /eslint-plugin-es/4.1.0_eslint@8.8.0: resolution: {integrity: sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==} engines: {node: '>=8.10.0'} peerDependencies: eslint: '>=4.19.1' dependencies: - eslint: 7.32.0 + eslint: 8.8.0 eslint-utils: 2.1.0 regexpp: 3.2.0 dev: true - /eslint-plugin-es5/1.5.0_eslint@7.32.0: + /eslint-plugin-es5/1.5.0_eslint@8.8.0: resolution: {integrity: sha512-Qxmfo7v2B7SGAEURJo0dpBweFf+JU15kSyALfiB2rXWcBuJ96r6X9kFHXFnhdopPHCaHjoQs1xQPUJVbGMb1AA==} peerDependencies: eslint: '>= 3.0.0' dependencies: - eslint: 7.32.0 + eslint: 8.8.0 dev: true /eslint-plugin-import/2.25.4: @@ -12488,7 +12861,7 @@ packages: tsconfig-paths: 3.12.0 dev: true - /eslint-plugin-import/2.25.4_eslint@7.32.0: + /eslint-plugin-import/2.25.4_eslint@8.8.0: resolution: {integrity: sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==} engines: {node: '>=4'} peerDependencies: @@ -12498,7 +12871,7 @@ packages: array.prototype.flat: 1.2.5 debug: 2.6.9 doctrine: 2.1.0 - eslint: 7.32.0 + eslint: 8.8.0 eslint-import-resolver-node: 0.3.6 eslint-module-utils: 2.7.2 has: 1.0.3 @@ -12510,58 +12883,65 @@ packages: tsconfig-paths: 3.12.0 dev: true - /eslint-plugin-inclusive-language/1.2.1: - resolution: {integrity: sha512-WFXME2g/rEm/ex9HCfptZXJVm6/IrBks4+0rZft24zve4RH196PPuCFvd36aidc2IaHrvVAZHeyahODc7ueoNw==} + /eslint-plugin-inclusive-language/2.2.0: + resolution: {integrity: sha512-RzPeSjuw1NYiTSQyFzYl2uTDgiPQWDUmFCiGAMCITmXN627DsWZ9rR4KNzrb8vnk/gLL5qdYr8oxh44xsrcO5Q==} + dependencies: + humps: 2.0.1 dev: true - /eslint-plugin-jest/24.7.0_d3b4c2d4ac51f4275548d5d796aee5d5: - resolution: {integrity: sha512-wUxdF2bAZiYSKBclsUMrYHH6WxiBreNjyDxbRv345TIvPeoCEgPNEn3Sa+ZrSqsf1Dl9SqqSREXMHExlMMu1DA==} - engines: {node: '>=10'} + /eslint-plugin-jest/25.7.0_2710175b8e1738b8f39f06cfa9aa7159: + resolution: {integrity: sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} peerDependencies: - '@typescript-eslint/eslint-plugin': '>= 4' - eslint: '>=5' + '@typescript-eslint/eslint-plugin': ^4.0.0 || ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + jest: '*' peerDependenciesMeta: '@typescript-eslint/eslint-plugin': optional: true + jest: + optional: true dependencies: - '@typescript-eslint/eslint-plugin': 4.33.0_2951ba233cd46bb4e0f2f0a3f7fe108e - '@typescript-eslint/experimental-utils': 4.33.0_eslint@7.32.0 - eslint: 7.32.0 + '@typescript-eslint/eslint-plugin': 5.10.2_0d682450f1ef58680b7f0316f2e82e26 + '@typescript-eslint/experimental-utils': 5.10.2_eslint@8.8.0 + eslint: 8.8.0 transitivePeerDependencies: - supports-color - typescript dev: true - /eslint-plugin-jest/24.7.0_eslint@7.32.0: - resolution: {integrity: sha512-wUxdF2bAZiYSKBclsUMrYHH6WxiBreNjyDxbRv345TIvPeoCEgPNEn3Sa+ZrSqsf1Dl9SqqSREXMHExlMMu1DA==} - engines: {node: '>=10'} + /eslint-plugin-jest/26.0.0_eslint@8.8.0: + resolution: {integrity: sha512-Fvs0YgJ/nw9FTrnqTuMGVrkozkd07jkQzWm0ajqyHlfcsdkxGfAuv30fgfWHOnHiCr9+1YQ365CcDX7vrNhqQg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} peerDependencies: - '@typescript-eslint/eslint-plugin': '>= 4' - eslint: '>=5' + '@typescript-eslint/eslint-plugin': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + jest: '*' peerDependenciesMeta: '@typescript-eslint/eslint-plugin': optional: true + jest: + optional: true dependencies: - '@typescript-eslint/experimental-utils': 4.33.0_eslint@7.32.0 - eslint: 7.32.0 + '@typescript-eslint/utils': 5.10.2_eslint@8.8.0 + eslint: 8.8.0 transitivePeerDependencies: - supports-color - typescript dev: true - /eslint-plugin-jsdoc/36.1.1_eslint@7.32.0: - resolution: {integrity: sha512-nuLDvH1EJaKx0PCa9oeQIxH6pACIhZd1gkalTUxZbaxxwokjs7TplqY0Q8Ew3CoZaf5aowm0g/Z3JGHCatt+gQ==} - engines: {node: ^12 || ^14 || ^16} + /eslint-plugin-jsdoc/37.7.0_eslint@8.8.0: + resolution: {integrity: sha512-vzy3/ltXoGtabRnjLogaEmhGxxIv5B8HK5MJLIrdxFJUvhBppZjuVuLr71DjIBi0jg6bFomwkYKjojt29cN8PA==} + engines: {node: ^12 || ^14 || ^16 || ^17} peerDependencies: - eslint: ^6.0.0 || ^7.0.0 + eslint: ^7.0.0 || ^8.0.0 dependencies: - '@es-joy/jsdoccomment': 0.10.8 - comment-parser: 1.2.4 + '@es-joy/jsdoccomment': 0.18.0 + comment-parser: 1.3.0 debug: 4.3.3 - eslint: 7.32.0 + escape-string-regexp: 4.0.0 + eslint: 8.8.0 esquery: 1.4.0 - jsdoc-type-pratt-parser: 1.2.0 - lodash: 4.17.21 regextras: 0.8.0 semver: 7.3.5 spdx-expression-parse: 3.0.1 @@ -12569,7 +12949,7 @@ packages: - supports-color dev: true - /eslint-plugin-jsx-a11y/6.5.1_eslint@7.32.0: + /eslint-plugin-jsx-a11y/6.5.1_eslint@8.8.0: resolution: {integrity: sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==} engines: {node: '>=4.0'} peerDependencies: @@ -12583,24 +12963,24 @@ packages: axobject-query: 2.2.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 7.32.0 + eslint: 8.8.0 has: 1.0.3 jsx-ast-utils: 3.2.1 language-tags: 1.0.5 minimatch: 3.0.4 dev: true - /eslint-plugin-lodash/7.3.0_eslint@7.32.0: + /eslint-plugin-lodash/7.3.0_eslint@8.8.0: resolution: {integrity: sha512-FQM8HklruJzulPawX3uZqWbeyN3bQT4hjVCpFYMrWo0Hdz1qDCwp1v3JS4zjhdssAXdwCxdnyrNMCZJK70GeUQ==} engines: {node: '>=10'} peerDependencies: eslint: '>=2' dependencies: - eslint: 7.32.0 + eslint: 8.8.0 lodash: 4.17.21 dev: true - /eslint-plugin-prettier/3.4.1_34b707f3a53b0942f3919c1ff656ce36: + /eslint-plugin-prettier/3.4.1_5208900944bd53d50aafd0e7d193e6c3: resolution: {integrity: sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==} engines: {node: '>=6.0.0'} peerDependencies: @@ -12611,39 +12991,39 @@ packages: eslint-config-prettier: optional: true dependencies: - eslint: 7.32.0 - eslint-config-prettier: 7.2.0_eslint@7.32.0 + eslint: 8.8.0 + eslint-config-prettier: 8.3.0_eslint@8.8.0 prettier: /wp-prettier/2.2.1-beta-1 prettier-linter-helpers: 1.0.0 dev: true - /eslint-plugin-prettier/3.4.1_b003eb7dfbbe32a2afc96a18053e1e13: - resolution: {integrity: sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==} + /eslint-plugin-prettier/4.0.0_5208900944bd53d50aafd0e7d193e6c3: + resolution: {integrity: sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==} engines: {node: '>=6.0.0'} peerDependencies: - eslint: '>=5.0.0' + eslint: '>=7.28.0' eslint-config-prettier: '*' - prettier: '>=1.13.0' + prettier: '>=2.0.0' peerDependenciesMeta: eslint-config-prettier: optional: true dependencies: - eslint: 7.32.0 - eslint-config-prettier: 8.3.0_eslint@7.32.0 + eslint: 8.8.0 + eslint-config-prettier: 8.3.0_eslint@8.8.0 prettier: /wp-prettier/2.2.1-beta-1 prettier-linter-helpers: 1.0.0 dev: true - /eslint-plugin-react-hooks/4.3.0_eslint@7.32.0: + /eslint-plugin-react-hooks/4.3.0_eslint@8.8.0: resolution: {integrity: sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==} engines: {node: '>=10'} peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 dependencies: - eslint: 7.32.0 + eslint: 8.8.0 dev: true - /eslint-plugin-react/7.28.0_eslint@7.32.0: + /eslint-plugin-react/7.28.0_eslint@8.8.0: resolution: {integrity: sha512-IOlFIRHzWfEQQKcAD4iyYDndHwTQiCMcJVJjxempf203jnNLUnW34AXLrV33+nEXoifJE2ZEGmcjKPL8957eSw==} engines: {node: '>=4'} peerDependencies: @@ -12652,7 +13032,7 @@ packages: array-includes: 3.1.4 array.prototype.flatmap: 1.2.5 doctrine: 2.1.0 - eslint: 7.32.0 + eslint: 8.8.0 estraverse: 5.3.0 jsx-ast-utils: 3.2.1 minimatch: 3.0.4 @@ -12676,13 +13056,13 @@ packages: svelte: 3.42.4 dev: true - /eslint-plugin-wpcalypso/5.0.0_eslint@7.32.0: + /eslint-plugin-wpcalypso/5.0.0_eslint@8.8.0: resolution: {integrity: sha512-pcghYspmOv+KzBr+jlDMaazKc8ZKs4vm/dbZWpqCm26wbgCfCpe4276gZJRfUv7Zs+puy3+7h1i/Bd5zfiKBnA==} engines: {node: '>=10'} peerDependencies: eslint: '>=5' dependencies: - eslint: 7.32.0 + eslint: 8.8.0 dev: true /eslint-scope/5.1.1: @@ -12692,6 +13072,14 @@ packages: esrecurse: 4.3.0 estraverse: 4.3.0 + /eslint-scope/7.1.0: + resolution: {integrity: sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + /eslint-utils/2.1.0: resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} engines: {node: '>=6'} @@ -12708,13 +13096,13 @@ packages: eslint-visitor-keys: 2.1.0 dev: true - /eslint-utils/3.0.0_eslint@7.32.0: + /eslint-utils/3.0.0_eslint@8.8.0: resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} peerDependencies: eslint: '>=5' dependencies: - eslint: 7.32.0 + eslint: 8.8.0 eslint-visitor-keys: 2.1.0 dev: true @@ -12728,62 +13116,62 @@ packages: engines: {node: '>=10'} dev: true - /eslint/7.32.0: - resolution: {integrity: sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==} - engines: {node: ^10.12.0 || >=12.0.0} + /eslint-visitor-keys/3.2.0: + resolution: {integrity: sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint/8.8.0: + resolution: {integrity: sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@babel/code-frame': 7.12.11 - '@eslint/eslintrc': 0.4.3 - '@humanwhocodes/config-array': 0.5.0 + '@eslint/eslintrc': 1.0.5 + '@humanwhocodes/config-array': 0.9.3 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 debug: 4.3.3 doctrine: 3.0.0 - enquirer: 2.3.6 escape-string-regexp: 4.0.0 - eslint-scope: 5.1.1 - eslint-utils: 2.1.0 - eslint-visitor-keys: 2.1.0 - espree: 7.3.1 + eslint-scope: 7.1.0 + eslint-utils: 3.0.0_eslint@8.8.0 + eslint-visitor-keys: 3.2.0 + espree: 9.3.0 esquery: 1.4.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 6.0.1 functional-red-black-tree: 1.0.1 - glob-parent: 5.1.2 + glob-parent: 6.0.2 globals: 13.12.0 - ignore: 4.0.6 + ignore: 5.2.0 import-fresh: 3.3.0 imurmurhash: 0.1.4 is-glob: 4.0.3 - js-yaml: 3.14.1 + js-yaml: 4.1.0 json-stable-stringify-without-jsonify: 1.0.1 levn: 0.4.1 lodash.merge: 4.6.2 minimatch: 3.0.4 natural-compare: 1.4.0 optionator: 0.9.1 - progress: 2.0.3 regexpp: 3.2.0 - semver: 7.3.5 strip-ansi: 6.0.1 strip-json-comments: 3.1.1 - table: 6.8.0 text-table: 0.2.0 v8-compile-cache: 2.3.0 transitivePeerDependencies: - supports-color dev: true - /espree/7.3.1: - resolution: {integrity: sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==} - engines: {node: ^10.12.0 || >=12.0.0} + /espree/9.3.0: + resolution: {integrity: sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - acorn: 7.4.1 - acorn-jsx: 5.3.2_acorn@7.4.1 - eslint-visitor-keys: 1.3.0 + acorn: 8.7.0 + acorn-jsx: 5.3.2_acorn@8.7.0 + eslint-visitor-keys: 3.2.0 dev: true /esprima/4.0.1: @@ -12892,6 +13280,7 @@ packages: /exec-sh/0.3.6: resolution: {integrity: sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==} + dev: true /execa/1.0.0: resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} @@ -12904,6 +13293,7 @@ packages: p-finally: 1.0.0 signal-exit: 3.0.6 strip-eof: 1.0.0 + dev: true /execa/5.0.0: resolution: {integrity: sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==} @@ -13738,6 +14128,7 @@ packages: engines: {node: '>=6'} dependencies: pump: 3.0.0 + dev: true /get-stream/5.2.0: resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} @@ -13940,13 +14331,6 @@ packages: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} - /globals/12.4.0: - resolution: {integrity: sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.8.1 - dev: true - /globals/13.12.0: resolution: {integrity: sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==} engines: {node: '>=8'} @@ -14455,7 +14839,6 @@ packages: resolution: {integrity: sha512-uPSF6lAJb3nSePJ43hN3eKj1dTWpN9gMod0ZssbFTIsen+WehTmEadgL+kg78xLJFdRfrrC//SavDzmRVdE+Ig==} dependencies: '@babel/runtime': 7.16.7 - dev: true /hmac-drbg/1.0.1: resolution: {integrity: sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=} @@ -14645,6 +15028,10 @@ packages: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} + /humps/2.0.1: + resolution: {integrity: sha1-3QLqYIG9BWjcXQcxhEY5V7qe+ao=} + dev: true + /husky/7.0.4: resolution: {integrity: sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==} engines: {node: '>=12'} @@ -14711,7 +15098,6 @@ packages: /ignore/5.1.8: resolution: {integrity: sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==} engines: {node: '>= 4'} - dev: true /ignore/5.2.0: resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} @@ -14918,6 +15304,7 @@ packages: hasBin: true dependencies: ci-info: 2.0.0 + dev: true /is-core-module/2.8.1: resolution: {integrity: sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==} @@ -15468,16 +15855,6 @@ packages: - supports-color - utf-8-validate - /jest-diff/26.6.2: - resolution: {integrity: sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==} - engines: {node: '>= 10.14.2'} - dependencies: - chalk: 4.1.2 - diff-sequences: 26.6.2 - jest-get-type: 26.3.0 - pretty-format: 26.6.2 - dev: false - /jest-diff/27.4.6: resolution: {integrity: sha512-zjaB0sh0Lb13VyPsd92V7HkqF6yKRH9vm33rwBt7rPYrpQvS1nCvlIy2pICbKta+ZjWngYLNn4cCK4nyZkjS/w==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -15586,11 +15963,6 @@ packages: - utf-8-validate dev: true - /jest-get-type/26.3.0: - resolution: {integrity: sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==} - engines: {node: '>= 10.14.2'} - dev: false - /jest-get-type/27.4.0: resolution: {integrity: sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -15614,6 +15986,7 @@ packages: walker: 1.0.8 optionalDependencies: fsevents: 2.3.2 + dev: true /jest-haste-map/27.4.6: resolution: {integrity: sha512-0tNpgxg7BKurZeFkIOvGCkbmOHbLFf4LUQOxrQSMjvrQaQe3l6E8x6jYC1NuWkGo5WDdbr8FEzUxV2+LWNawKQ==} @@ -15665,16 +16038,6 @@ packages: jest-get-type: 27.4.0 pretty-format: 27.4.6 - /jest-matcher-utils/26.6.2: - resolution: {integrity: sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==} - engines: {node: '>= 10.14.2'} - dependencies: - chalk: 4.1.2 - jest-diff: 26.6.2 - jest-get-type: 26.3.0 - pretty-format: 26.6.2 - dev: false - /jest-matcher-utils/27.4.6: resolution: {integrity: sha512-XD4PKT3Wn1LQnRAq7ZsTI0VRuEc9OrCPFiO1XL7bftTGmfNF0DcEwMHRgqiu7NGf8ZoZDREpGrCniDkjt79WbA==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -15719,6 +16082,7 @@ packages: /jest-regex-util/26.0.0: resolution: {integrity: sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==} engines: {node: '>= 10.14.2'} + dev: true /jest-regex-util/27.4.0: resolution: {integrity: sha512-WeCpMpNnqJYMQoOjm1nTtsgbR4XHAk1u00qDoNBQoykM280+/TmgA5Qh5giC1ecy6a5d4hbSsHzpBtu5yvlbEg==} @@ -15816,6 +16180,7 @@ packages: dependencies: '@types/node': 17.0.8 graceful-fs: 4.2.9 + dev: true /jest-serializer/27.4.0: resolution: {integrity: sha512-RDhpcn5f1JYTX2pvJAGDcnsNTnsV9bjYPU8xcV+xPwOXnUPOQwf4ZEuiU6G9H1UztH+OapMgu/ckEVwO87PwnQ==} @@ -15863,6 +16228,7 @@ packages: graceful-fs: 4.2.9 is-ci: 2.0.0 micromatch: 4.0.4 + dev: true /jest-util/27.4.2: resolution: {integrity: sha512-YuxxpXU6nlMan9qyLuxHaMMOzXAl5aGZWCSzben5DhLHemYQxCc4YK+4L3ZrCutT8GPQ+ui9k5D8rUJoDioMnA==} @@ -15905,6 +16271,7 @@ packages: '@types/node': 17.0.8 merge-stream: 2.0.0 supports-color: 7.2.0 + dev: true /jest-worker/27.4.6: resolution: {integrity: sha512-gHWJF/6Xi5CTG5QCvROr6GcmpIqNYpDJyc8A1h/DyXqH1tD6SnRCM0d3U5msV31D2LB/U+E0M+W4oyvKV44oNw==} @@ -15964,19 +16331,13 @@ packages: hasBin: true dependencies: argparse: 2.0.1 - dev: false /jsbn/0.1.1: resolution: {integrity: sha1-peZUwuWi3rXyAdls77yoDA7y9RM=} dev: false - /jsdoc-type-pratt-parser/1.1.1: - resolution: {integrity: sha512-uelRmpghNwPBuZScwgBG/OzodaFk5RbO5xaivBdsAY70icWfShwZ7PCMO0x1zSkOa8T1FzHThmrdoyg/0AwV5g==} - engines: {node: '>=12.0.0'} - dev: true - - /jsdoc-type-pratt-parser/1.2.0: - resolution: {integrity: sha512-4STjeF14jp4bqha44nKMY1OUI6d2/g6uclHWUCZ7B4DoLzaB5bmpTkQrpqU+vSVzMD0LsKAOskcnI3I3VfIpmg==} + /jsdoc-type-pratt-parser/2.2.2: + resolution: {integrity: sha512-zRokSWcPLSWkoNzsWn9pq7YYSwDhKyEe+cJYT2qaPqLOOJb5sFSi46BPj81vP+e8chvCNdQL9RG86Bi9EI6MDw==} engines: {node: '>=12.0.0'} dev: true @@ -16561,10 +16922,6 @@ packages: resolution: {integrity: sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=} dev: true - /lodash.truncate/4.4.2: - resolution: {integrity: sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=} - dev: true - /lodash.uniq/4.5.0: resolution: {integrity: sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=} @@ -16752,7 +17109,7 @@ packages: /md5-es/1.8.2: resolution: {integrity: sha512-LKq5jmKMhJYhsBFUh2w+J3C4bMiC5uQie/UYJ429UATmMnFr6iANO2uQq5HXAZSIupGp0WO2mH3sNfxR4XO40Q==} - dev: false + dev: true /md5.js/1.3.5: resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} @@ -17165,6 +17522,7 @@ packages: /nice-try/1.0.5: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} + dev: true /nise/4.1.0: resolution: {integrity: sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==} @@ -17352,6 +17710,7 @@ packages: engines: {node: '>=4'} dependencies: path-key: 2.0.1 + dev: true /npm-run-path/4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} @@ -17663,6 +18022,7 @@ packages: /p-finally/1.0.0: resolution: {integrity: sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=} engines: {node: '>=4'} + dev: true /p-limit/1.3.0: resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} @@ -17683,6 +18043,13 @@ packages: dependencies: yocto-queue: 0.1.0 + /p-limit/4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + yocto-queue: 1.0.0 + dev: false + /p-locate/2.0.0: resolution: {integrity: sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=} engines: {node: '>=4'} @@ -17885,6 +18252,7 @@ packages: /path-key/2.0.1: resolution: {integrity: sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=} engines: {node: '>=4'} + dev: true /path-key/3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} @@ -18750,6 +19118,7 @@ packages: dependencies: end-of-stream: 1.4.4 once: 1.4.0 + dev: true /pumpify/1.5.1: resolution: {integrity: sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==} @@ -19101,7 +19470,7 @@ packages: engines: {node: '>=8.10.0'} hasBin: true dependencies: - '@babel/core': 7.16.0 + '@babel/core': 7.16.7 '@babel/generator': 7.16.7 '@babel/runtime': 7.16.7 ast-types: 0.14.2 @@ -19448,7 +19817,6 @@ packages: react: 17.0.2 react-dom: 17.0.2_react@17.0.2 react-router: 6.2.1_react@17.0.2 - dev: true /react-router-dom/6.2.1_react@17.0.2: resolution: {integrity: sha512-I6Zax+/TH/cZMDpj3/4Fl2eaNdcvoxxHoH1tYOREsQ22OKDYofGebrNm6CTPUcvLvZm63NL/vzCYdjf9CUhqmA==} @@ -19486,7 +19854,6 @@ packages: dependencies: history: 5.2.0 react: 17.0.2 - dev: true /react-shallow-renderer/16.14.1: resolution: {integrity: sha512-rkIMcQi01/+kxiTE9D3fdS959U1g7gs+/rborw++42m1O9FAQiNI/UNRZExVUoAOprn4umcXf+pFRou8i4zuBg==} @@ -19522,7 +19889,7 @@ packages: react: '>= 16.8.0' react-dom: '>= 16.8.0' dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.16.7 prop-types: 15.7.2 react: 17.0.2 react-dom: 17.0.2_react@17.0.2 @@ -20561,6 +20928,7 @@ packages: /rsvp/4.8.5: resolution: {integrity: sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==} engines: {node: 6.* || >= 7.*} + dev: true /rtlcss/2.6.2: resolution: {integrity: sha512-06LFAr+GAPo+BvaynsXRfoYTJvSaWRyOhURCQ7aeI1MKph9meM222F+Zkt3bDamyHHJuGi3VPtiRkpyswmQbGA==} @@ -20647,6 +21015,7 @@ packages: micromatch: 3.1.10 minimist: 1.2.5 walker: 1.0.8 + dev: true /sass-loader/12.4.0_sass@1.38.1+webpack@5.65.0: resolution: {integrity: sha512-7xN+8khDIzym1oL9XyS6zP6Ges+Bo2B2xbPrjdMHEYyV3AQYhd/wXeru++3ODHF0zMjYmVadblSKrPrjEkL8mg==} @@ -20943,6 +21312,7 @@ packages: engines: {node: '>=0.10.0'} dependencies: shebang-regex: 1.0.0 + dev: true /shebang-command/2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} @@ -20953,6 +21323,7 @@ packages: /shebang-regex/1.0.0: resolution: {integrity: sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=} engines: {node: '>=0.10.0'} + dev: true /shebang-regex/3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} @@ -21063,15 +21434,6 @@ packages: engines: {node: '>=0.10.0'} dev: false - /slice-ansi/4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - dev: true - /snapdragon-node/2.1.1: resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} engines: {node: '>=0.10.0'} @@ -21138,9 +21500,6 @@ packages: resolution: {integrity: sha1-mIkBnRAkzOVc3AaUmDN+9hhqEaE=} dev: false - /source-list-map/2.0.1: - resolution: {integrity: sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==} - /source-map-js/0.6.2: resolution: {integrity: sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==} engines: {node: '>=0.10.0'} @@ -21536,6 +21895,7 @@ packages: /strip-eof/1.0.0: resolution: {integrity: sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=} engines: {node: '>=0.10.0'} + dev: true /strip-final-newline/2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} @@ -21771,17 +22131,6 @@ packages: resolution: {integrity: sha512-40pEZ2mhjaZzK0BnI+QGNjJO8UYx9pP5v7BGe17SORTO0OEuuaAwQTkAp8whcZvqon44wKFOikD+Al11K3JICQ==} dev: false - /table/6.8.0: - resolution: {integrity: sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==} - engines: {node: '>=10.0.0'} - dependencies: - ajv: 8.8.2 - lodash.truncate: 4.4.2 - slice-ansi: 4.0.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - /tannin/1.2.0: resolution: {integrity: sha512-U7GgX/RcSeUETbV7gYgoz8PD7Ni4y95pgIP/Z6ayI3CfhSujwKEBlGFTCRN+Aqnuyf4AN2yHL+L8x+TCGjb9uA==} dependencies: @@ -22956,13 +23305,6 @@ packages: source-map: 0.5.7 dev: false - /webpack-sources/2.3.1: - resolution: {integrity: sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==} - engines: {node: '>=10.13.0'} - dependencies: - source-list-map: 2.0.1 - source-map: 0.6.1 - /webpack-sources/3.2.2: resolution: {integrity: sha512-cp5qdmHnu5T8wRg2G3vZZHoJPN14aqQ89SyQ11NpGH5zEMDCclt49rzo+MaRazk7/UeILhAI+/sEtcM+7Fr0nw==} engines: {node: '>=10.13.0'} @@ -23399,6 +23741,11 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + /yocto-queue/1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + dev: false + /zwitch/1.0.5: resolution: {integrity: sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==} dev: true @@ -23417,7 +23764,7 @@ packages: - encoding dev: false - github.com/sveltejs/eslint-config/8a67624e4080bd7997606eb34981aa3346bc8de2_0ca1a0e6c61895213d3918b4d67bc4f3: + github.com/sveltejs/eslint-config/8a67624e4080bd7997606eb34981aa3346bc8de2_948a3e55fb7525b40c6fc4d3c0529949: resolution: {tarball: https://codeload.github.com/sveltejs/eslint-config/tar.gz/8a67624e4080bd7997606eb34981aa3346bc8de2} id: github.com/sveltejs/eslint-config/8a67624e4080bd7997606eb34981aa3346bc8de2 name: '@sveltejs/eslint-config' @@ -23431,8 +23778,8 @@ packages: eslint-plugin-svelte3: '>= 2' typescript: '>= 3' dependencies: - '@typescript-eslint/eslint-plugin': 4.33.0_8c654464cf7de6904a251c0e456613ed - '@typescript-eslint/parser': 4.33.0_typescript@4.3.5 + '@typescript-eslint/eslint-plugin': 5.10.2_9b53d4b455d21bf3af38fdac900301d2 + '@typescript-eslint/parser': 5.10.2_typescript@4.3.5 eslint-plugin-import: 2.25.4 eslint-plugin-svelte3: 3.2.1_svelte@3.42.4 typescript: 4.3.5 diff --git a/projects/github-actions/repo-gardening/CHANGELOG.md b/projects/github-actions/repo-gardening/CHANGELOG.md index bc9917a47b6fe..1b1a29425dfbf 100644 --- a/projects/github-actions/repo-gardening/CHANGELOG.md +++ b/projects/github-actions/repo-gardening/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.1] - 2022-02-01 +### Changed +- General: update required node version to v16.13.2 +- Updated package dependencies + ## [2.0.0] - 2021-11-02 ### Added - Automatically add the RNA label to PRs. @@ -74,6 +79,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Initial release +[2.0.1]: https://github.com/Automattic/action-repo-gardening/compare/v2.0.0...v2.0.1 [2.0.0]: https://github.com/Automattic/action-repo-gardening/compare/v1.4.0...v2.0.0 [1.4.0]: https://github.com/Automattic/action-repo-gardening/compare/v1.3.0...v1.4.0 [1.3.0]: https://github.com/Automattic/action-repo-gardening/compare/v1.2.2...v1.3.0 diff --git a/projects/github-actions/repo-gardening/changelog/update-min-pnpm-version b/projects/github-actions/repo-gardening/changelog/update-min-pnpm-version deleted file mode 100644 index d824134990470..0000000000000 --- a/projects/github-actions/repo-gardening/changelog/update-min-pnpm-version +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: changed -Comment: Update minimum pnpm version. - - diff --git a/projects/github-actions/repo-gardening/changelog/update-node-version-16132 b/projects/github-actions/repo-gardening/changelog/update-node-version-16132 deleted file mode 100644 index feb2fb77ea11d..0000000000000 --- a/projects/github-actions/repo-gardening/changelog/update-node-version-16132 +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: changed - -General: update required node version to v16.13.2 diff --git a/projects/github-actions/repo-gardening/changelog/update-project-scripts-no-install b/projects/github-actions/repo-gardening/changelog/update-project-scripts-no-install deleted file mode 100644 index f45fac5ea79e2..0000000000000 --- a/projects/github-actions/repo-gardening/changelog/update-project-scripts-no-install +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: removed -Comment: Tooling only: Build and test scripts no longer call `composer install` or `pnpm install`. - - diff --git a/projects/github-actions/repo-gardening/package.json b/projects/github-actions/repo-gardening/package.json index 28e266883a6f6..54455116d02e1 100644 --- a/projects/github-actions/repo-gardening/package.json +++ b/projects/github-actions/repo-gardening/package.json @@ -1,6 +1,6 @@ { "name": "repo-gardening", - "version": "2.0.1-alpha", + "version": "2.0.1", "description": "Manage PR and issues in your Open Source project (automate labelling, milestones, feedback to PR authors, ...)", "author": "Automattic", "license": "GPL-2.0-or-later", diff --git a/projects/js-packages/analytics/CHANGELOG.md b/projects/js-packages/analytics/CHANGELOG.md index 9267e052e08d6..0aef61d7172e6 100644 --- a/projects/js-packages/analytics/CHANGELOG.md +++ b/projects/js-packages/analytics/CHANGELOG.md @@ -2,6 +2,10 @@ ### This is a list detailing changes for the Jetpack RNA Analytics package releases. +## 0.1.7 - 2022-01-25 +### Changed +- Updated package dependencies. + ## 0.1.6 - 2022-01-18 ### Changed - General: update required node version to v16.13.2 diff --git a/projects/js-packages/analytics/changelog/update-project-scripts-no-install b/projects/js-packages/analytics/changelog/update-project-scripts-no-install deleted file mode 100644 index f45fac5ea79e2..0000000000000 --- a/projects/js-packages/analytics/changelog/update-project-scripts-no-install +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: removed -Comment: Tooling only: Build and test scripts no longer call `composer install` or `pnpm install`. - - diff --git a/projects/js-packages/analytics/package.json b/projects/js-packages/analytics/package.json index ba8ce48d09e64..0879adc0c1110 100644 --- a/projects/js-packages/analytics/package.json +++ b/projects/js-packages/analytics/package.json @@ -1,6 +1,6 @@ { "name": "@automattic/jetpack-analytics", - "version": "0.1.7-alpha", + "version": "0.1.7", "description": "Jetpack Analytics Package", "author": "Automattic", "license": "GPL-2.0-or-later", diff --git a/projects/js-packages/api/CHANGELOG.md b/projects/js-packages/api/CHANGELOG.md index 1a4cf3db5e170..e0f5930d95e07 100644 --- a/projects/js-packages/api/CHANGELOG.md +++ b/projects/js-packages/api/CHANGELOG.md @@ -2,6 +2,10 @@ ### This is a list detailing changes for the Jetpack RNA Components package releases. +## 0.8.3 - 2022-01-25 +### Changed +- Updated package dependencies. + ## 0.8.2 - 2022-01-18 ### Changed - General: update required node version to v16.13.2 diff --git a/projects/github-actions/repo-gardening/changelog/renovate-node-fetch-2.x b/projects/js-packages/api/changelog/renovate-wordpress-monorepo similarity index 100% rename from projects/github-actions/repo-gardening/changelog/renovate-node-fetch-2.x rename to projects/js-packages/api/changelog/renovate-wordpress-monorepo diff --git a/projects/js-packages/api/changelog/update-project-scripts-no-install b/projects/js-packages/api/changelog/update-project-scripts-no-install deleted file mode 100644 index f45fac5ea79e2..0000000000000 --- a/projects/js-packages/api/changelog/update-project-scripts-no-install +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: removed -Comment: Tooling only: Build and test scripts no longer call `composer install` or `pnpm install`. - - diff --git a/projects/js-packages/api/package.json b/projects/js-packages/api/package.json index e2f87b6a37c1e..0ee6411826867 100644 --- a/projects/js-packages/api/package.json +++ b/projects/js-packages/api/package.json @@ -1,12 +1,12 @@ { "name": "@automattic/jetpack-api", - "version": "0.8.3-alpha", + "version": "0.8.4-alpha", "description": "Jetpack Api Package", "author": "Automattic", "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/url": "3.3.1", - "@automattic/jetpack-config": "workspace:^0.1.3-alpha", + "@wordpress/url": "3.4.0", + "@automattic/jetpack-config": "workspace:^0.1.3", "lodash": "4.17.21" }, "devDependencies": { diff --git a/projects/js-packages/babel-plugin-replace-textdomain/CHANGELOG.md b/projects/js-packages/babel-plugin-replace-textdomain/CHANGELOG.md index 067ddb0158fe1..b70250ef6aece 100644 --- a/projects/js-packages/babel-plugin-replace-textdomain/CHANGELOG.md +++ b/projects/js-packages/babel-plugin-replace-textdomain/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.0.2] - 2022-01-25 +### Changed +- Updated package dependencies. + ## [1.0.1] - 2022-01-18 ### Changed - General: update required node version to v16.13.2 @@ -18,5 +22,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Initial release. - Replace missing domains too. +[1.0.2]: https://github.com/Automattic/babel-plugin-replace-textdomain/compare/v1.0.1...v1.0.2 [1.0.1]: https://github.com/Automattic/babel-plugin-replace-textdomain/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.com/Automattic/babel-plugin-replace-textdomain/compare/v0.1.0...v1.0.0 diff --git a/projects/js-packages/babel-plugin-replace-textdomain/changelog/add-fancy-eslint-ignore b/projects/js-packages/babel-plugin-replace-textdomain/changelog/add-fancy-eslint-ignore deleted file mode 100644 index afe95e481cf32..0000000000000 --- a/projects/js-packages/babel-plugin-replace-textdomain/changelog/add-fancy-eslint-ignore +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: changed -Comment: Hack eslint config to use `.gitignore` and per-dir `.eslintignore`. - - diff --git a/projects/js-packages/babel-plugin-replace-textdomain/changelog/update-project-scripts-no-install b/projects/js-packages/babel-plugin-replace-textdomain/changelog/update-project-scripts-no-install deleted file mode 100644 index f45fac5ea79e2..0000000000000 --- a/projects/js-packages/babel-plugin-replace-textdomain/changelog/update-project-scripts-no-install +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: removed -Comment: Tooling only: Build and test scripts no longer call `composer install` or `pnpm install`. - - diff --git a/projects/js-packages/babel-plugin-replace-textdomain/package.json b/projects/js-packages/babel-plugin-replace-textdomain/package.json index 6faa6a620b6e2..5b39d507a58a1 100644 --- a/projects/js-packages/babel-plugin-replace-textdomain/package.json +++ b/projects/js-packages/babel-plugin-replace-textdomain/package.json @@ -1,6 +1,6 @@ { "name": "@automattic/babel-plugin-replace-textdomain", - "version": "1.0.2-alpha", + "version": "1.0.2", "description": "A Babel plugin to replace the textdomain in gettext-style function calls.", "homepage": "https://jetpack.com", "bugs": { diff --git a/projects/js-packages/base-styles/CHANGELOG.md b/projects/js-packages/base-styles/CHANGELOG.md index da2788a7e9337..37fc66fe6190d 100644 --- a/projects/js-packages/base-styles/CHANGELOG.md +++ b/projects/js-packages/base-styles/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.7] - 2022-01-25 +### Changed +- Updated package dependencies. + ## [0.1.6] - 2022-01-18 ### Changed - General: update required node version to v16.13.2 @@ -44,6 +48,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated package dependencies. - Use Node 16.7.0 in tooling. This shouldn't change the behavior of the code itself. +[0.1.7]: https://github.com/Automattic/jetpack-base-styles/compare/0.1.6...0.1.7 [0.1.6]: https://github.com/Automattic/jetpack-base-styles/compare/0.1.5...0.1.6 [0.1.5]: https://github.com/Automattic/jetpack-base-styles/compare/0.1.4...0.1.5 [0.1.4]: https://github.com/Automattic/jetpack-base-styles/compare/0.1.3...0.1.4 diff --git a/projects/js-packages/eslint-config-target-es/changelog/renovate-mdn-browser-compat-data-4.x b/projects/js-packages/base-styles/changelog/renovate-wordpress-monorepo similarity index 100% rename from projects/js-packages/eslint-config-target-es/changelog/renovate-mdn-browser-compat-data-4.x rename to projects/js-packages/base-styles/changelog/renovate-wordpress-monorepo diff --git a/projects/js-packages/base-styles/changelog/update-project-scripts-no-install b/projects/js-packages/base-styles/changelog/update-project-scripts-no-install deleted file mode 100644 index f45fac5ea79e2..0000000000000 --- a/projects/js-packages/base-styles/changelog/update-project-scripts-no-install +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: removed -Comment: Tooling only: Build and test scripts no longer call `composer install` or `pnpm install`. - - diff --git a/projects/js-packages/base-styles/package.json b/projects/js-packages/base-styles/package.json index 15b9f35e924df..96dbfa7ad8b9d 100644 --- a/projects/js-packages/base-styles/package.json +++ b/projects/js-packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@automattic/jetpack-base-styles", - "version": "0.1.7-alpha", + "version": "0.1.8-alpha", "description": "Jetpack components base styles", "homepage": "https://jetpack.com", "bugs": { @@ -19,7 +19,7 @@ "build-production-js": "echo 'Not implemented." }, "devDependencies": { - "@wordpress/base-styles": "4.0.4" + "@wordpress/base-styles": "4.1.0" }, "engines": { "node": "^14.18.3 || ^16.13.2", diff --git a/projects/js-packages/components/CHANGELOG.md b/projects/js-packages/components/CHANGELOG.md index 2c9a1a89dbfb2..3cfb02d81f27f 100644 --- a/projects/js-packages/components/CHANGELOG.md +++ b/projects/js-packages/components/CHANGELOG.md @@ -2,6 +2,17 @@ ### This is a list detailing changes for the Jetpack RNA Components package releases. +## 0.10.4 - 2022-02-02 +### Added +- Re-organize stories of js-packages components by project and package name + +### Changed +- RNA: Improve layout structure with Container and Col + +## 0.10.3 - 2022-01-25 +### Changed +- Do not style header elements from AdminSection component + ## 0.10.2 - 2022-01-18 ### Changed - General: update required node version to v16.13.2 diff --git a/projects/js-packages/components/changelog/add-fancy-eslint-ignore b/projects/js-packages/components/changelog/add-fancy-eslint-ignore deleted file mode 100644 index afe95e481cf32..0000000000000 --- a/projects/js-packages/components/changelog/add-fancy-eslint-ignore +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: changed -Comment: Hack eslint config to use `.gitignore` and per-dir `.eslintignore`. - - diff --git a/projects/js-packages/eslint-config-target-es/changelog/renovate-mdn-browser-compat-data-4.x#2 b/projects/js-packages/components/changelog/renovate-wordpress-monorepo similarity index 100% rename from projects/js-packages/eslint-config-target-es/changelog/renovate-mdn-browser-compat-data-4.x#2 rename to projects/js-packages/components/changelog/renovate-wordpress-monorepo diff --git a/projects/js-packages/partner-coupon/changelog/update-connection-enforce-initial-state b/projects/js-packages/components/changelog/renovate-wordpress-monorepo#2 similarity index 100% rename from projects/js-packages/partner-coupon/changelog/update-connection-enforce-initial-state rename to projects/js-packages/components/changelog/renovate-wordpress-monorepo#2 diff --git a/projects/js-packages/components/changelog/update-connection-section-my-jetpack-styles b/projects/js-packages/components/changelog/update-connection-section-my-jetpack-styles deleted file mode 100644 index 476dc7f8dd0e9..0000000000000 --- a/projects/js-packages/components/changelog/update-connection-section-my-jetpack-styles +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: changed - -Do not style header elements from AdminSection component diff --git a/projects/js-packages/components/changelog/update-project-scripts-no-install b/projects/js-packages/components/changelog/update-project-scripts-no-install deleted file mode 100644 index f45fac5ea79e2..0000000000000 --- a/projects/js-packages/components/changelog/update-project-scripts-no-install +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: removed -Comment: Tooling only: Build and test scripts no longer call `composer install` or `pnpm install`. - - diff --git a/projects/js-packages/components/components/action-button/stories/index.jsx b/projects/js-packages/components/components/action-button/stories/index.jsx index ccfb95d1ef4f4..6df24feab04af 100644 --- a/projects/js-packages/components/components/action-button/stories/index.jsx +++ b/projects/js-packages/components/components/action-button/stories/index.jsx @@ -6,7 +6,7 @@ import ActionButton from '../index.jsx'; import { action } from '@storybook/addon-actions'; export default { - title: 'Playground/Action Button', + title: 'JS Packages/Components/Action Button', component: ActionButton, // TODO: Storybook Actions are not working. See https://github.com/storybookjs/storybook/issues/7215 argTypes: { diff --git a/projects/js-packages/components/components/admin-page/footer.jsx b/projects/js-packages/components/components/admin-page/footer.jsx deleted file mode 100644 index cb130d487295f..0000000000000 --- a/projects/js-packages/components/components/admin-page/footer.jsx +++ /dev/null @@ -1,51 +0,0 @@ -/** - * External dependencies - */ -import React from 'react'; -import { __ } from '@wordpress/i18n'; -import PropTypes from 'prop-types'; - -/** - * Internal dependencies - */ -import styles from './style.module.scss'; -import JetpackFooter from '../jetpack-footer'; -import Row from '../layout/row'; -import Container from '../layout/container'; -import Col from '../layout/col'; - -/** - * Footer for the AdminPage component - * - * @param {object} props - Component properties. - * @returns {React.Component} AdminPage component. - */ -const AdminPageFooter = props => { - const { moduleName, a8cLogoHref } = props; - - return ( -
- - - - - - - -
- ); -}; - -AdminPageFooter.defaultProps = { - a8cLogoHref: 'https://jetpack.com', - moduleName: __( 'Jetpack', 'jetpack' ), -}; - -AdminPageFooter.propTypes = { - /** Link for 'An Automattic Airline' in the footer. */ - a8cLogoHref: PropTypes.string, - /** Name of the module, e.g. 'Jetpack Search' that will be displayed in the footer. */ - moduleName: PropTypes.string, -}; - -export default AdminPageFooter; diff --git a/projects/js-packages/components/components/admin-page/header.jsx b/projects/js-packages/components/components/admin-page/header.jsx deleted file mode 100644 index 5d23d46f13f9c..0000000000000 --- a/projects/js-packages/components/components/admin-page/header.jsx +++ /dev/null @@ -1,32 +0,0 @@ -/** - * External dependencies - */ -import React from 'react'; - -/** - * Internal dependencies - */ -import styles from './style.module.scss'; -import JetpackLogo from '../jetpack-logo'; -import Row from '../layout/row'; -import Container from '../layout/container'; -import Col from '../layout/col'; - -/** - * Header for the AdminPage component - * - * @returns {React.Component} AdminPage component. - */ -const AdminPageHeader = () => ( -
- - - - - - - -
-); - -export default AdminPageHeader; diff --git a/projects/js-packages/components/components/admin-page/index.jsx b/projects/js-packages/components/components/admin-page/index.jsx index 865a0353ed93f..10e770a7561cb 100644 --- a/projects/js-packages/components/components/admin-page/index.jsx +++ b/projects/js-packages/components/components/admin-page/index.jsx @@ -9,8 +9,10 @@ import PropTypes from 'prop-types'; * Internal dependencies */ import styles from './style.module.scss'; -import AdminPageHeader from './header'; -import AdminPageFooter from './footer'; +import JetpackFooter from '../jetpack-footer'; +import JetpackLogo from '../jetpack-logo'; +import Container from '../layout/container'; +import Col from '../layout/col'; /** * This is the base structure for any admin page. It comes with Header and Footer. @@ -24,10 +26,24 @@ const AdminPage = props => { const { children, moduleName, a8cLogoHref, showHeader, showFooter } = props; return ( -
- { showHeader && } - { children } - { showFooter && } +
+ { showHeader && ( + + + + + + ) } + + { children } + + { showFooter && ( + + + + + + ) }
); }; diff --git a/projects/js-packages/components/components/admin-page/stories/index.jsx b/projects/js-packages/components/components/admin-page/stories/index.jsx index 3e9ee09d538b7..c57f8b46b15fb 100644 --- a/projects/js-packages/components/components/admin-page/stories/index.jsx +++ b/projects/js-packages/components/components/admin-page/stories/index.jsx @@ -5,7 +5,7 @@ import React from 'react'; import AdminPage from '../index.jsx'; export default { - title: 'Playground/Admin Page', + title: 'JS Packages/Components/Admin Page', component: AdminPage, }; diff --git a/projects/js-packages/components/components/admin-page/style.module.scss b/projects/js-packages/components/components/admin-page/style.module.scss index 141e917c78f0d..72aa0ab6a900e 100644 --- a/projects/js-packages/components/components/admin-page/style.module.scss +++ b/projects/js-packages/components/components/admin-page/style.module.scss @@ -1,10 +1,8 @@ -@import '@automattic/jetpack-base-styles/style'; - -.jp-admin-page { +.admin-page { margin-left: -20px; // to neutralize the padding of #wpcontent. -} + background-color: var(--jp-white); -.jp-admin-page-section { - padding: 40px 0px; - background-color: white; + @media (max-width: 782px) { + margin-left: -10px; // to neutralize the padding of #wpcontent. + } } diff --git a/projects/js-packages/components/components/admin-section/basic/index.jsx b/projects/js-packages/components/components/admin-section/basic/index.jsx index f107f45dbd9a3..03efbc2ef6dd1 100644 --- a/projects/js-packages/components/components/admin-section/basic/index.jsx +++ b/projects/js-packages/components/components/admin-section/basic/index.jsx @@ -7,7 +7,6 @@ import React from 'react'; * Internal dependencies */ import styles from './style.module.scss'; -import Container from '../../layout/container'; /** * This is the wrapper component to build sections within your admin page. @@ -17,11 +16,7 @@ import Container from '../../layout/container'; */ const AdminSection = props => { const { children } = props; - return ( -
- { children } -
- ); + return
{ children }
; }; export default AdminSection; diff --git a/projects/js-packages/components/components/admin-section/basic/style.module.scss b/projects/js-packages/components/components/admin-section/basic/style.module.scss index cbe5d2d6f1866..b31bf1adb230b 100644 --- a/projects/js-packages/components/components/admin-section/basic/style.module.scss +++ b/projects/js-packages/components/components/admin-section/basic/style.module.scss @@ -1,6 +1,3 @@ - -.jp-admin-section { - padding: 64px 0px; - background-color: white; - +.section { + background-color: var(--jp-white); } diff --git a/projects/js-packages/components/components/admin-section/hero/index.jsx b/projects/js-packages/components/components/admin-section/hero/index.jsx index e7c46fb5e5749..adc642f0e7123 100644 --- a/projects/js-packages/components/components/admin-section/hero/index.jsx +++ b/projects/js-packages/components/components/admin-section/hero/index.jsx @@ -7,7 +7,6 @@ import React from 'react'; * Internal dependencies */ import styles from './style.module.scss'; -import Container from '../../layout/container'; /** * The wrapper component for a Hero Section to be used in admin pages. @@ -17,11 +16,7 @@ import Container from '../../layout/container'; */ const AdminSectionHero = props => { const { children } = props; - return ( -
- { children } -
- ); + return
{ children }
; }; export default AdminSectionHero; diff --git a/projects/js-packages/components/components/admin-section/hero/style.module.scss b/projects/js-packages/components/components/admin-section/hero/style.module.scss index 6eb3fc404c2ee..65c3200b871a5 100644 --- a/projects/js-packages/components/components/admin-section/hero/style.module.scss +++ b/projects/js-packages/components/components/admin-section/hero/style.module.scss @@ -1,11 +1,3 @@ -@import '@automattic/jetpack-base-styles/style'; - -.jp-admin-section-hero { - padding: 48px 0px 64px 0px; +.section-hero { background: var( --jp-white-off ); - - h1, h2, h3, h4, h5, h6 { - margin-top: 0px; - line-height: 1.2; - } } diff --git a/projects/js-packages/components/components/admin-section/stories/index.jsx b/projects/js-packages/components/components/admin-section/stories/index.jsx index a5cd28c1f377f..db10c3bd11ad1 100644 --- a/projects/js-packages/components/components/admin-section/stories/index.jsx +++ b/projects/js-packages/components/components/admin-section/stories/index.jsx @@ -6,30 +6,30 @@ import AdminSection from '../basic'; import AdminSectionHero from '../hero'; import AdminPage from '../../admin-page'; import Col from '../../layout/col'; -import Row from '../../layout/row'; +import Container from '../../layout/container'; export default { - title: 'Playground/Admin Sections', + title: 'JS Packages/Components/Admin Sections', }; // Export additional stories using pre-defined values const Template = () => ( - +

Sample Hero section

This is a sample Hero section

-
+
- +

Sample Section

This is a sample section

-
+
); @@ -39,22 +39,22 @@ export const _default = Template.bind( {} ); export const onlyBasic = () => ( - +

Sample Section

This is a sample section

-
+
); export const onlyHero = () => ( - +

Sample Hero Section

This is a sample Hero section

-
+
); diff --git a/projects/js-packages/components/components/automattic-byline-logo/stories/index.jsx b/projects/js-packages/components/components/automattic-byline-logo/stories/index.jsx index 8e7af04464380..6fbb1b107bda3 100644 --- a/projects/js-packages/components/components/automattic-byline-logo/stories/index.jsx +++ b/projects/js-packages/components/components/automattic-byline-logo/stories/index.jsx @@ -11,7 +11,7 @@ import React from 'react'; import AutomatticBylineLogo from '../index.jsx'; export default { - title: 'Playground/Automattic Byline Logo', + title: 'JS Packages/Components/Automattic Byline Logo', component: AutomatticBylineLogo, }; diff --git a/projects/js-packages/components/components/decorative-card/stories/index.jsx b/projects/js-packages/components/components/decorative-card/stories/index.jsx index 6cd2d1a31310f..68f2cf9dfe4d2 100644 --- a/projects/js-packages/components/components/decorative-card/stories/index.jsx +++ b/projects/js-packages/components/components/decorative-card/stories/index.jsx @@ -5,7 +5,7 @@ import React from 'react'; import DecorativeCard from '../index.jsx'; export default { - title: 'Playground/Decorative Card', + title: 'JS Packages/Components/Decorative Card', component: DecorativeCard, }; diff --git a/projects/js-packages/components/components/jetpack-footer/stories/index.jsx b/projects/js-packages/components/components/jetpack-footer/stories/index.jsx index b94fbe4946461..7d4ec6664e2bc 100644 --- a/projects/js-packages/components/components/jetpack-footer/stories/index.jsx +++ b/projects/js-packages/components/components/jetpack-footer/stories/index.jsx @@ -10,7 +10,7 @@ import React from 'react'; import JetpackFooter from '../index.jsx'; export default { - title: 'Playground/Jetpack Footer', + title: 'JS Packages/Components/Jetpack Footer', component: JetpackFooter, }; diff --git a/projects/js-packages/components/components/jetpack-logo/stories/index.jsx b/projects/js-packages/components/components/jetpack-logo/stories/index.jsx index eb180b04e09d6..142fff399ae1b 100644 --- a/projects/js-packages/components/components/jetpack-logo/stories/index.jsx +++ b/projects/js-packages/components/components/jetpack-logo/stories/index.jsx @@ -10,7 +10,7 @@ import React from 'react'; import JetpackLogo from '../index.jsx'; export default { - title: 'Playground/Jetpack Logo', + title: 'JS Packages/Components/Jetpack Logo', component: JetpackLogo, argTypes: { logoColor: { control: 'color' }, diff --git a/projects/js-packages/components/components/layout/col/index.jsx b/projects/js-packages/components/components/layout/col/index.jsx index 07d9fccf85abb..93580d4b685c7 100644 --- a/projects/js-packages/components/components/layout/col/index.jsx +++ b/projects/js-packages/components/components/layout/col/index.jsx @@ -17,28 +17,29 @@ import styles from './style.module.scss'; * @returns {React.Component} Col component. */ const Col = props => { - const { children, sm, md, lg } = props; - const small = Number.isInteger( sm ) ? sm : 0; - const medium = Number.isInteger( md ) ? md : 0; - const large = Number.isInteger( lg ) ? lg : 0; - const minimum = [ small, medium, large ].reduce( ( prev, curr ) => - curr > 0 && curr < prev ? curr : prev - ); + const { children, className } = props; - const className = classnames( - small > 0 ? styles[ 'sm-col-span-' + small ] : styles[ 'sm-col-span-' + minimum ], - medium > 0 ? styles[ 'md-col-span-' + medium ] : styles[ 'md-col-span-' + minimum ], - large > 0 ? styles[ 'lg-col-span-' + large ] : styles[ 'lg-col-span-' + minimum ] - ); - return
{ children }
; + const sm = Math.min( 4, props.sm ?? 4 ); // max of 4, if undefined = 4 + const md = Math.min( 8, props.md ?? 8 ); // max of 8, if undefined = 8 + const lg = Math.min( 12, props.lg ?? 12 ); // max of 12, if undefined = 12 + + const colClassName = classnames( className, { + [ styles[ `col-sm-${ sm }` ] ]: Number.isInteger( sm ), + [ styles[ `col-md-${ md }` ] ]: Number.isInteger( md ), + [ styles[ `col-lg-${ lg }` ] ]: Number.isInteger( lg ), + } ); + + return
{ children }
; }; Col.proptypes = { - /** Colspan for small viewport. Needs to be an integer. Defaults to the smallest colspan informed. */ - sm: PropTypes.number, - /** Colspan for medium viewport. Needs to be an integer. Defaults to the smallest colspan informed. */ + /** Custom className to be inserted. */ + className: PropTypes.string, + /** Colspan for small viewport. Needs to be an integer. */ + sm: PropTypes.number.isRequired, + /** Colspan for medium viewport. Needs to be an integer. */ md: PropTypes.number, - /** Colspan for large viewport. Needs to be an integer. Defaults to the smallest colspan informed. */ + /** Colspan for large viewport. Needs to be an integer. */ lg: PropTypes.number, }; diff --git a/projects/js-packages/components/components/layout/col/style.module.scss b/projects/js-packages/components/components/layout/col/style.module.scss index 706ad07fc8959..558c50c0e1651 100644 --- a/projects/js-packages/components/components/layout/col/style.module.scss +++ b/projects/js-packages/components/components/layout/col/style.module.scss @@ -1,35 +1,20 @@ -@import '@automattic/jetpack-base-styles/style'; - -@for $i from 1 through 4 { - .sm-col-span-#{$i} { - grid-column-end: span #{$i}; - } -} - -@include for-phone-up { - @for $i from 1 through 8 { - .md-col-span-#{$i} { +@mixin cols($size, $columns) { + @for $i from 1 through $columns { + .col-#{$size}-#{$i} { grid-column-end: span #{$i}; } } } -@include for-tablet-up { - @for $i from 1 through 12 { - .lg-col-span-#{$i} { - grid-column-end: span #{$i}; - } - } +@media ( min-width: 0px ) { + @include cols(sm, 4) } -@include for-tablet-down { - .md-col-span-0 { - display: none; - } +@media ( min-width: 600px ) { + @include cols(md, 8) } -@include for-phone-down { - .sm-col-span-0 { - display: none; - } +@media ( min-width: 960px ) { + @include cols(lg, 12) } + diff --git a/projects/js-packages/components/components/layout/container/index.jsx b/projects/js-packages/components/components/layout/container/index.jsx index 221d769accb34..1c156f008e65e 100644 --- a/projects/js-packages/components/components/layout/container/index.jsx +++ b/projects/js-packages/components/components/layout/container/index.jsx @@ -2,6 +2,8 @@ * External dependencies */ import React from 'react'; +import classNames from 'classnames'; +import PropTypes from 'prop-types'; /** * Internal dependencies @@ -15,8 +17,43 @@ import styles from './style.module.scss'; * @returns {React.Component} Container component. */ const Container = props => { - const { children } = props; - return
{ children }
; + const { children, fluid, className } = props; + + const horizontalSpacing = `calc( var(--horizontal-spacing) * ${ props.horizontalSpacing } )`; + const horizontalGap = `calc( var(--horizontal-spacing) * ${ props.horizontalGap } )`; + + const containerStyle = { + paddingTop: horizontalSpacing, + paddingBottom: horizontalSpacing, + rowGap: horizontalGap, + }; + + const containerClassName = classNames( className, styles.container, { + [ styles.fluid ]: fluid, + } ); + + return ( +
+ { children } +
+ ); +}; + +Container.propTypes = { + /** Make container not having a max width. */ + fluid: PropTypes.bool, + /** Custom className to be inserted. */ + className: PropTypes.string, + /** Number of spacing (top / bottom), it gets mutiplied by 8px. Needs to be an integer */ + horizontalSpacing: PropTypes.number, + /** Number of gap betwen rows, it gets multipled by 8px. Needs to be an integer */ + horizontalGap: PropTypes.number, +}; + +Container.defaultProps = { + fluid: false, + horizontalGap: 1, + horizontalSpacing: 1, }; export default Container; diff --git a/projects/js-packages/components/components/layout/container/style.module.scss b/projects/js-packages/components/components/layout/container/style.module.scss index d914ad02b4df0..9c983ee6939e2 100644 --- a/projects/js-packages/components/components/layout/container/style.module.scss +++ b/projects/js-packages/components/components/layout/container/style.module.scss @@ -1,7 +1,34 @@ -.jp-container { - display: flex; - align-items: center; - flex-wrap: wrap; - max-width: 1128px; +@mixin container($columns, $width, $padding) { + @media ( min-width: #{$width} ) { + padding: 0 #{$padding}; + grid-template-columns: repeat( #{$columns}, minmax(0, 1fr) ); + } +} + +.container { + --max-container-width: 1128px; + + // vertical spacing + --vertical-gutter: 24px; + --vertical-spacing-sm: 16px; + --vertical-spacing-md: 18px; + --vertical-spacing-lg: 24px; + + // horizontal spacing + --horizontal-spacing: 8px; + + display: grid; + column-gap: var(--vertical-gutter); + max-width: var(--max-container-width); margin: 0 auto; + width: 100%; + + @include container( 4, 0px, var(--vertical-spacing-sm) ); + @include container( 8, 600px, var(--vertical-spacing-md) ); + @include container( 12, 960px, var(--vertical-spacing-lg) ); + + &.fluid { + max-width: none; + padding: unset; + } } diff --git a/projects/js-packages/components/components/layout/row/index.jsx b/projects/js-packages/components/components/layout/row/index.jsx deleted file mode 100644 index 9d8e1dec37c78..0000000000000 --- a/projects/js-packages/components/components/layout/row/index.jsx +++ /dev/null @@ -1,22 +0,0 @@ -/** - * External dependencies - */ -import React from 'react'; - -/** - * Internal dependencies - */ -import styles from './style.module.scss'; - -/** - * JP Row - * - * @param {object} props - Component properties. - * @returns {React.Component} Row component. - */ -const Row = props => { - const { children } = props; - return
{ children }
; -}; - -export default Row; diff --git a/projects/js-packages/components/components/layout/row/style.module.scss b/projects/js-packages/components/components/layout/row/style.module.scss deleted file mode 100644 index 731a5e746b80b..0000000000000 --- a/projects/js-packages/components/components/layout/row/style.module.scss +++ /dev/null @@ -1,20 +0,0 @@ -@import '@automattic/jetpack-base-styles/style'; - -.jp-row { - display: grid; - grid-gap: 24px; - grid-template-columns: repeat( 4, 1fr ); - width: 100%; - margin: 0 16px; - - @include for-phone-up { - grid-template-columns: repeat( 8, 1fr ); - margin: 0 18px; - } - - @include for-tablet-up { - grid-template-columns: repeat( 12, 1fr ); - max-width: 1128px; - margin: 0 24px; - } -} diff --git a/projects/js-packages/components/components/layout/stories/index.jsx b/projects/js-packages/components/components/layout/stories/index.jsx new file mode 100644 index 0000000000000..f01aa78f264ad --- /dev/null +++ b/projects/js-packages/components/components/layout/stories/index.jsx @@ -0,0 +1,81 @@ +/** + * External dependencies + */ +import React from 'react'; + +/** + * Internal dependencies + */ +import Container from '../container'; +import Col from '../col'; +import styles from './styles.module.scss'; + +const Layout = ( { items, fluid, horizontalGap, horizontalSpacing } ) => { + return ( + + { items.map( ( { sm, lg, md } ) => ( + + { Number.isInteger( sm ) ? `sm=${ sm } ` : '' } + { Number.isInteger( md ) ? `md=${ md } ` : '' } + { Number.isInteger( lg ) ? `lg=${ lg } ` : '' } + + ) ) } + + + Composition Example + Composition Example + + + + ); +}; + +export default { + title: 'JS Packages/Components/Layout', + component: Layout, +}; + +const Template = args => ; +export const Default = Template.bind( {} ); +Default.args = { + fluid: false, + horizontalSpacing: 10, + horizontalGap: 5, + items: [ + { + sm: 2, + md: 5, + lg: 4, + }, + { + sm: 2, + md: 3, + lg: 8, + }, + { + sm: 2, + md: 3, + lg: 8, + }, + { + sm: 2, + md: 5, + lg: 4, + }, + { + sm: 2, + md: 5, + lg: 4, + }, + { + sm: 2, + md: 3, + lg: 8, + }, + ], +}; diff --git a/projects/js-packages/components/components/layout/stories/styles.module.scss b/projects/js-packages/components/components/layout/stories/styles.module.scss new file mode 100644 index 0000000000000..5d02b35942615 --- /dev/null +++ b/projects/js-packages/components/components/layout/stories/styles.module.scss @@ -0,0 +1,10 @@ +.container { + background: var(--jp-gray-50); +} + +.col { + padding: 20px; + background: var(--jp-gray-80); + font-size: 1rem; + color: var(--jp-white-off); +} diff --git a/projects/js-packages/components/components/pricing-card/stories/index.jsx b/projects/js-packages/components/components/pricing-card/stories/index.jsx index 60a045429b2ed..da72e12e22e21 100644 --- a/projects/js-packages/components/components/pricing-card/stories/index.jsx +++ b/projects/js-packages/components/components/pricing-card/stories/index.jsx @@ -11,7 +11,7 @@ import { action } from '@storybook/addon-actions'; import PricingCard from '../index.jsx'; export default { - title: 'Playground/Pricing Card', + title: 'JS Packages/Components/Pricing Card', component: PricingCard, // TODO: Storybook Actions are not working. See https://github.com/storybookjs/storybook/issues/7215 argTypes: { diff --git a/projects/js-packages/components/components/spinner/stories/index.jsx b/projects/js-packages/components/components/spinner/stories/index.jsx index c8c0460e178a4..b344d5ff69859 100644 --- a/projects/js-packages/components/components/spinner/stories/index.jsx +++ b/projects/js-packages/components/components/spinner/stories/index.jsx @@ -10,7 +10,7 @@ import React from 'react'; import Spinner from '../index.jsx'; export default { - title: 'Playground/Spinner', + title: 'JS Packages/Components/Spinner', component: Spinner, argTypes: { color: { control: 'color' }, diff --git a/projects/js-packages/components/index.jsx b/projects/js-packages/components/index.jsx index dabd234c58852..493f150083452 100644 --- a/projects/js-packages/components/index.jsx +++ b/projects/js-packages/components/index.jsx @@ -27,6 +27,5 @@ export { default as AdminPage } from './components/admin-page'; export { default as DecorativeCard } from './components/decorative-card'; export { default as Col } from './components/layout/col'; export { default as Container } from './components/layout/container'; -export { default as Row } from './components/layout/row'; export { default as numberFormat } from './components/number-format'; export { getUserLocale, cleanLocale } from './lib/locale'; diff --git a/projects/js-packages/components/package.json b/projects/js-packages/components/package.json index 62b79e88405cb..6ab65265c017c 100644 --- a/projects/js-packages/components/package.json +++ b/projects/js-packages/components/package.json @@ -1,21 +1,21 @@ { "name": "@automattic/jetpack-components", - "version": "0.10.3-alpha", + "version": "0.10.5-alpha", "description": "Jetpack Components Package", "author": "Automattic", "license": "GPL-2.0-or-later", "dependencies": { "@automattic/format-currency": "1.0.0-alpha.0", "@wordpress/browserslist-config": "4.1.0", - "@wordpress/components": "19.1.6", - "@wordpress/date": "4.2.3", - "@wordpress/i18n": "4.2.4", + "@wordpress/components": "19.3.0", + "@wordpress/date": "4.3.0", + "@wordpress/i18n": "4.3.0", "classnames": "2.3.1", "lodash": "4.17.21", "prop-types": "^15.7.2" }, "devDependencies": { - "@automattic/jetpack-base-styles": "workspace:^0.1.7-alpha", + "@automattic/jetpack-base-styles": "workspace:^0.1.8-alpha", "@babel/core": "7.16.0", "@babel/preset-react": "7.16.0", "jetpack-js-test-runner": "workspace:*", diff --git a/projects/js-packages/config/CHANGELOG.md b/projects/js-packages/config/CHANGELOG.md index 8b79d254eeb01..f333ab0a17f2a 100644 --- a/projects/js-packages/config/CHANGELOG.md +++ b/projects/js-packages/config/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.1.3 - 2022-01-25 +### Added +- Add missing dev dependency on `nyc` for code coverage. + ## 0.1.2 - 2022-01-18 ### Changed - General: update required node version to v16.13.2 diff --git a/projects/js-packages/config/changelog/update-project-scripts-no-install b/projects/js-packages/config/changelog/update-project-scripts-no-install deleted file mode 100644 index f45fac5ea79e2..0000000000000 --- a/projects/js-packages/config/changelog/update-project-scripts-no-install +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: removed -Comment: Tooling only: Build and test scripts no longer call `composer install` or `pnpm install`. - - diff --git a/projects/js-packages/config/package.json b/projects/js-packages/config/package.json index 113de6c088884..64d70ba21edc7 100644 --- a/projects/js-packages/config/package.json +++ b/projects/js-packages/config/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@automattic/jetpack-config", - "version": "0.1.3-alpha", + "version": "0.1.3", "description": "Handles Jetpack global configuration shared across all packages", "homepage": "https://jetpack.com", "bugs": { @@ -17,7 +17,8 @@ "test": "NODE_ENV=test NODE_PATH=tests:. js-test-runner --jsdom 'glob:./!(node_modules)/**/test/*.@(jsx|js)'" }, "devDependencies": { - "jetpack-js-test-runner": "workspace:*" + "jetpack-js-test-runner": "workspace:*", + "nyc": "15.1.0" }, "engines": { "node": "^14.18.3 || ^16.13.2", diff --git a/projects/js-packages/connection/CHANGELOG.md b/projects/js-packages/connection/CHANGELOG.md index 04b75bdc7e8fa..37fc27b086495 100644 --- a/projects/js-packages/connection/CHANGELOG.md +++ b/projects/js-packages/connection/CHANGELOG.md @@ -2,6 +2,25 @@ ### This is a list detailing changes for the Jetpack RNA Connection Component releases. +## 0.15.0 - 2022-02-02 +### Added +- Added user click tracking to disconnect dialog modal. + +### Changed +- Updated package dependencies. + +### Fixed +- Fix access to display_name property in connection status card. + +## 0.14.0 - 2022-01-25 +### Changed +- Enforces the usage of initial state +- Update h3 style for connection status card + +### Fixed +- Fix Wrong spelling of propTypes in ConnectedPlugins +- Make redirectUri property not be required in ConnectionStatusCard + ## 0.13.2 - 2022-01-18 ### Changed - General: update required node version to v16.13.2 diff --git a/projects/js-packages/connection/changelog/add-fancy-eslint-ignore b/projects/js-packages/connection/changelog/add-fancy-eslint-ignore deleted file mode 100644 index afe95e481cf32..0000000000000 --- a/projects/js-packages/connection/changelog/add-fancy-eslint-ignore +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: changed -Comment: Hack eslint config to use `.gitignore` and per-dir `.eslintignore`. - - diff --git a/projects/js-packages/connection/changelog/fix-redirectUri-connection-status-card b/projects/js-packages/connection/changelog/fix-redirectUri-connection-status-card deleted file mode 100644 index 5939a4ff0c800..0000000000000 --- a/projects/js-packages/connection/changelog/fix-redirectUri-connection-status-card +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -Make redirectUri property not be required in ConnectionStatusCard diff --git a/projects/js-packages/storybook/changelog/renovate-babel-monorepo b/projects/js-packages/connection/changelog/renovate-wordpress-monorepo similarity index 100% rename from projects/js-packages/storybook/changelog/renovate-babel-monorepo rename to projects/js-packages/connection/changelog/renovate-wordpress-monorepo diff --git a/projects/js-packages/storybook/changelog/2021-09-28-16-11-44-715508 b/projects/js-packages/connection/changelog/renovate-wordpress-monorepo#2 similarity index 100% rename from projects/js-packages/storybook/changelog/2021-09-28-16-11-44-715508 rename to projects/js-packages/connection/changelog/renovate-wordpress-monorepo#2 diff --git a/projects/js-packages/connection/changelog/update-connection-enforce-initial-state b/projects/js-packages/connection/changelog/update-connection-enforce-initial-state deleted file mode 100644 index f169b8f8f7b87..0000000000000 --- a/projects/js-packages/connection/changelog/update-connection-enforce-initial-state +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: changed - -Enforces the usage of initial state diff --git a/projects/js-packages/connection/changelog/update-connection-section-my-jetpack-styles b/projects/js-packages/connection/changelog/update-connection-section-my-jetpack-styles deleted file mode 100644 index f73d2d7a6494e..0000000000000 --- a/projects/js-packages/connection/changelog/update-connection-section-my-jetpack-styles +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: changed - -Update h3 style for connection status card diff --git a/projects/js-packages/connection/changelog/update-enforce-connection-initial-state b/projects/js-packages/connection/changelog/update-enforce-connection-initial-state deleted file mode 100644 index f169b8f8f7b87..0000000000000 --- a/projects/js-packages/connection/changelog/update-enforce-connection-initial-state +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: changed - -Enforces the usage of initial state diff --git a/projects/js-packages/connection/changelog/update-project-scripts-no-install b/projects/js-packages/connection/changelog/update-project-scripts-no-install deleted file mode 100644 index f45fac5ea79e2..0000000000000 --- a/projects/js-packages/connection/changelog/update-project-scripts-no-install +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: removed -Comment: Tooling only: Build and test scripts no longer call `composer install` or `pnpm install`. - - diff --git a/projects/js-packages/connection/components/connected-plugins/index.jsx b/projects/js-packages/connection/components/connected-plugins/index.jsx index d0408266fdaad..71a9ba54af894 100644 --- a/projects/js-packages/connection/components/connected-plugins/index.jsx +++ b/projects/js-packages/connection/components/connected-plugins/index.jsx @@ -64,7 +64,7 @@ const ConnectedPlugins = props => { return null; }; -ConnectedPlugins.PropTypes = { +ConnectedPlugins.propTypes = { /** Plugins that are using the Jetpack connection. */ connectedPlugins: PropTypes.object, /** Slug of the plugin that has initiated the disconnect. */ diff --git a/projects/js-packages/connection/components/connection-status-card/index.jsx b/projects/js-packages/connection/components/connection-status-card/index.jsx index ebef16433caa8..36173d60060af 100644 --- a/projects/js-packages/connection/components/connection-status-card/index.jsx +++ b/projects/js-packages/connection/components/connection-status-card/index.jsx @@ -147,7 +147,8 @@ const ConnectionStatusCard = props => { { isUserConnected && (
  • - { __( 'Logged in as', 'jetpack' ) } { userConnectionData?.display_name } + { __( 'Logged in as', 'jetpack' ) }{ ' ' } + { userConnectionData.currentUser?.wpcomUser?.display_name }
  • ) } diff --git a/projects/js-packages/connection/components/disconnect-dialog/index.jsx b/projects/js-packages/connection/components/disconnect-dialog/index.jsx index 5ca75d6b5fbad..378f1e8520b28 100644 --- a/projects/js-packages/connection/components/disconnect-dialog/index.jsx +++ b/projects/js-packages/connection/components/disconnect-dialog/index.jsx @@ -220,6 +220,11 @@ const DisconnectDialog = props => { [ setDisconnectError, setIsDisconnecting, pluginScreenDisconnectCallback, context, _disconnect ] ); + const trackModalClick = useCallback( + target => jetpackAnalytics.tracks.recordEvent( target, defaultTracksArgs ), + [ defaultTracksArgs ] + ); + /** * Do we have the necessary data to be able to submit a survey? * Need to have the ID of the connected user and the ID of the connected site. @@ -321,6 +326,7 @@ const DisconnectDialog = props => { disconnectError={ disconnectError } context={ context } // Where is the modal showing? ( most important for when it loads on the plugins page ) disconnectingPlugin={ disconnectingPlugin } // Which plugin is initiating the disconnect. + trackModalClick={ trackModalClick } /> ); } else if ( isDisconnected && ! isProvidingFeedback && ! isFeedbackProvided ) { diff --git a/projects/js-packages/connection/components/disconnect-dialog/steps/step-disconnect.jsx b/projects/js-packages/connection/components/disconnect-dialog/steps/step-disconnect.jsx index b3f887a2f2048..f4a2ba72a353a 100644 --- a/projects/js-packages/connection/components/disconnect-dialog/steps/step-disconnect.jsx +++ b/projects/js-packages/connection/components/disconnect-dialog/steps/step-disconnect.jsx @@ -1,7 +1,7 @@ /** * External Dependencies */ -import React from 'react'; +import React, { useCallback } from 'react'; /** * Internal Dependencies @@ -30,8 +30,29 @@ const StepDisconnect = props => { disconnectingPlugin, closeModal, context, + trackModalClick, } = props; + const trackLearnClick = useCallback( + () => trackModalClick( 'jetpack_disconnect_dialog_click_learn_about' ), + [ trackModalClick ] + ); + const trackSupportClick = useCallback( + () => trackModalClick( 'jetpack_disconnect_dialog_click_support' ), + [ trackModalClick ] + ); + const handleStayConnectedClick = useCallback( () => { + trackModalClick( 'jetpack_disconnect_dialog_click_stay_connected' ); + closeModal(); + }, [ trackModalClick, closeModal ] ); + const handleDisconnectClick = useCallback( + e => { + trackModalClick( 'jetpack_disconnect_dialog_click_disconnect' ); + onDisconnect( e ); + }, + [ trackModalClick, onDisconnect ] + ); + /** * Render the disconnect button, allows for some variance based on context. * @@ -50,7 +71,7 @@ const StepDisconnect = props => { ); case PRODUCT_STATUSES.ERROR: return ( - ); case PRODUCT_STATUSES.INACTIVE: return ( - ); @@ -89,24 +99,71 @@ const renderActionButton = ( { }; const ProductCard = props => { - const { name, admin, description, icon, status, onDeactivate } = props; + const { + name, + admin, + description, + icon, + status, + onActivate, + onAdd, + onDeactivate, + isFetching, + } = props; const isActive = status === PRODUCT_STATUSES.ACTIVE; const isError = status === PRODUCT_STATUSES.ERROR; const isInactive = status === PRODUCT_STATUSES.INACTIVE; - const isAbsent = status === PRODUCT_STATUSES.ABSENT; + const isAbsent = status === PRODUCT_STATUSES.ABSENT || status === PRODUCT_STATUSES.NEEDS_PURCHASE; + const isPurchaseRequired = status === PRODUCT_STATUSES.NEEDS_PURCHASE; const flagLabel = PRODUCT_STATUSES_LABELS[ status ]; const canDeactivate = ( isActive || isError ) && admin; const containerClassName = classNames( styles.container, { - [ styles.absent ]: isAbsent, + [ styles.plugin_absent ]: isAbsent, + [ styles[ 'is-purchase-required' ] ]: isPurchaseRequired, } ); const statusClassName = classNames( styles.status, { [ styles.active ]: isActive, [ styles.inactive ]: isInactive, [ styles.error ]: isError, + [ styles[ 'is-fetching' ] ]: isFetching, } ); + const { + tracks: { recordEvent }, + } = useAnalytics(); + + /** + * Calls the passed function onDeactivate after firing Tracks event + */ + const deactivateHandler = useCallback( () => { + recordEvent( 'jetpack_myjetpack_product_card_deactivate_click', { + product: name, + } ); + onDeactivate(); + }, [ name, onDeactivate, recordEvent ] ); + + /** + * Calls the passed function onActivate after firing Tracks event + */ + const activateHandler = useCallback( () => { + recordEvent( 'jetpack_myjetpack_product_card_activate_click', { + product: name, + } ); + onActivate(); + }, [ name, onActivate, recordEvent ] ); + + /** + * Calls the passed function onAdd after firing Tracks event + */ + const addHandler = useCallback( () => { + recordEvent( 'jetpack_myjetpack_product_card_add_click', { + product: name, + } ); + onAdd(); + }, [ name, onAdd, recordEvent ] ); + return (
    @@ -116,24 +173,25 @@ const ProductCard = props => {

    { description }

    { canDeactivate ? ( - - { renderActionButton( props ) } + + { renderActionButton( { ...props, onActivate: activateHandler } ) } ) : ( - renderActionButton( props ) + renderActionButton( { ...props, onActivate: activateHandler, onAdd: addHandler } ) ) } { ! isAbsent &&
    { flagLabel }
    }
    @@ -146,6 +204,7 @@ ProductCard.propTypes = { description: PropTypes.string.isRequired, icon: PropTypes.element, admin: PropTypes.bool.isRequired, + isFetching: PropTypes.bool, onDeactivate: PropTypes.func, onManage: PropTypes.func, onFixConnection: PropTypes.func, @@ -157,11 +216,13 @@ ProductCard.propTypes = { PRODUCT_STATUSES.INACTIVE, PRODUCT_STATUSES.ERROR, PRODUCT_STATUSES.ABSENT, + PRODUCT_STATUSES.NEEDS_PURCHASE, ] ).isRequired, }; ProductCard.defaultProps = { icon: null, + isFetching: false, onDeactivate: () => {}, onManage: () => {}, onFixConnection: () => {}, diff --git a/projects/packages/my-jetpack/_inc/components/product-card/stories/index.jsx b/projects/packages/my-jetpack/_inc/components/product-card/stories/index.jsx index b840c1689db30..2b8d3ab5a8031 100644 --- a/projects/packages/my-jetpack/_inc/components/product-card/stories/index.jsx +++ b/projects/packages/my-jetpack/_inc/components/product-card/stories/index.jsx @@ -1,4 +1,5 @@ /* eslint-disable react/react-in-jsx-scope */ + /** * External dependencies */ @@ -8,9 +9,15 @@ import React from 'react'; * Internal dependencies */ import ProductCard, { PRODUCT_STATUSES } from '../index.jsx'; +import { initStore } from '../../../state/store'; + +// Set myJetpackRest global var. +window.myJetpackRest = {}; + +initStore(); export default { - title: 'My Jetpack/Product Card', + title: 'Packages/My Jetpack/Product Card', component: ProductCard, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/projects/packages/my-jetpack/_inc/components/product-card/style.module.scss b/projects/packages/my-jetpack/_inc/components/product-card/style.module.scss index b70e31b52b9d1..a590af4ab23c2 100644 --- a/projects/packages/my-jetpack/_inc/components/product-card/style.module.scss +++ b/projects/packages/my-jetpack/_inc/components/product-card/style.module.scss @@ -9,11 +9,12 @@ --product-card-description-font-size: 14px; --product-card-actions-font-size: 12px; --product-card-margin-base: 4px; + --product-card-actions-size: 36px; --status-size: 8px; --status-active: #008710; --status-inactive: #646970; --status-error: #B32D2E; - --status-absent: #C3C4C7; + --status-plugin_absent: #C3C4C7; padding: 24px; background: var( --jp-white ); @@ -24,10 +25,11 @@ flex-direction: column; justify-content: space-between; - &.absent { + &.is-purchase-required, + &.plugin_absent { background: none; box-shadow: none; - box-shadow: 0 0 0 1px var( --status-absent ) inset; + box-shadow: 0 0 0 1px var( --status-plugin_absent ) inset; } } @@ -51,15 +53,23 @@ align-items: center; justify-content: space-between; width: 100%; - height: 36px; + min-height: var(--product-card-actions-size); margin-top: calc(var(--product-card-margin-base) * 4); // 16px font-size: var(--product-card-actions-font-size); font-weight: 600; + flex-wrap: wrap; +} + +.group { + display: flex; + height: var(--product-card-actions-size); } .status { margin-left: var(--product-card-margin-base); white-space: nowrap; + height: var(--product-card-actions-size); + line-height: var(--product-card-actions-size); &:before { content: ""; @@ -70,7 +80,7 @@ border-radius: 50%; } - // in absent case, there's not status flag + // in plugin absent case, there's not status flag $statuses: active, inactive, error; @each $status in $statuses { @@ -83,5 +93,23 @@ } } } + + &.is-fetching { + &:before { + animation: blink-animation 0.5s linear infinite; + } + } +} + +@keyframes blink-animation{ + 0%{ + opacity: 0; + } + 50%{ + opacity: 0.5; + } + 100%{ + opacity: 0; + } } diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/anti-spam-card.jsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/anti-spam-card.jsx index 5384dd4398f1f..8da3fcbc77783 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/anti-spam-card.jsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/anti-spam-card.jsx @@ -7,9 +7,10 @@ import PropTypes from 'prop-types'; /** * Internal dependencies */ -import ProductCard, { PRODUCT_STATUSES } from '../product-card'; +import ProductCard from '../product-card'; +import { useProduct } from '../../hooks/use-product'; -const AntiSpamIcon = () => ( +export const AntiSpamIcon = () => ( ( ); const AntiSpamCard = ( { admin } ) => { - // @todo: implement action handlers + const { status, activate, deactivate, detail, isFetching } = useProduct( 'anti-spam' ); + const { name, description } = detail; + return ( } admin={ admin } + isFetching={ isFetching } + onDeactivate={ deactivate } + onActivate={ activate } /> ); }; diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/backup-card.jsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/backup-card.jsx index e2e110085d450..2f78bdbb726ed 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/backup-card.jsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/backup-card.jsx @@ -10,7 +10,7 @@ import PropTypes from 'prop-types'; import ProductCard from '../product-card'; import { useProduct } from '../../hooks/use-product'; -const BackupIcon = () => ( +export const BackupIcon = () => ( ( ); const BackupCard = ( { admin } ) => { - const { status, activate, deactivate, detail } = useProduct( 'backup' ); + const { status, activate, deactivate, detail, isFetching } = useProduct( 'backup' ); const { name, description } = detail; return ( @@ -31,6 +31,7 @@ const BackupCard = ( { admin } ) => { description={ description } status={ status } icon={ } + isFetching={ isFetching } admin={ admin } onDeactivate={ deactivate } onActivate={ activate } diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/boost-card.jsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/boost-card.jsx index 149b5ac4bf97c..ae84a80f474e3 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/boost-card.jsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/boost-card.jsx @@ -1,29 +1,42 @@ /** * External dependencies */ -import React from 'react'; +import React, { useCallback } from 'react'; import PropTypes from 'prop-types'; +import { useNavigate } from 'react-router-dom'; /** * Internal dependencies */ -import ProductCard, { PRODUCT_STATUSES } from '../product-card'; +import ProductCard from '../product-card'; +import { useProduct } from '../../hooks/use-product'; -const BoostIcon = () => ( +export const BoostIcon = () => ( ); const BoostCard = ( { admin } ) => { - // @todo: implement action handlers + const { status, activate, deactivate, detail, isFetching } = useProduct( 'boost' ); + const { name, description } = detail; + const navigate = useNavigate(); + + const onAddHandler = useCallback( () => { + navigate( '/add-boost' ); + }, [ navigate ] ); + return ( } admin={ admin } + isFetching={ isFetching } + onDeactivate={ deactivate } + onActivate={ activate } + onAdd={ onAddHandler } /> ); }; diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/crm-card.jsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/crm-card.jsx index 84011e5362ad3..7bb1055a0ce8a 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/crm-card.jsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/crm-card.jsx @@ -7,9 +7,10 @@ import PropTypes from 'prop-types'; /** * Internal dependencies */ -import ProductCard, { PRODUCT_STATUSES } from '../product-card'; +import ProductCard from '../product-card'; +import { useProduct } from '../../hooks/use-product'; -const CrmIcon = () => ( +export const CrmIcon = () => ( ( ); const CrmCard = ( { admin } ) => { - // @todo: implement action handlers + const { status, activate, deactivate, detail, isFetching } = useProduct( 'crm' ); + const { name, description } = detail; + return ( } + isFetching={ isFetching } admin={ admin } + onDeactivate={ deactivate } + onActivate={ activate } /> ); }; diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/extras-card.jsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/extras-card.jsx index ea738502bb7de..fc499d46a8732 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/extras-card.jsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/extras-card.jsx @@ -7,9 +7,10 @@ import PropTypes from 'prop-types'; /** * Internal dependencies */ -import ProductCard, { PRODUCT_STATUSES } from '../product-card'; +import ProductCard from '../product-card'; +import { useProduct } from '../../hooks/use-product'; -const ExtrasIcon = () => ( +export const ExtrasIcon = () => ( ( ); const ExtrasCard = ( { admin } ) => { - // @todo: implement action handlers + const { status, activate, deactivate, detail, isFetching } = useProduct( 'extras' ); + const { name, description } = detail; + return ( } admin={ admin } + isFetching={ isFetching } + onDeactivate={ deactivate } + onActivate={ activate } /> ); }; diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.jsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.jsx index e94f4b3f51749..2f70eed8d4645 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.jsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.jsx @@ -2,7 +2,7 @@ * External dependencies */ import React from 'react'; -import { Container, Row, Col } from '@automattic/jetpack-components'; +import { Container, Col } from '@automattic/jetpack-components'; /** * Internal dependencies @@ -23,33 +23,31 @@ import ExtrasCard from './extras-card'; */ const ProductCardsSection = () => { return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + ); }; diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/scan-card.jsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/scan-card.jsx index 6ddc3b7bd8ce6..e96f97fd41c43 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/scan-card.jsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/scan-card.jsx @@ -7,9 +7,10 @@ import PropTypes from 'prop-types'; /** * Internal dependencies */ -import ProductCard, { PRODUCT_STATUSES } from '../product-card'; +import ProductCard from '../product-card'; +import { useProduct } from '../../hooks/use-product'; -const ScanIcon = () => ( +export const ScanIcon = () => ( ( ); const ScanCard = ( { admin } ) => { - // @todo: implement action handlers + const { status, activate, deactivate, detail, isFetching } = useProduct( 'scan' ); + const { name, description } = detail; + return ( } admin={ admin } + isFetching={ isFetching } + onDeactivate={ deactivate } + onActivate={ activate } /> ); }; diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/search-card.jsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/search-card.jsx index afecdb5daceaa..ac424d1147cf4 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/search-card.jsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/search-card.jsx @@ -1,15 +1,17 @@ /** * External dependencies */ -import React from 'react'; +import React, { useCallback } from 'react'; import PropTypes from 'prop-types'; +import { useNavigate } from 'react-router-dom'; /** * Internal dependencies */ -import ProductCard, { PRODUCT_STATUSES } from '../product-card'; +import ProductCard from '../product-card'; +import { useProduct } from '../../hooks/use-product'; -const SearchIcon = () => ( +export const SearchIcon = () => ( @@ -17,14 +19,23 @@ const SearchIcon = () => ( ); const SearchCard = ( { admin } ) => { - // @todo: implement action handlers + const { status, activate, deactivate, detail, isFetching } = useProduct( 'search' ); + const { name, description } = detail; + + const navigate = useNavigate(); + const onAddHandler = useCallback( () => navigate( '/add-search' ), [ navigate ] ); + return ( } admin={ admin } + isFetching={ isFetching } + onDeactivate={ deactivate } + onActivate={ activate } + onAdd={ onAddHandler } /> ); }; diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/stories/index.jsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/stories/index.jsx index 1fe6bd32bdaf3..d95bcf2b5fa2c 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/stories/index.jsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/stories/index.jsx @@ -9,7 +9,7 @@ import React from 'react'; import ProductCardsSection from '../index.jsx'; export default { - title: 'My Jetpack/Product Cards Section', + title: 'Packages/My Jetpack/Product Cards Section', component: ProductCardsSection, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/videopress-card.jsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/videopress-card.jsx index 7e23886d86e2b..d125b7db73e25 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/videopress-card.jsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/videopress-card.jsx @@ -7,9 +7,10 @@ import PropTypes from 'prop-types'; /** * Internal dependencies */ -import ProductCard, { PRODUCT_STATUSES } from '../product-card'; +import ProductCard from '../product-card'; +import { useProduct } from '../../hooks/use-product'; -const VideopressIcon = () => ( +export const VideopressIcon = () => ( ( ); const VideopressCard = ( { admin } ) => { - // @todo: implement action handlers + const { status, activate, deactivate, detail, isFetching } = useProduct( 'videopress' ); + const { name, description } = detail; + return ( } admin={ admin } + isFetching={ isFetching } + onDeactivate={ deactivate } + onActivate={ activate } /> ); }; diff --git a/projects/packages/my-jetpack/_inc/components/product-detail-card/index.jsx b/projects/packages/my-jetpack/_inc/components/product-detail-card/index.jsx new file mode 100644 index 0000000000000..994acfc46bdb6 --- /dev/null +++ b/projects/packages/my-jetpack/_inc/components/product-detail-card/index.jsx @@ -0,0 +1,140 @@ +/** + * External dependencies + */ +import React from 'react'; +import classnames from 'classnames'; +import { Button } from '@wordpress/components'; +import { Icon, check } from '@wordpress/icons'; +import { getCurrencyObject } from '@automattic/format-currency'; +import { __, sprintf } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { useProduct } from '../../hooks/use-product'; +import { BackupIcon } from '../product-cards-section/backup-card'; +import styles from './style.module.scss'; +import { BoostIcon } from '../product-cards-section/boost-card'; + +/** + * Simple react component to render the product icon, + * depending on the product slug. + * + * @param {string} slug - The product slug. + * @returns {object} ProductDetailCard react component. + */ +function ProductIcon( { slug } ) { + switch ( slug ) { + case 'backup': + return ; + + case 'boost': + return ; + default: + return null; + } +} + +/** + * React component to render the price. + * + * @param {object} props - Component props. + * @param {string} props.value - Product price + * @param {string} props.currency - Product current code + * @param {string} props.isOld - True when the product price is old + * @returns {object} Price react component. + */ +function Price( { value, currency, isOld } ) { + const priceObject = getCurrencyObject( value, currency ); + + const classNames = classnames( styles.price, { + [ styles[ 'is-old' ] ]: isOld, + } ); + + return ( +
    + { priceObject.symbol } + { priceObject.integer } + { priceObject.fraction } +
    + ); +} + +/** + * Product Detail component. + * + * @param {object} props - Component props. + * @param {string} props.slug - Product slug + * @param {Function} props.trackButtonClick - Function to call for tracking clicks on Call To Action button + * @returns {object} ProductDetailCard react component. + */ +const ProductDetail = ( { slug, trackButtonClick } ) => { + const { detail } = useProduct( slug ); + const { title, longDescription, features, pricingForUi = {} } = detail; + const { isFree, fullPrice, currencyCode } = pricingForUi; + + return ( +
    + + +

    { title }

    +

    { longDescription }

    +
      + { features.map( ( feature, id ) => ( +
    • + + { feature } +
    • + ) ) } +
    + + { ! isFree && ( +
    + + +
    + { __( '/month, paid yearly', 'jetpack-my-jetpack' ) } +
    +
    + ) } + + { isFree && ( +

    { __( 'Free', 'jetpack-my-jetpack' ) }

    + ) } + + +
    + ); +}; + +ProductDetail.defaultProps = { + trackButtonClick: () => {}, +}; + +export { ProductDetail }; + +/** + * ProductDetailCard component. + * + * @param {object} props - Component props. + * @param {string} props.slug - Product slug + * @returns {object} ProductDetailCard react component. + */ +export default function ProductDetailCard( { slug } ) { + return ( +
    + +
    + ); +} diff --git a/projects/packages/my-jetpack/_inc/components/product-detail-card/stories/index.jsx b/projects/packages/my-jetpack/_inc/components/product-detail-card/stories/index.jsx new file mode 100644 index 0000000000000..622933713c258 --- /dev/null +++ b/projects/packages/my-jetpack/_inc/components/product-detail-card/stories/index.jsx @@ -0,0 +1,74 @@ +/* eslint-disable react/react-in-jsx-scope */ +/** + * External dependencies + */ +import React from 'react'; +import withMock from 'storybook-addon-mock'; + +/** + * Internal dependencies + */ +import ProductDetailCard, { ProductDetail } from '../index.jsx'; +import { backupProductData, boostProductData } from './mock-data.js'; + +export default { + title: 'Packages/My Jetpack/Product Detail Card', + component: ProductDetailCard, + decorators: [ withMock ], +}; + +const DefaultArgs = {}; + +const DefaultProductDetailCard = args => ; + +const mapResponse = { + backup: backupProductData, + boost: boostProductData, +}; + +/** + * Helper function that returns the story mock data. + * + * @param {string} product - Product slug + * @returns {Array} Story mock data + */ +function getMockData( product ) { + return [ + { + url: `my-jetpack/v1/site/products/${ product }?_locale=user`, + method: 'GET', + status: 200, + response: mapResponse[ product ], + }, + ]; +} + +export const _default = DefaultProductDetailCard.bind( {} ); +_default.parameters = { + mockData: getMockData( 'backup' ), +}; +_default.args = DefaultArgs; + +const BackupTemplate = args => ; +export const JetpackBackup = BackupTemplate.bind( {} ); +JetpackBackup.parameters = { + mockData: getMockData( 'backup' ), +}; + +const BoostTemplate = args => ; +export const BoostBackup = BoostTemplate.bind( {} ); +BoostBackup.parameters = { + mockData: getMockData( 'boost' ), +}; + +const BackupCardTemplate = args => ; +export const JetpackBackupCard = BackupCardTemplate.bind( {} ); +JetpackBackupCard.parameters = { + mockData: getMockData( 'backup' ), +}; + +const BoostCardTemplate = args => ; +export const BoostBackupCard = BoostCardTemplate.bind( {} ); +BoostBackupCard.parameters = { + mockData: getMockData( 'boost' ), +}; diff --git a/projects/packages/my-jetpack/_inc/components/product-detail-card/stories/mock-data.js b/projects/packages/my-jetpack/_inc/components/product-detail-card/stories/mock-data.js new file mode 100644 index 0000000000000..906d34440a8d2 --- /dev/null +++ b/projects/packages/my-jetpack/_inc/components/product-detail-card/stories/mock-data.js @@ -0,0 +1,40 @@ +export const backupProductData = { + slug: 'backup', + name: 'Backup', + title: 'Jepack Backup', + description: 'Save every change', + long_description: + 'Real-time backups save every change and one-click restores get you back online quickly.', + status: 'active', + features: [ + 'Real-time cloud backups', + '10GB of backup storage', + '30-day archive & activity log', + 'One-click restores', + ], + pricingForUi: { + available: true, + currencyCode: 'EUR', + fullPrice: '9', + promotionPercentage: '50', + }, +}; + +export const boostProductData = { + slug: 'boost', + name: 'Boost', + title: 'Jepack Boost', + description: 'Instant speed and SEO', + long_description: + 'Jetpack Boost gives your site the same performance advantages as the world’s leading websites, no developer required.', + status: 'inactive', + features: [ + 'Check your site performance', + 'Enable improvements in one click', + 'Standalone free plugin for those focused on speed', + ], + pricingForUi: { + available: true, + is_free: true, + }, +}; diff --git a/projects/packages/my-jetpack/_inc/components/product-detail-card/style.module.scss b/projects/packages/my-jetpack/_inc/components/product-detail-card/style.module.scss new file mode 100644 index 0000000000000..b8bc78facfacb --- /dev/null +++ b/projects/packages/my-jetpack/_inc/components/product-detail-card/style.module.scss @@ -0,0 +1,152 @@ +.card { + // Card main wrapper + --product-card-bg-color: white; + --product-card-border-color: #d5d5d5; + --product-card-shadow: rgb(0 0 0 / 3%); + --product-card-border-radius: 4px; + + background-color: var(--product-card-bg-color); + border: 1px solid var(--product-card-border-color); + border-radius: var(--product-card-border-radius); + box-shadow: 0 2px 6px var(--product-card-shadow), 0 1px 2px var(--product-card-shadow); + max-width: 384px; +} + +.container { + // @todo find a better way to change link color + // since this could affect more places + --wp-admin-theme-color: var(--jp-black); + + // all css variables used down in product-detail-card + + // Colors + --jp-green-primary: #069e08; + --jp-green-secondary: #2fb41f; + --jp-text-color: ###; + + // Text + --product-card-description-line-height: 1.5; + --product-card-description-font-size: 16px; + --product-card-price-font-size: 4rem; + + display: flex; + flex-direction: column; + justify-content: space-between; + max-width: 600px; + padding: 60px 40px; + + h3 { + font-size: var(--font-title-large); + font-weight: 700; + margin-top: 48px; + line-height: 1.1; + color: var( --jp-black ); + margin: 10px 0; + } + + .checkout-button { + margin-top: 20px; + white-space: pre-line; + height: auto; + line-height: 26px; + } + + // Product Icon + & > svg { + height: 30px; + line-height: 30px; + } +} + +.name { + line-height: var(--product-card-description-line-height); + font-size: var(--product-card-description-font-size); + margin: 0 0 22px; +} + +.features { + margin: 0 0 30px; + padding: 0; + li { + list-style: none; + display: flex; + align-items: center; + margin-bottom: 8px; + font-size: 14px; + line-height: 1.4; + } + + svg { + fill: var(--jp-green-primary); + } +} + +.price-container { + display: flex; + flex-wrap: wrap; + flex-direction: row; + align-items: flex-end; + margin-top: auto; + color: var(--jp-text-color); +} + +.price { + font-size: var(--product-card-price-font-size); + display: flex; + margin: 0; + position: relative; + + &:first-child { + margin-right: 10px; + } + + .price-symbol { + padding-right: 1px; + font-size: 0.5em; + line-height: 1.4; + } + + .price-number { + font-size: inherit; + font-weight: 700; + line-height: 1; + } + + .price-fraction { + padding-left: 1px; + font-size: 0.35em; + font-weight: 700; + line-height: 1.7; + } + + &.is-old { + color: #a7aaad; + &:after { + content: " "; + display: block; + width: 100%; + height: 3px; + background: #c9356e; + border-radius: 5px; + position: absolute; + top: 50%; + margin-top: -2px; + pointer-events: none; + } + } +} + +.price-description { + color: #787c82; + letter-spacing: 0.2px; + flex-grow: 2; +} + +.checkout-button { + align-self: flex-start; + font-size: 16px; + padding: 8px 60px; + text-align: center;; + width: 100%; + display: inline-block; +} diff --git a/projects/packages/my-jetpack/_inc/components/product-interstitial/boost.png b/projects/packages/my-jetpack/_inc/components/product-interstitial/boost.png new file mode 100644 index 0000000000000..65a8aedd98f67 Binary files /dev/null and b/projects/packages/my-jetpack/_inc/components/product-interstitial/boost.png differ diff --git a/projects/packages/my-jetpack/_inc/components/product-interstitial/index.jsx b/projects/packages/my-jetpack/_inc/components/product-interstitial/index.jsx new file mode 100644 index 0000000000000..ad06224fbaa57 --- /dev/null +++ b/projects/packages/my-jetpack/_inc/components/product-interstitial/index.jsx @@ -0,0 +1,88 @@ +/** + * External dependencies + */ +import React, { useCallback, useEffect } from 'react'; +import { Container, Col } from '@automattic/jetpack-components'; + +/** + * Internal dependencies + */ +import { ProductDetail } from '../product-detail-card'; +import styles from './style.module.scss'; +import useAnalytics from '../../hooks/use-analytics'; +import boostImage from './boost.png'; +import searchImage from './search.png'; + +/** + * Product Interstitial component. + * + * @param {object} props - Component props. + * @param {string} props.slug - Product slug + * @param {object} props.children - Product additional content + * @returns {object} ProductInterstitial react component. + */ +export default function ProductInterstitial( { slug, children = null } ) { + const { + tracks: { recordEvent }, + } = useAnalytics(); + + useEffect( () => { + recordEvent( 'jetpack_myjetpack_product_interstitial_view', { product: slug } ); + }, [ recordEvent, slug ] ); + + const trackProductClick = useCallback( () => { + recordEvent( 'jetpack_myjetpack_product_interstitial_add_link_click', { product: slug } ); + }, [ recordEvent, slug ] ); + + return ( +
    + + + + + + { children } + + +
    + ); +} + +/** + * BackupInterstitial component + * + * @returns {object} BackupInterstitial react component. + */ +export function BackupInterstitial() { + return ( + +

    @todo Popular upgrade here

    +
    + ); +} + +/** + * SearchInterstitial component + * + * @returns {object} BoostInterstitial react component. + */ +export function BoostInterstitial() { + return ( + + Boost + + ); +} + +/** + * SearchInterstitial component + * + * @returns {object} SearchInterstitial react component. + */ +export function SearchInterstitial() { + return ( + + Search + + ); +} diff --git a/projects/packages/my-jetpack/_inc/components/product-interstitial/search.png b/projects/packages/my-jetpack/_inc/components/product-interstitial/search.png new file mode 100644 index 0000000000000..4ef9cf13a1091 Binary files /dev/null and b/projects/packages/my-jetpack/_inc/components/product-interstitial/search.png differ diff --git a/projects/packages/my-jetpack/_inc/components/product-interstitial/stories/index.jsx b/projects/packages/my-jetpack/_inc/components/product-interstitial/stories/index.jsx new file mode 100644 index 0000000000000..c3a5c7f9a707f --- /dev/null +++ b/projects/packages/my-jetpack/_inc/components/product-interstitial/stories/index.jsx @@ -0,0 +1,41 @@ +/* eslint-disable react/react-in-jsx-scope */ +/** + * External dependencies + */ +import React from 'react'; +import withMock from 'storybook-addon-mock'; + +/** + * Internal dependencies + */ +import ProductInterstitial, { + BackupInterstitial, + BoostInterstitial, + SearchInterstitial, +} from '../index.jsx'; + +export default { + title: 'Packages/My Jetpack/Product Interstitial', + component: ProductInterstitial, + decorators: [ withMock ], +}; + +const DefaultArgs = {}; + +const DefaultBackupDetailCard = args => ; + +export const _default = DefaultBackupDetailCard.bind( {} ); +_default.parameters = {}; +_default.args = DefaultArgs; + +const BackupTemplate = args => ; +export const JetpackBackup = BackupTemplate.bind( {} ); +JetpackBackup.parameters = {}; + +const BoostTemplate = args => ; +export const JetpackBoost = BoostTemplate.bind( {} ); +JetpackBoost.parameters = {}; + +const SearchTemplate = args => ; +export const JetpackSearch = SearchTemplate.bind( {} ); +JetpackSearch.parameters = {}; diff --git a/projects/packages/my-jetpack/_inc/components/product-interstitial/style.module.scss b/projects/packages/my-jetpack/_inc/components/product-interstitial/style.module.scss new file mode 100644 index 0000000000000..6cd00d4ba1a03 --- /dev/null +++ b/projects/packages/my-jetpack/_inc/components/product-interstitial/style.module.scss @@ -0,0 +1,43 @@ +.container { + // Card main wrapper + --product-card-bg-color: white; + --product-card-border-color: #d5d5d5; + --product-card-shadow: rgb(0 0 0 / 3%); + --product-card-border-radius: 4px; + + background-color: var(--product-card-bg-color); + border: 1px solid var(--product-card-border-color); + border-radius: var(--product-card-border-radius); + box-shadow: 0 2px 6px var(--product-card-shadow), 0 1px 2px var(--product-card-shadow); +} + +.imageContainer { + display: flex; + align-items: center; + + img { + object-fit: cover; + width: 100%; + } +} + +// Wrapper + +@media (max-width: 768px) { + .wrapper { + margin-right: 12px; + } +} + +@mixin container($width, $margin-right) { + @media ( min-width: #{$width} ) { + margin-right: $margin-right + } +} + +.wrapper { + --margin-right-compensation-sm: 10px; + --margin-right-compensation-md: 20px; + @include container( 0px, var(--margin-right-compensation-sm) ); + @include container( 782px, var(--margin-right-compensation-md) ); +} \ No newline at end of file diff --git a/projects/packages/my-jetpack/_inc/hooks/use-analytics/index.js b/projects/packages/my-jetpack/_inc/hooks/use-analytics/index.js index 7aa0dfec949d8..e5013017ef2ad 100644 --- a/projects/packages/my-jetpack/_inc/hooks/use-analytics/index.js +++ b/projects/packages/my-jetpack/_inc/hooks/use-analytics/index.js @@ -1,29 +1,24 @@ -/* global myJetpackInitialState */ /** * External dependencies */ import { useEffect } from 'react'; import jetpackAnalytics from '@automattic/jetpack-analytics'; -import { useConnection } from '@automattic/jetpack-connection'; +import useMyJetpackConnection from '../use-my-jetpack-connection'; const useAnalytics = () => { - const { apiRoot, apiNonce } = myJetpackInitialState; + const { isUserConnected, userConnectionData = {} } = useMyJetpackConnection(); + const { login, ID } = userConnectionData.currentUser?.wpcomUser || {}; - const { isUserConnected, userConnectionData } = useConnection( { - apiRoot, - apiNonce, - } ); - - const { login, ID } = userConnectionData.currentUser.wpcomUser; /** * Initialize tracks with user data. * Should run when we have a connected user. */ useEffect( () => { - if ( isUserConnected ) { + if ( isUserConnected && ID && login ) { jetpackAnalytics.initialize( ID, login ); } - } ); + }, [ ID, isUserConnected, login ] ); + const { clearedIdentity, ga, diff --git a/projects/packages/my-jetpack/_inc/hooks/use-my-jetpack-connection/index.js b/projects/packages/my-jetpack/_inc/hooks/use-my-jetpack-connection/index.js new file mode 100644 index 0000000000000..f04ad8d947b17 --- /dev/null +++ b/projects/packages/my-jetpack/_inc/hooks/use-my-jetpack-connection/index.js @@ -0,0 +1,56 @@ +/* global myJetpackInitialState */ +/* global myJetpackRest */ +/** + * WordPress dependencies + */ +import { useEffect } from 'react'; +import { useConnection } from '@automattic/jetpack-connection'; + +/** + * React custom hook to get the site purchases data. + * + * @param {object} options - Options to pass to the hook. + * @param {boolean} options.reditect - Perform a redirect when no connection is found. + * @returns {object} site purchases data + */ +export default function useMyJetpackConnection( options = { redirect: false } ) { + const { apiRoot, apiNonce } = myJetpackRest; + const { topJetpackMenuItemUrl } = myJetpackInitialState; + const { redirect } = options; + const connectionData = useConnection( { apiRoot, apiNonce } ); + + // Alias: https://github.com/Automattic/jetpack/blob/master/projects/packages/connection/src/class-rest-connector.php/#L315 + const isSiteConnected = connectionData.isRegistered; + + /* + * When the site is not connect, + * and the `redirect` option is set to `true`, + * redirect to the Jetpack dashboard. + */ + useEffect( () => { + // Bail early when topJetpackMenuItemUrl is not defined. + if ( ! topJetpackMenuItemUrl ) { + return; + } + + // Bail early when redirect mode is disabled. + if ( ! redirect ) { + return; + } + + // When site is connected, bail early. + if ( isSiteConnected ) { + return; + } + + window.location = topJetpackMenuItemUrl; + }, [ isSiteConnected, redirect, topJetpackMenuItemUrl ] ); + + return { + apiNonce, + apiRoot, + ...connectionData, + isSiteConnected, + redirectUrl: topJetpackMenuItemUrl, + }; +} diff --git a/projects/packages/my-jetpack/_inc/hooks/use-notice/Readme.md b/projects/packages/my-jetpack/_inc/hooks/use-notice/Readme.md new file mode 100644 index 0000000000000..57f1a7c9f6b4a --- /dev/null +++ b/projects/packages/my-jetpack/_inc/hooks/use-notice/Readme.md @@ -0,0 +1,20 @@ +# useNotice custom hooks + +## useNoticeWatcher + +## useGlobalNotice + +```es6 +import { useGlobalNotice } from './hooks/use-notice'; + +function PlansSection() { + const global = useGlobalNotice(); + if ( ! global ) { + return null; + } + + return ( + { global.message }; + ) +} +``` diff --git a/projects/packages/my-jetpack/_inc/hooks/use-notice/index.js b/projects/packages/my-jetpack/_inc/hooks/use-notice/index.js new file mode 100644 index 0000000000000..c6387b7ffdfd4 --- /dev/null +++ b/projects/packages/my-jetpack/_inc/hooks/use-notice/index.js @@ -0,0 +1,62 @@ +/** + * WordPress dependencies + */ +import { useEffect } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { useNavigate } from 'react-router-dom'; + +/** + * Internal dependencies + */ +import { STORE_ID } from '../../state/store'; +import useMyJetpackConnection from '../use-my-jetpack-connection'; + +/** + * React custom hook to get global notices. + * + * @returns {object} Global notices data + */ +export function useGlobalNotice() { + const dispatch = useDispatch(); + + const { message, options } = useSelect( select => select( STORE_ID ).getGlobalNotice() ); + return { + message, + options: options || {}, + clean: () => dispatch( STORE_ID ).cleanGlobalNotice(), + }; +} + +/** + * React custom hook to watch global events. + * For instance, when the user is not connected, + * the hook dispatches an action to populate the global notice. + */ +export default function useNoticeWatcher() { + const dispatch = useDispatch(); + const { isUserConnected } = useMyJetpackConnection(); + const navigate = useNavigate(); + + useEffect( () => { + if ( ! isUserConnected ) { + return dispatch( STORE_ID ).setGlobalNotice( + __( + 'Jetpack is currently not connected and some products might not work until the connection is reestablished.', + 'jetpack-my-jetpack' + ), + { + status: 'error', + actions: [ + { + label: __( 'Connect Jetpack now.', 'jetpack-my-jetpack' ), + onClick: () => navigate( '/connection' ), + variant: 'link', + noDefaultClasses: true, + }, + ], + } + ); + } + }, [ isUserConnected, dispatch, navigate ] ); +} diff --git a/projects/packages/my-jetpack/_inc/hooks/use-product/Readme.md b/projects/packages/my-jetpack/_inc/hooks/use-product/Readme.md index e42b63a9ca089..b6b930b72d0c0 100644 --- a/projects/packages/my-jetpack/_inc/hooks/use-product/Readme.md +++ b/projects/packages/my-jetpack/_inc/hooks/use-product/Readme.md @@ -23,8 +23,6 @@ An object with details about the product. Returns the current products list of My Jetpack. -An array with all products list. - ### activate( ) A helper function to activate a product. diff --git a/projects/packages/my-jetpack/_inc/hooks/use-product/index.js b/projects/packages/my-jetpack/_inc/hooks/use-product/index.js index 766e4491d148b..667604daf06a4 100644 --- a/projects/packages/my-jetpack/_inc/hooks/use-product/index.js +++ b/projects/packages/my-jetpack/_inc/hooks/use-product/index.js @@ -7,6 +7,7 @@ import { useSelect, useDispatch } from '@wordpress/data'; * Internal dependencies */ import { STORE_ID } from '../../state/store'; +import { mapObjectKeysToCamel } from '../../utils/to-camel'; /** * React custom hook to deal with a My Jetpack product. @@ -16,7 +17,14 @@ import { STORE_ID } from '../../state/store'; */ export function useProduct( productId ) { const { activateProduct, deactivateProduct } = useDispatch( STORE_ID ); - const detail = useSelect( select => select( STORE_ID ).getProduct( productId ) ); + + /* + * Re map object keys to camel case. + * Consider to improve this in the process. + */ + let detail = useSelect( select => select( STORE_ID ).getProduct( productId ) ); + detail = mapObjectKeysToCamel( detail, true ); + detail.pricingForUi = mapObjectKeysToCamel( detail.pricingForUi, true ); return { activate: () => activateProduct( productId ), @@ -24,7 +32,7 @@ export function useProduct( productId ) { productsList: useSelect( select => select( STORE_ID ).getProducts() ), detail, isActive: detail.status === 'active', + isFetching: useSelect( select => select( STORE_ID ).isFetching( productId ) ), status: detail.status, // shorthand. Consider to remove. - isFetching: !! detail.isFetching, }; } diff --git a/projects/packages/my-jetpack/_inc/hooks/use-route-blocker/index.js b/projects/packages/my-jetpack/_inc/hooks/use-route-blocker/index.js new file mode 100644 index 0000000000000..b5e5a9b8deaf7 --- /dev/null +++ b/projects/packages/my-jetpack/_inc/hooks/use-route-blocker/index.js @@ -0,0 +1,16 @@ +/** + * External dependencies + */ +import { useEffect } from 'react'; +import { useNavigationType, useNavigate } from 'react-router-dom'; + +export default () => { + const type = useNavigationType(); + const navigate = useNavigate(); + + useEffect( () => { + if ( type === 'POP' ) { + navigate( '/', { replace: true } ); + } + }, [ type, navigate ] ); +}; diff --git a/projects/packages/my-jetpack/_inc/state/actions.js b/projects/packages/my-jetpack/_inc/state/actions.js index c01e0676fcb0b..7290195937f4d 100644 --- a/projects/packages/my-jetpack/_inc/state/actions.js +++ b/projects/packages/my-jetpack/_inc/state/actions.js @@ -15,12 +15,16 @@ import { REST_API_SITE_PRODUCTS_ENDPOINT } from './constants'; const SET_PURCHASES_IS_FETCHING = 'SET_PURCHASES_IS_FETCHING'; const FETCH_PURCHASES = 'FETCH_PURCHASES'; const SET_PURCHASES = 'SET_PURCHASES'; -const SET_PRODUCT_ACTION_ERROR = 'SET_PRODUCT_ACTION_ERROR'; +const SET_IS_FETCHING_PRODUCT = 'SET_IS_FETCHING_PRODUCT'; +const SET_PRODUCT = 'SET_PRODUCT'; +const SET_PRODUCT_REQUEST_ERROR = 'SET_PRODUCT_REQUEST_ERROR'; const ACTIVATE_PRODUCT = 'ACTIVATE_PRODUCT'; const DEACTIVATE_PRODUCT = 'DEACTIVATE_PRODUCT'; -const SET_FETCHING_PRODUCT_STATUS = 'SET_FETCHING_PRODUCT_STATUS'; const SET_PRODUCT_STATUS = 'SET_PRODUCT_STATUS'; +const SET_GLOBAL_NOTICE = 'SET_GLOBAL_NOTICE'; +const CLEAN_GLOBAL_NOTICE = 'CLEAN_GLOBAL_NOTICE'; + const setPurchasesIsFetching = isFetching => { return { type: SET_PURCHASES_IS_FETCHING, isFetching }; }; @@ -33,17 +37,33 @@ const setPurchases = purchases => { return { type: SET_PURCHASES, purchases }; }; +const setProduct = product => ( { type: SET_PRODUCT, product } ); + +const setRequestProductError = ( productId, error ) => ( { + type: SET_PRODUCT_REQUEST_ERROR, + productId, + error, +} ); + const setProductStatus = ( productId, status ) => { return { type: SET_PRODUCT_STATUS, productId, status }; }; -const setIsFetchingProductStatus = ( productId, isFetching ) => { - return { type: SET_FETCHING_PRODUCT_STATUS, productId, isFetching }; -}; - -const setProductActionError = error => { - return { type: SET_PRODUCT_ACTION_ERROR, error }; -}; +/** + * Action that set the `isFetching` state of the product, + * when the client hits the server. + * + * @param {string} productId - My Jetpack product ID. + * @param {boolean} isFetching - True if the product is being fetched. Otherwise, False. + * @returns {object} - Redux action. + */ +function setIsFetchingProduct( productId, isFetching ) { + return { + type: SET_IS_FETCHING_PRODUCT, + productId, + isFetching, + }; +} /** * Side effect action which will sync @@ -61,31 +81,34 @@ function requestProductStatus( productId, data, { select, dispatch } ) { // Check valid product. const isValid = select.isValidProduct( productId ); if ( ! isValid ) { + dispatch( setProductStatus( productId, 'error' ) ); return dispatch( - setProductActionError( { + setRequestProductError( productId, { code: 'invalid_product', message: __( 'Invalid product name', 'jetpack-my-jetpack' ), } ) ); } - dispatch( setIsFetchingProductStatus( productId, true ) ); + const method = data.activate ? 'POST' : 'DELETE'; + dispatch( setIsFetchingProduct( productId, true ) ); // Activate/deactivate product. return apiFetch( { path: `${ REST_API_SITE_PRODUCTS_ENDPOINT }/${ productId }`, - method: 'POST', + method, data, } ) - .then( status => { - dispatch( setIsFetchingProductStatus( productId, false ) ); - dispatch( setProductStatus( productId, status ) ); + .then( freshProduct => { + dispatch( setIsFetchingProduct( productId, false ) ); + dispatch( setProduct( freshProduct ) ); resolve( status ); } ) .catch( error => { - dispatch( setProductActionError( error ) ); + dispatch( setProductStatus( productId, 'error' ) ); + dispatch( setRequestProductError( productId, error ) ); reject( error ); - dispatch( setIsFetchingProductStatus( productId, false ) ); + dispatch( setIsFetchingProduct( productId, false ) ); } ); } ); } @@ -113,14 +136,27 @@ const deactivateProduct = productId => async store => { }; const productActions = { + setProduct, activateProduct, deactivateProduct, + setIsFetchingProduct, + setRequestProductError, +}; + +const noticeActions = { + setGlobalNotice: ( message, options ) => ( { + type: 'SET_GLOBAL_NOTICE', + message, + options, + } ), + cleanGlobalNotice: () => ( { type: 'CLEAN_GLOBAL_NOTICE' } ), }; const actions = { setPurchasesIsFetching, fetchPurchases, setPurchases, + ...noticeActions, ...productActions, }; @@ -128,10 +164,13 @@ export { SET_PURCHASES_IS_FETCHING, FETCH_PURCHASES, SET_PURCHASES, - SET_PRODUCT_ACTION_ERROR, + SET_PRODUCT, + SET_PRODUCT_REQUEST_ERROR, ACTIVATE_PRODUCT, DEACTIVATE_PRODUCT, - SET_FETCHING_PRODUCT_STATUS, + SET_IS_FETCHING_PRODUCT, SET_PRODUCT_STATUS, + SET_GLOBAL_NOTICE, + CLEAN_GLOBAL_NOTICE, actions as default, }; diff --git a/projects/packages/my-jetpack/_inc/state/reducers.js b/projects/packages/my-jetpack/_inc/state/reducers.js index 593ffb0fca3d8..0301619589276 100644 --- a/projects/packages/my-jetpack/_inc/state/reducers.js +++ b/projects/packages/my-jetpack/_inc/state/reducers.js @@ -9,13 +9,31 @@ import { combineReducers } from '@wordpress/data'; import { SET_PURCHASES, SET_PURCHASES_IS_FETCHING, - SET_PRODUCT_ACTION_ERROR, + SET_PRODUCT, SET_PRODUCT_STATUS, - SET_FETCHING_PRODUCT_STATUS, + SET_IS_FETCHING_PRODUCT, + SET_PRODUCT_REQUEST_ERROR, + SET_GLOBAL_NOTICE, + CLEAN_GLOBAL_NOTICE, } from './actions'; const products = ( state = {}, action ) => { switch ( action.type ) { + case SET_IS_FETCHING_PRODUCT: { + const { productId, isFetching } = action; + return { + ...state, + isFetching: { + ...state.isFetching, + [ productId ]: isFetching, + }, + errors: { + ...state.errors, + [ productId ]: isFetching ? undefined : state.errors[ productId ], + }, + }; + } + case SET_PRODUCT_STATUS: { const { productId, status } = action; return { @@ -24,31 +42,32 @@ const products = ( state = {}, action ) => { ...state.items, [ productId ]: { ...state.items[ productId ], - ...status, + status, }, }, - error: {}, }; } - case SET_PRODUCT_ACTION_ERROR: + case SET_PRODUCT: { + const { product } = action; + const { slug: productId } = product; return { ...state, - error: action.error, + items: { + ...state.items, + [ productId ]: product, + }, }; + } - case SET_FETCHING_PRODUCT_STATUS: { - const { productId, isFetching } = action; + case SET_PRODUCT_REQUEST_ERROR: { + const { productId, error } = action; return { ...state, - items: { - ...state.items, - [ productId ]: { - ...state.items[ productId ], - isFetching, - }, + errors: { + ...state.errors, + [ productId ]: error, }, - error: isFetching ? {} : state.error, }; } @@ -76,9 +95,35 @@ const purchases = ( state = {}, action ) => { } }; +const notices = ( state = { global: {} }, action ) => { + switch ( action.type ) { + case SET_GLOBAL_NOTICE: { + const { message, options } = action; + return { + ...state, + global: { + message, + options, + }, + }; + } + + case CLEAN_GLOBAL_NOTICE: { + return { + ...state, + global: {}, + }; + } + + default: + return state; + } +}; + const reducers = combineReducers( { products, purchases, + notices, } ); export default reducers; diff --git a/projects/packages/my-jetpack/_inc/state/resolvers.js b/projects/packages/my-jetpack/_inc/state/resolvers.js index 22c828d9cbe29..e80b717012458 100644 --- a/projects/packages/my-jetpack/_inc/state/resolvers.js +++ b/projects/packages/my-jetpack/_inc/state/resolvers.js @@ -6,9 +6,26 @@ import apiFetch from '@wordpress/api-fetch'; /** * Internal dependencies */ -import { REST_API_SITE_PURCHASES_ENDPOINT } from './constants'; +import { REST_API_SITE_PURCHASES_ENDPOINT, REST_API_SITE_PRODUCTS_ENDPOINT } from './constants'; const myJetpackResolvers = { + getProduct: ( productId ) => async ( { dispatch } ) => { + try { + dispatch.setProduct( + await apiFetch( { + path: `${ REST_API_SITE_PRODUCTS_ENDPOINT }/${ productId }`, + } ) + ); + } catch ( error ) { + // Pick error from the response body. + if ( error?.code && error?.message ) { + dispatch.setRequestProductError( productId, error ); + } else { + throw new Error( error ); + } + } + }, + getPurchases: () => async ( { dispatch } ) => { dispatch.setPurchasesIsFetching( true ); diff --git a/projects/packages/my-jetpack/_inc/state/selectors.js b/projects/packages/my-jetpack/_inc/state/selectors.js index 8caa5597946d3..6d35a4d3364e9 100644 --- a/projects/packages/my-jetpack/_inc/state/selectors.js +++ b/projects/packages/my-jetpack/_inc/state/selectors.js @@ -9,6 +9,7 @@ const productSelectors = { getProductNames, getProduct, isValidProduct, + isFetching: ( state, productId ) => state.products?.isFetching?.[ productId ] || false, }; const purchasesSelectors = { @@ -16,9 +17,14 @@ const purchasesSelectors = { isRequestingPurchases: state => state.isRequestingPurchases || false, }; +const noticeSelectors = { + getGlobalNotice: state => state.notices?.global, +}; + const selectors = { ...productSelectors, ...purchasesSelectors, + ...noticeSelectors, }; export default selectors; diff --git a/projects/packages/my-jetpack/_inc/style.module.scss b/projects/packages/my-jetpack/_inc/style.module.scss new file mode 100644 index 0000000000000..94bb3d8604c2e --- /dev/null +++ b/projects/packages/my-jetpack/_inc/style.module.scss @@ -0,0 +1,14 @@ +.layout { + min-height: calc( 100vh - 100px ); // Thank you for creating with WordPress.Version 5.9 + position: relative; + padding-bottom: 30px; +} + +.footer { + position: absolute; + bottom: 0px; + width: 100%; + height: 30px; + line-height: 30px; + padding-right: 20px; +} \ No newline at end of file diff --git a/projects/packages/my-jetpack/_inc/utils/get-manage-your-plan-url.js b/projects/packages/my-jetpack/_inc/utils/get-manage-your-plan-url.js index ec5ab784ed8cd..bc1ea11af68be 100644 --- a/projects/packages/my-jetpack/_inc/utils/get-manage-your-plan-url.js +++ b/projects/packages/my-jetpack/_inc/utils/get-manage-your-plan-url.js @@ -17,6 +17,6 @@ import { MY_JETPACK_MY_PLANS_MANAGE_SOURCE } from '../constants'; * @returns {string} the redirect URL */ export default function () { - const { siteSuffix: site } = window?.myJetpackInitialState; + const site = window?.myJetpackInitialState?.siteSuffix; return getRedirectUrl( MY_JETPACK_MY_PLANS_MANAGE_SOURCE, { site } ); } diff --git a/projects/packages/my-jetpack/_inc/utils/to-camel.js b/projects/packages/my-jetpack/_inc/utils/to-camel.js new file mode 100644 index 0000000000000..986b8015a5149 --- /dev/null +++ b/projects/packages/my-jetpack/_inc/utils/to-camel.js @@ -0,0 +1,42 @@ +/** + * Convert snake case string to camel case string. + * + * @param {string} string - String to convert. + * @returns {string} - Converted string. + */ +export function snakeToCamel( string ) { + return string.replace( /([-_][a-z])/gi, $1 => { + return $1.toUpperCase().replace( '_', '' ); + } ); +} + +/** + * Check is the string has snake shape. + * + * @param {string} string - String to check. + * @returns {boolean} - True if the string has snake shape. + */ +function isSnake( string ) { + return string.indexOf( '_' ) !== -1; +} + +/** + * Map object keys to camel case, in case they have snake shape. + * + * @param {object} object - Object to be converted. + * @param {boolean} deleteOriginalProp - Whether to delete the original property. False by default. + * @returns {object} - Converted object. + */ +export function mapObjectKeysToCamel( object = {}, deleteOriginalProp = false ) { + for ( const key in object ) { + if ( object.hasOwnProperty( key ) && isSnake( key ) ) { + object[ snakeToCamel( key ) ] = object[ key ]; + + if ( deleteOriginalProp ) { + delete object[ key ]; + } + } + } + + return object; +} diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-data-approach b/projects/packages/my-jetpack/changelog/add-anti-spam-my-jetpack similarity index 57% rename from projects/packages/my-jetpack/changelog/update-my-jetpack-data-approach rename to projects/packages/my-jetpack/changelog/add-anti-spam-my-jetpack index 9a5a3d6662d69..797fde0a6b358 100644 --- a/projects/packages/my-jetpack/changelog/update-my-jetpack-data-approach +++ b/projects/packages/my-jetpack/changelog/add-anti-spam-my-jetpack @@ -1,4 +1,4 @@ Significance: patch Type: added -Add first data approach +anti spam product class diff --git a/projects/packages/my-jetpack/changelog/add-event-interstitial-my-jetpack b/projects/packages/my-jetpack/changelog/add-event-interstitial-my-jetpack new file mode 100644 index 0000000000000..059b466161234 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/add-event-interstitial-my-jetpack @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +Fire Tracks event when showing the Interstitial page diff --git a/projects/packages/my-jetpack/changelog/add-fancy-eslint-ignore b/projects/packages/my-jetpack/changelog/add-fancy-eslint-ignore deleted file mode 100644 index afe95e481cf32..0000000000000 --- a/projects/packages/my-jetpack/changelog/add-fancy-eslint-ignore +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: changed -Comment: Hack eslint config to use `.gitignore` and per-dir `.eslintignore`. - - diff --git a/projects/packages/my-jetpack/changelog/add-my-jetpack-product-card b/projects/packages/my-jetpack/changelog/add-my-jetpack-product-card deleted file mode 100644 index e07b1f0b309a2..0000000000000 --- a/projects/packages/my-jetpack/changelog/add-my-jetpack-product-card +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: added - -My Jetpack: Add Product Card component diff --git a/projects/packages/my-jetpack/changelog/add-my-jetpack-tracks-event-interstitial-click b/projects/packages/my-jetpack/changelog/add-my-jetpack-tracks-event-interstitial-click new file mode 100644 index 0000000000000..a13aedaf7087b --- /dev/null +++ b/projects/packages/my-jetpack/changelog/add-my-jetpack-tracks-event-interstitial-click @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +Fire Tracks event when clicking CTA button on product Interstitial page diff --git a/projects/packages/my-jetpack/changelog/add-my_jetpack_has_plan b/projects/packages/my-jetpack/changelog/add-my_jetpack_has_plan new file mode 100644 index 0000000000000..14a8adfb86373 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/add-my_jetpack_has_plan @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +Add has_required_plan to product info and implement method in Search diff --git a/projects/js-packages/storybook/changelog/2022-01-04-19-50-37-326407 b/projects/packages/my-jetpack/changelog/add-my_jetpack_has_plan#2 similarity index 100% rename from projects/js-packages/storybook/changelog/2022-01-04-19-50-37-326407 rename to projects/packages/my-jetpack/changelog/add-my_jetpack_has_plan#2 diff --git a/projects/packages/my-jetpack/changelog/add-products-section-my-jetpack b/projects/packages/my-jetpack/changelog/add-products-section-my-jetpack deleted file mode 100644 index a286866458353..0000000000000 --- a/projects/packages/my-jetpack/changelog/add-products-section-my-jetpack +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: added - -Adds very basic product cards section component to my jetpack diff --git a/projects/packages/my-jetpack/changelog/add-record-event-for-on-add b/projects/packages/my-jetpack/changelog/add-record-event-for-on-add new file mode 100644 index 0000000000000..e3a1920771229 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/add-record-event-for-on-add @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +Fire Tracks event when clickn Add link on My Jetpack product card diff --git a/projects/packages/my-jetpack/changelog/add-scan-and-backup-purchase-check b/projects/packages/my-jetpack/changelog/add-scan-and-backup-purchase-check new file mode 100644 index 0000000000000..bbe1f452756a9 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/add-scan-and-backup-purchase-check @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +Plan verification for Backup and Scan diff --git a/projects/packages/my-jetpack/changelog/add-visitor-status b/projects/packages/my-jetpack/changelog/add-visitor-status deleted file mode 100644 index 0b395e9ceee8c..0000000000000 --- a/projects/packages/my-jetpack/changelog/add-visitor-status +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: added - -Added Visitor class for status regarding the site visitor. diff --git a/projects/packages/my-jetpack/changelog/fix-set-product-status-reducer-my-jetpack b/projects/packages/my-jetpack/changelog/fix-set-product-status-reducer-my-jetpack new file mode 100644 index 0000000000000..85b9b40141658 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/fix-set-product-status-reducer-my-jetpack @@ -0,0 +1,4 @@ +Significance: patch +Type: fixed + +Fix My Jetpack's reducer for SET_PRODUCT_STATUS diff --git a/projects/packages/my-jetpack/changelog/fix-svg-attr-my-jetpack-product-card b/projects/packages/my-jetpack/changelog/fix-svg-attr-my-jetpack-product-card deleted file mode 100644 index f877ecaaf06f0..0000000000000 --- a/projects/packages/my-jetpack/changelog/fix-svg-attr-my-jetpack-product-card +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -Fixed svg attribute strokeWidth for Boost Card diff --git a/projects/packages/my-jetpack/changelog/poc-my-jetpac-product-class b/projects/packages/my-jetpack/changelog/poc-my-jetpac-product-class deleted file mode 100644 index 94d53f63b453c..0000000000000 --- a/projects/packages/my-jetpack/changelog/poc-my-jetpac-product-class +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: added - -add API endpoints to manipulate products diff --git a/projects/packages/my-jetpack/changelog/remove-plans-endpoints-my-jetpack b/projects/packages/my-jetpack/changelog/remove-plans-endpoints-my-jetpack deleted file mode 100644 index 494f1463fb811..0000000000000 --- a/projects/packages/my-jetpack/changelog/remove-plans-endpoints-my-jetpack +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: added - -Removed endpoint plans superseded by purchases diff --git a/projects/js-packages/storybook/changelog/renovate-storybook-monorepo#2 b/projects/packages/my-jetpack/changelog/renovate-wordpress-monorepo similarity index 100% rename from projects/js-packages/storybook/changelog/renovate-storybook-monorepo#2 rename to projects/packages/my-jetpack/changelog/renovate-wordpress-monorepo diff --git a/projects/js-packages/storybook/changelog/2022-01-11-19-07-56-905220 b/projects/packages/my-jetpack/changelog/renovate-wordpress-monorepo#2 similarity index 100% rename from projects/js-packages/storybook/changelog/2022-01-11-19-07-56-905220 rename to projects/packages/my-jetpack/changelog/renovate-wordpress-monorepo#2 diff --git a/projects/packages/my-jetpack/changelog/update-connection-enforce-initial-state b/projects/packages/my-jetpack/changelog/update-connection-enforce-initial-state deleted file mode 100644 index c47cb18e82997..0000000000000 --- a/projects/packages/my-jetpack/changelog/update-connection-enforce-initial-state +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: changed - -Updated package dependencies. diff --git a/projects/packages/my-jetpack/changelog/update-css-module-plans-section b/projects/packages/my-jetpack/changelog/update-css-module-plans-section deleted file mode 100644 index 85861596aba92..0000000000000 --- a/projects/packages/my-jetpack/changelog/update-css-module-plans-section +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: added - -Added css module for My Jetpack Plans Section diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-add-pricing-harcoded-product-data b/projects/packages/my-jetpack/changelog/update-my-jetpack-add-pricing-harcoded-product-data new file mode 100644 index 0000000000000..d6a890c2d7b86 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/update-my-jetpack-add-pricing-harcoded-product-data @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +Add Product princign harcoded data diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-add-product-boost-interstitial b/projects/packages/my-jetpack/changelog/update-my-jetpack-add-product-boost-interstitial new file mode 100644 index 0000000000000..946482fd9acb9 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/update-my-jetpack-add-product-boost-interstitial @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +Add Boost interstitial cmp. diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-add-product-interstitial-cmp b/projects/packages/my-jetpack/changelog/update-my-jetpack-add-product-interstitial-cmp new file mode 100644 index 0000000000000..4adad2e01ed71 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/update-my-jetpack-add-product-interstitial-cmp @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +Introduce ProductDetailCard component diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-add-products-endpoint b/projects/packages/my-jetpack/changelog/update-my-jetpack-add-products-endpoint deleted file mode 100644 index c0ec3dccade6f..0000000000000 --- a/projects/packages/my-jetpack/changelog/update-my-jetpack-add-products-endpoint +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: added - -Add Products and REST_Products basic classes diff --git a/projects/packages/connection-ui/changelog/update-enforce-connection-initial-state b/projects/packages/my-jetpack/changelog/update-my-jetpack-add-search-product-data similarity index 56% rename from projects/packages/connection-ui/changelog/update-enforce-connection-initial-state rename to projects/packages/my-jetpack/changelog/update-my-jetpack-add-search-product-data index c9a80df46cbc6..98561ef639652 100644 --- a/projects/packages/connection-ui/changelog/update-enforce-connection-initial-state +++ b/projects/packages/my-jetpack/changelog/update-my-jetpack-add-search-product-data @@ -1,4 +1,4 @@ Significance: patch Type: added -connection initial state +Add search product data diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-add-title-and-features-to-products-data b/projects/packages/my-jetpack/changelog/update-my-jetpack-add-title-and-features-to-products-data new file mode 100644 index 0000000000000..15e7180c0d3e4 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/update-my-jetpack-add-title-and-features-to-products-data @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +Add title and features to products data diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-clean-unused-hook b/projects/packages/my-jetpack/changelog/update-my-jetpack-clean-unused-hook deleted file mode 100644 index 3978d3f9d8702..0000000000000 --- a/projects/packages/my-jetpack/changelog/update-my-jetpack-clean-unused-hook +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: removed - -Remove unused usePlans() custom react hook diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-connection-redirect b/projects/packages/my-jetpack/changelog/update-my-jetpack-connection-redirect new file mode 100644 index 0000000000000..26fdd23674bdf --- /dev/null +++ b/projects/packages/my-jetpack/changelog/update-my-jetpack-connection-redirect @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +My Jetpack: Update notice style and implements redirect for connection route diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-connection-screen b/projects/packages/my-jetpack/changelog/update-my-jetpack-connection-screen new file mode 100644 index 0000000000000..324f508c87934 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/update-my-jetpack-connection-screen @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +My Jetpack: Add Connection screen diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-connections-section b/projects/packages/my-jetpack/changelog/update-my-jetpack-connections-section deleted file mode 100644 index b522b73954f77..0000000000000 --- a/projects/packages/my-jetpack/changelog/update-my-jetpack-connections-section +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: changed - -Add Connections Section wrapping the Connection Status Card to My Jetpack diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-do-not-ship-raw-files b/projects/packages/my-jetpack/changelog/update-my-jetpack-do-not-ship-raw-files deleted file mode 100644 index 8afa612f711b0..0000000000000 --- a/projects/packages/my-jetpack/changelog/update-my-jetpack-do-not-ship-raw-files +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: changed - -Build: do not ship raw files in production bundle. diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-fix-tracking-events-handler b/projects/packages/my-jetpack/changelog/update-my-jetpack-fix-tracking-events-handler new file mode 100644 index 0000000000000..63463e190d3e5 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/update-my-jetpack-fix-tracking-events-handler @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +useCallback for functions that are bound to onEvents diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-handle-search-product-from-ui b/projects/packages/my-jetpack/changelog/update-my-jetpack-handle-search-product-from-ui new file mode 100644 index 0000000000000..801eded873ab6 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/update-my-jetpack-handle-search-product-from-ui @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +Implement Search product interstitial diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-open-boost-interstitial b/projects/packages/my-jetpack/changelog/update-my-jetpack-open-boost-interstitial new file mode 100644 index 0000000000000..c1cea97a4d763 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/update-my-jetpack-open-boost-interstitial @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +Connect Boost card with the interstitial page via /add-boost root diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-re-organize-layout b/projects/packages/my-jetpack/changelog/update-my-jetpack-re-organize-layout new file mode 100644 index 0000000000000..92983c3c0bae1 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/update-my-jetpack-re-organize-layout @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +Introduce basic Layout component. Add GoBackLink component diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-reduxify-products b/projects/packages/my-jetpack/changelog/update-my-jetpack-reduxify-products deleted file mode 100644 index 1cc4b8bd62b93..0000000000000 --- a/projects/packages/my-jetpack/changelog/update-my-jetpack-reduxify-products +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: added - -My Jetpack: Implement data handling for enable/disable products diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-restore-get-product-resolver b/projects/packages/my-jetpack/changelog/update-my-jetpack-restore-get-product-resolver new file mode 100644 index 0000000000000..36331f47cce81 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/update-my-jetpack-restore-get-product-resolver @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +Restore getProduct() resolver diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-use-pricing-data b/projects/packages/my-jetpack/changelog/update-my-jetpack-use-pricing-data new file mode 100644 index 0000000000000..e129473a2969c --- /dev/null +++ b/projects/packages/my-jetpack/changelog/update-my-jetpack-use-pricing-data @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +Implement Free price for Boost product diff --git a/projects/packages/my-jetpack/changelog/update-project-scripts-no-install b/projects/packages/my-jetpack/changelog/update-project-scripts-no-install deleted file mode 100644 index f45fac5ea79e2..0000000000000 --- a/projects/packages/my-jetpack/changelog/update-project-scripts-no-install +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: removed -Comment: Tooling only: Build and test scripts no longer call `composer install` or `pnpm install`. - - diff --git a/projects/packages/my-jetpack/composer.json b/projects/packages/my-jetpack/composer.json index 3a485c4120fdf..3e7a28f67789f 100644 --- a/projects/packages/my-jetpack/composer.json +++ b/projects/packages/my-jetpack/composer.json @@ -5,14 +5,17 @@ "license": "GPL-2.0-or-later", "require": { "automattic/jetpack-admin-ui": "^0.2", - "automattic/jetpack-assets": "^1.16", + "automattic/jetpack-assets": "^1.17", "automattic/jetpack-connection": "^1.36", + "automattic/jetpack-plugins-installer": "^0.1", "automattic/jetpack-terms-of-service": "^1.9", "automattic/jetpack-tracking": "^1.14" }, "require-dev": { "yoast/phpunit-polyfills": "1.0.3", "automattic/jetpack-changelogger": "^3.0", + "automattic/jetpack-options": "^1.14", + "automattic/jetpack-search": "^0.7", "automattic/wordbless": "@dev" }, "autoload": { @@ -70,7 +73,7 @@ "link-template": "https://github.com/Automattic/jetpack-my-jetpack/compare/${old}...${new}" }, "branch-alias": { - "dev-master": "0.4.x-dev" + "dev-master": "0.5.x-dev" } }, "config": { diff --git a/projects/packages/my-jetpack/jest.setup.js b/projects/packages/my-jetpack/jest.setup.js index 01caebccf3e3c..06b97b04e86b9 100644 --- a/projects/packages/my-jetpack/jest.setup.js +++ b/projects/packages/my-jetpack/jest.setup.js @@ -2,3 +2,12 @@ * External dependencies */ import '@testing-library/jest-dom'; +window.JP_CONNECTION_INITIAL_STATE = { + userConnectionData: { + currentUser: { + wpcomUser: { Id: 99999, login: 'bobsacramento', display_name: 'Bob Sacrmaneto' }, + }, + }, +}; +window.myJetpackInitialState = {}; +window.myJetpackRest = {}; diff --git a/projects/packages/my-jetpack/package.json b/projects/packages/my-jetpack/package.json index b57cf8f5d5eed..d1b0019c61347 100644 --- a/projects/packages/my-jetpack/package.json +++ b/projects/packages/my-jetpack/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@automattic/jetpack-my-jetpack", - "version": "0.4.0-alpha", + "version": "0.5.1-alpha", "description": "WP Admin page with information and configuration shared among all Jetpack stand-alone plugins", "homepage": "https://jetpack.com", "bugs": { @@ -21,22 +21,26 @@ "test": "js-test-runner jest --passWithNoTests --setupFilesAfterEnv ./jest.setup.js" }, "dependencies": { - "@automattic/jetpack-analytics": "workspace:^0.1.7-alpha", - "@automattic/jetpack-components": "workspace:^0.10.3-alpha", - "@automattic/jetpack-connection": "workspace:^0.14.0-alpha", - "@wordpress/components": "19.1.6", - "@wordpress/data": "6.1.5", - "@wordpress/i18n": "4.2.4", + "@automattic/format-currency": "1.0.0-alpha.0", + "@automattic/jetpack-analytics": "workspace:^0.1.7", + "@automattic/jetpack-components": "workspace:^0.10.5-alpha", + "@automattic/jetpack-connection": "workspace:^0.15.1-alpha", + "@wordpress/api-fetch": "6.0.0", + "@wordpress/components": "19.3.0", + "@wordpress/data": "6.2.0", + "@wordpress/i18n": "4.3.0", + "@wordpress/icons": "6.2.0", "classnames": "2.3.1", - "prop-types": "15.8.1" + "prop-types": "15.8.1", + "react-router-dom": "6" }, "sideEffects": [ "*.css", "*.scss" ], "devDependencies": { - "@automattic/jetpack-base-styles": "workspace:^0.1.7-alpha", - "@automattic/jetpack-webpack-config": "workspace:^1.0.3-alpha", + "@automattic/jetpack-base-styles": "workspace:^0.1.8-alpha", + "@automattic/jetpack-webpack-config": "workspace:^1.1.2-alpha", "@babel/core": "7.16.0", "@babel/preset-env": "7.16.4", "@babel/register": "7.16.0", diff --git a/projects/packages/my-jetpack/src/class-initializer.php b/projects/packages/my-jetpack/src/class-initializer.php index 0365057c71175..af0c83b6084f8 100644 --- a/projects/packages/my-jetpack/src/class-initializer.php +++ b/projects/packages/my-jetpack/src/class-initializer.php @@ -28,12 +28,7 @@ class Initializer { * @return void */ public static function init() { - if ( did_action( 'my_jetpack_init' ) ) { - return; - } - - // Feature flag while we are developing it. - if ( ! defined( 'JETPACK_ENABLE_MY_JETPACK' ) || ! JETPACK_ENABLE_MY_JETPACK ) { + if ( ! self::should_initialize() ) { return; } @@ -102,8 +97,6 @@ public static function enqueue_scripts() { 'my_jetpack_main_app', 'myJetpackInitialState', array( - 'apiRoot' => esc_url_raw( rest_url() ), - 'apiNonce' => wp_create_nonce( 'wp_rest' ), 'products' => array( 'items' => Products::get_products(), ), @@ -116,6 +109,15 @@ public static function enqueue_scripts() { ) ); + wp_localize_script( + 'my_jetpack_main_app', + 'myJetpackRest', + array( + 'apiRoot' => esc_url_raw( rest_url() ), + 'apiNonce' => wp_create_nonce( 'wp_rest' ), + ) + ); + // Connection Initial State. wp_add_inline_script( 'my_jetpack_main_app', Connection_Initial_State::render(), 'before' ); @@ -166,6 +168,36 @@ public static function permissions_callback() { return current_user_can( 'manage_options' ); } + /** + * Return true if we should initialize the My Jetpack + */ + public static function should_initialize() { + if ( did_action( 'my_jetpack_init' ) ) { + return false; + } + + /** + * Allows filtering whether My Jetpack should be initialized + * + * @since 0.5.0-alpha + * + * @param bool $shoud_initialize Should we initialize My Jetpack? + */ + $should = apply_filters( 'jetpack_my_jetpack_should_initialize', true ); + + // Feature flag while we are developing it. + if ( ! defined( 'JETPACK_ENABLE_MY_JETPACK' ) || ! JETPACK_ENABLE_MY_JETPACK ) { + return false; + } + + // Do not initialize My Jetpack if site is not connected. + if ( ! ( new Connection_Manager() )->is_connected() ) { + return false; + } + + return $should; + } + /** * Site full-data endpoint. * diff --git a/projects/packages/my-jetpack/src/class-products.php b/projects/packages/my-jetpack/src/class-products.php index 2dfae5cfc0e42..36e8c75f74d0e 100644 --- a/projects/packages/my-jetpack/src/class-products.php +++ b/projects/packages/my-jetpack/src/class-products.php @@ -108,39 +108,7 @@ public static function get_product_data_schema() { * @return array Object with infromation about the product. */ public static function get_anti_spam_data() { - return array( - 'slug' => 'anti-spam', - 'description' => __( 'Stop comment and form spam', 'jetpack-my-jetpack' ), - 'name' => __( 'Anti-spam', 'jetpack-my-jetpack' ), - 'status' => 'inactive', - ); - } - - /** - * Activate Backup product - */ - public static function activate_backup_product() { - /* - * @todo: implement - * suggestion: when it enables, return an success array: - * array( 'status' => 'activated' ); - * Otherwise, an WP_Error instance will be nice. - */ - return array( - 'status' => 'active', - ); - } - - /** - * Deactivate Backup product - */ - public static function deactivate_backup_product() { - /* - * @todo: implement - */ - return array( - 'status' => 'inactive', - ); + return Products\Anti_Spam::get_info(); } /** @@ -149,12 +117,7 @@ public static function deactivate_backup_product() { * @return array Object with infromation about the product. */ public static function get_backup_data() { - return array( - 'slug' => 'backup', - 'description' => __( 'Save every change', 'jetpack-my-jetpack' ), - 'name' => __( 'Backup', 'jetpack-my-jetpack' ), - 'status' => 'active', - ); + return Products\Backup::get_info(); } /** @@ -172,12 +135,7 @@ public static function get_boost_data() { * @return array Object with infromation about the product. */ public static function get_crm_data() { - return array( - 'slug' => 'crm', - 'description' => __( 'Connect with your people', 'jetpack-my-jetpack' ), - 'name' => __( 'CRM', 'jetpack-my-jetpack' ), - 'status' => 'plugin_absent', - ); + return Products\Crm::get_info(); } /** @@ -200,12 +158,7 @@ public static function get_extras_data() { * @return array Object with infromation about the product. */ public static function get_scan_data() { - return array( - 'slug' => 'scan', - 'description' => __( 'Stay one step ahead of threats', 'jetpack-my-jetpack' ), - 'name' => __( 'Scan', 'jetpack-my-jetpack' ), - 'status' => 'plugin_absent', - ); + return Products\Scan::get_info(); } /** @@ -214,12 +167,7 @@ public static function get_scan_data() { * @return array Object with infromation about the product. */ public static function get_search_data() { - return array( - 'slug' => 'search', - 'description' => __( 'Help them find what they need', 'jetpack-my-jetpack' ), - 'name' => __( 'Search', 'jetpack-my-jetpack' ), - 'status' => 'plugin_absent', - ); + return Products\Search::get_info(); } /** @@ -228,11 +176,6 @@ public static function get_search_data() { * @return array Object with infromation about the product. */ public static function get_videopress_data() { - return array( - 'slug' => 'videopress', - 'description' => __( 'High quality, ad-free video', 'jetpack-my-jetpack' ), - 'name' => __( 'VideoPress', 'jetpack-my-jetpack' ), - 'status' => 'active', - ); + return Products\Videopress::get_info(); } } diff --git a/projects/packages/my-jetpack/src/class-rest-products.php b/projects/packages/my-jetpack/src/class-rest-products.php index 3f638f993bc09..debd291ffa096 100644 --- a/projects/packages/my-jetpack/src/class-rest-products.php +++ b/projects/packages/my-jetpack/src/class-rest-products.php @@ -32,7 +32,7 @@ public function __construct() { 'description' => __( 'Product slug', 'jetpack-my-jetpack' ), 'type' => 'string', 'enum' => Products::get_product_names(), - 'required' => false, + 'required' => true, 'validate_callback' => __CLASS__ . '::check_product_argument', ); @@ -68,6 +68,20 @@ public function __construct() { ); } + /** + * Get the schema for the products endpoint + * + * @return array + */ + public function get_products_schema() { + return array( + '$schema' => 'http://json-schema.org/draft-04/schema#', + 'title' => 'products', + 'type' => 'object', + 'properties' => Products::get_product_data_schema(), + ); + } + /** * Check user capability to access the endpoint. * @@ -107,9 +121,7 @@ public static function check_product_argument( $value ) { * @return array of site products list. */ public static function get_products() { - $response = array( - 'products' => Products::get_products(), - ); + $response = Products::get_products(); return rest_ensure_response( $response, 200 ); } @@ -121,10 +133,7 @@ public static function get_products() { */ public static function get_product( $request ) { $product_slug = $request->get_param( 'product' ); - $response = array( - 'products' => array( Products::get_product( $product_slug ) ), - ); - return rest_ensure_response( $response, 200 ); + return rest_ensure_response( Products::get_product( $product_slug ), 200 ); } /** @@ -152,30 +161,20 @@ public static function activate_product( $request ) { $product_slug = $request->get_param( 'product' ); $product = Products::get_product( $product_slug ); if ( ! isset( $product['class'] ) ) { - return new \WP_REST_Response( - array( - 'error_message' => 'not_implemented', - ), - 400 + return new \WP_Error( + 'not_implemented', + esc_html__( 'The product class handler is not implemented', 'jetpack-my-jetpack' ), + array( 'status' => 501 ) ); } - $success = call_user_func( array( $product['class'], 'activate' ) ); - $error_code = ''; - $error_message = ''; - if ( is_wp_error( $success ) ) { - $error_code = $success->get_error_code(); - $error_message = $success->get_error_message(); - $success = false; + $activate_product_result = call_user_func( array( $product['class'], 'activate' ) ); + if ( is_wp_error( $activate_product_result ) ) { + $activate_product_result->add_data( array( 'status' => 400 ) ); + return $activate_product_result; } - $response = array( - 'success' => $success, - 'products' => array( Products::get_product( $product_slug ) ), - 'error_code' => $error_code, - 'error_message' => $error_message, - ); - return rest_ensure_response( $response, 200 ); + return rest_ensure_response( Products::get_product( $product_slug ), 200 ); } /** @@ -188,37 +187,20 @@ public static function deactivate_product( $request ) { $product_slug = $request->get_param( 'product' ); $product = Products::get_product( $product_slug ); if ( ! isset( $product['class'] ) ) { - return new \WP_REST_Response( - array( - 'error_message' => 'not_implemented', - ), - 400 + return new \WP_Error( + 'not_implemented', + esc_html__( 'The product class handler is not implemented', 'jetpack-my-jetpack' ), + array( 'status' => 501 ) ); } - $success = call_user_func( array( $product['class'], 'deactivate' ) ); - $response = array( - 'success' => $success, - 'products' => array( Products::get_product( $product_slug ) ), - ); - return rest_ensure_response( $response, 200 ); - - } - - /** - * Set site product state. - * - * @param \WP_REST_Request $request The request object. - * @return array of site products list. - */ - public static function set_product_state( $request ) { - $product_slug = $request->get_param( 'product' ); - $activate = $request->get_param( 'activate' ); - - if ( $activate ) { - return Products::activate_backup_product( $product_slug ); + $deactivate_product_result = call_user_func( array( $product['class'], 'deactivate' ) ); + if ( is_wp_error( $deactivate_product_result ) ) { + $deactivate_product_result->add_data( array( 'status' => 400 ) ); + return $deactivate_product_result; } - return Products::deactivate_backup_product( $product_slug ); + return rest_ensure_response( Products::get_product( $product_slug ), 200 ); } + } diff --git a/projects/packages/my-jetpack/src/class-rest-purchases.php b/projects/packages/my-jetpack/src/class-rest-purchases.php index 3439c4f8da78d..e01089e45238e 100644 --- a/projects/packages/my-jetpack/src/class-rest-purchases.php +++ b/projects/packages/my-jetpack/src/class-rest-purchases.php @@ -8,6 +8,7 @@ namespace Automattic\Jetpack\My_Jetpack; use Automattic\Jetpack\Connection\Client as Client; +use Automattic\Jetpack\Connection\Manager as Connection_Manager; /** * Registers the REST routes for Purchases. @@ -37,6 +38,19 @@ public function __construct() { * @return true|WP_Error */ public static function permissions_callback() { + $connection = new Connection_Manager(); + $is_user_connected = $connection->is_connected(); + + if ( ! $is_user_connected ) { + return new \WP_Error( + 'not_connected', + __( 'You are not connected to Jetpack.', 'jetpack-my-jetpack' ), + array( + 'status' => 400, + ) + ); + } + return current_user_can( 'manage_options' ); } diff --git a/projects/packages/my-jetpack/src/products/class-anti-spam.php b/projects/packages/my-jetpack/src/products/class-anti-spam.php new file mode 100644 index 0000000000000..e30d2b395b065 --- /dev/null +++ b/projects/packages/my-jetpack/src/products/class-anti-spam.php @@ -0,0 +1,103 @@ + true, + 'currency_code' => 'EUR', + 'full_price' => '9', + 'promotion_percentage' => '50', + ); + } +} diff --git a/projects/packages/my-jetpack/src/products/class-backup.php b/projects/packages/my-jetpack/src/products/class-backup.php new file mode 100644 index 0000000000000..605e3addc3151 --- /dev/null +++ b/projects/packages/my-jetpack/src/products/class-backup.php @@ -0,0 +1,146 @@ + true, + 'currency_code' => 'EUR', + 'full_price' => '9', + 'promotion_percentage' => '50', + ); + } + + /** + * Hits the wpcom api to check rewind status. + * + * @todo Maybe add caching. + * + * @return Object|WP_Error + */ + private static function get_state_from_wpcom() { + static $status = null; + + if ( ! is_null( $status ) ) { + return $status; + } + + $site_id = Jetpack_Options::get_option( 'id' ); + + $response = Client::wpcom_json_api_request_as_blog( sprintf( '/sites/%d/rewind', $site_id ) . '?force=wpcom', '2', array(), null, 'wpcom' ); + + if ( 200 !== wp_remote_retrieve_response_code( $response ) ) { + return new WP_Error( 'rewind_state_fetch_failed' ); + } + + $body = wp_remote_retrieve_body( $response ); + $status = json_decode( $body ); + return $status; + } + + /** + * Checks whether the current plan (or purchases) of the site already supports the product + * + * @return boolean + */ + public static function has_required_plan() { + $rewind_data = static::get_state_from_wpcom(); + if ( is_wp_error( $rewind_data ) ) { + return false; + } + return is_object( $rewind_data ) && isset( $rewind_data->state ) && 'unavailable' !== $rewind_data->state; + } + +} diff --git a/projects/packages/my-jetpack/src/products/class-boost.php b/projects/packages/my-jetpack/src/products/class-boost.php index 5ce5a93f32c0a..633591392fac3 100644 --- a/projects/packages/my-jetpack/src/products/class-boost.php +++ b/projects/packages/my-jetpack/src/products/class-boost.php @@ -7,84 +7,99 @@ namespace Automattic\Jetpack\My_Jetpack\Products; +use Automattic\Jetpack\My_Jetpack\Product; + /** * Class responsible for handling the Boost product */ -class Boost { +class Boost extends Product { - const PLUGIN_FILENAME = 'boost/jetpack-boost.php'; + /** + * The product slug + * + * @var string + */ + public static $slug = 'boost'; /** - * Get the Product info for the API + * The filename (id) of the plugin associated with this product. If not defined, it will default to the Jetpack plugin * - * @return array + * @var string */ - public static function get_info() { - if ( self::is_active() ) { - $status = 'active'; - } elseif ( ! self::is_plugin_installed() ) { - $status = 'plugin_absent'; - } else { - $status = 'inactive'; - } - return array( - 'slug' => 'boost', - 'description' => __( 'Instant speed and SEO', 'jetpack-my-jetpack' ), - 'name' => __( 'Boost', 'jetpack-my-jetpack' ), - 'status' => $status, - 'class' => __CLASS__, - ); + public static $plugin_filename = 'boost/jetpack-boost.php'; + + /** + * The slug of the plugin associated with this product. If not defined, it will default to the Jetpack plugin + * + * @var string + */ + public static $plugin_slug = 'jetpack-boost'; + + /** + * Whether this product requires a user connection + * + * @var string + */ + public static $requires_user_connection = false; + + /** + * Get the internationalized product name + * + * @return string + */ + public static function get_name() { + return __( 'Boost', 'jetpack-my-jetpack' ); } /** - * Checks whether the Product is active + * Get the internationalized product title * - * @return boolean + * @return string */ - public static function is_active() { - return self::is_plugin_active(); + public static function get_title() { + return __( 'Jetpack Boost', 'jetpack-my-jetpack' ); } /** - * Checks whether the plugin is installed + * Get the internationalized product description * - * @return boolean + * @return string */ - public static function is_plugin_installed() { - $all_plugins = get_plugins(); - return array_key_exists( self::PLUGIN_FILENAME, $all_plugins ); + public static function get_description() { + return __( 'Instant speed and SEO', 'jetpack-my-jetpack' ); } /** - * Checks whether the plugin is active + * Get the internationalized product long description * - * @return boolean + * @return string */ - public static function is_plugin_active() { - return is_plugin_active( self::PLUGIN_FILENAME ); + public static function get_long_description() { + return __( 'Jetpack Boost gives your site the same performance advantages as the world’s leading websites, no developer required.', 'jetpack-my-jetpack' ); } /** - * Activates the plugin (in the future also intall the plugin if needed) + * Get the internationalized features list * - * @return boolean|\WP_Error + * @return array Boost features list */ - public static function activate() { - // TODO - extract lib/plugins.php from Jetpack in order to install. For now this will only activate the already installed plugin. - $result = activate_plugin( self::PLUGIN_FILENAME ); - if ( is_wp_error( $result ) ) { - return $result; - } - return is_null( $result ); + public static function get_features() { + return array( + __( 'Check your site performance', 'jetpack-my-jetpack' ), + __( 'Enable improvements in one click', 'jetpack-my-jetpack' ), + __( 'Standalone free plugin for those focused on speed', 'jetpack-my-jetpack' ), + ); } /** - * Deactivate the plugin + * Get the product princing details * - * @return boolean + * @return array Pricing details */ - public static function deactivate() { - deactivate_plugins( self::PLUGIN_FILENAME ); - return true; + public static function get_pricing_for_ui() { + return array( + 'available' => true, + 'is_free' => true, + ); } } diff --git a/projects/packages/my-jetpack/src/products/class-crm.php b/projects/packages/my-jetpack/src/products/class-crm.php new file mode 100644 index 0000000000000..4535ebfd59804 --- /dev/null +++ b/projects/packages/my-jetpack/src/products/class-crm.php @@ -0,0 +1,101 @@ + true, + 'is_free' => true, + ); + } +} diff --git a/projects/packages/my-jetpack/src/products/class-hybrid-product.php b/projects/packages/my-jetpack/src/products/class-hybrid-product.php new file mode 100644 index 0000000000000..2a1b55391cc88 --- /dev/null +++ b/projects/packages/my-jetpack/src/products/class-hybrid-product.php @@ -0,0 +1,30 @@ + static::$slug, + 'name' => static::get_name(), + 'title' => static::get_title(), + 'description' => static::get_description(), + 'long_description' => static::get_long_description(), + 'features' => static::get_features(), + 'status' => static::get_status(), + 'pricing_for_ui' => static::get_pricing_for_ui(), + 'requires_user_connection' => static::$requires_user_connection, + 'has_required_plan' => static::has_required_plan(), + 'class' => get_called_class(), + ); + } + + /** + * Get the internationalized product name + * + * @return string + */ + abstract public static function get_name(); + + /** + * Get the internationalized product title + * + * @return string + */ + abstract public static function get_title(); + + /** + * Get the internationalized product description + * + * @return string + */ + abstract public static function get_description(); + + /** + * Get the internationalized product long description + * + * @return string + */ + abstract public static function get_long_description(); + + /** + * Get the internationalized features list + * + * @return array + */ + abstract public static function get_features(); + + /** + * Get the product pricing + * + * @return array + */ + abstract public static function get_pricing_for_ui(); + + /** + * Checks whether the current plan (or purchases) of the site already supports the product + * + * Returns true if it supports. Return false if a purchase is still required. + * + * Free products will always return true. + * + * @return boolean + */ + public static function has_required_plan() { + return true; + } + + /** + * Undocumented function + * + * @return string + */ + public static function get_status() { + if ( ! static::has_required_plan() ) { + $status = 'needs_purchase'; + } elseif ( static::is_active() ) { + $status = 'active'; + } elseif ( ! self::is_plugin_installed() ) { + $status = 'plugin_absent'; + } else { + $status = 'inactive'; + } + return $status; + } + + /** + * Checks whether the Product is active + * + * @return boolean + */ + public static function is_active() { + return static::is_plugin_active(); + } + + /** + * Checks whether the plugin is installed + * + * @return boolean + */ + public static function is_plugin_installed() { + $all_plugins = Plugins_Installer::get_plugins(); + return array_key_exists( static::get_plugin_filename(), $all_plugins ); + } + + /** + * Checks whether the plugin is active + * + * @return boolean + */ + public static function is_plugin_active() { + return Plugins_Installer::is_plugin_active( static::get_plugin_filename() ); + } + + /** + * Checks whether the Jetpack plugin is installed + * + * @return boolean + */ + public static function is_jetpack_plugin_installed() { + $all_plugins = Plugins_Installer::get_plugins(); + return array_key_exists( self::JETPACK_PLUGIN_FILENAME, $all_plugins ); + } + + /** + * Checks whether the Jetpack plugin is active + * + * @return boolean + */ + public static function is_jetpack_plugin_active() { + return Plugins_Installer::is_plugin_active( self::JETPACK_PLUGIN_FILENAME ); + } + + /** + * Activates the product by installing and activating its plugin + * + * @return boolean|WP_Error + */ + public static function activate() { + if ( static::is_active() ) { + return true; + } + + if ( ! static::is_plugin_installed() ) { + $installed = Plugins_Installer::install_plugin( static::get_plugin_slug() ); + if ( is_wp_error( $installed ) ) { + return $installed; + } + } + + if ( ! current_user_can( 'activate_plugins' ) ) { + return new WP_Error( 'not_allowed', __( 'You are not allowed to activate plugins on this site.', 'jetpack-my-jetpack' ) ); + } + + $result = activate_plugin( static::get_plugin_filename() ); + if ( is_wp_error( $result ) ) { + return $result; + } + return is_null( $result ); + } + + /** + * Deactivate the product + * + * @return boolean + */ + public static function deactivate() { + deactivate_plugins( static::get_plugin_filename() ); + return true; + } +} diff --git a/projects/packages/my-jetpack/src/products/class-scan.php b/projects/packages/my-jetpack/src/products/class-scan.php new file mode 100644 index 0000000000000..cc90e315fe992 --- /dev/null +++ b/projects/packages/my-jetpack/src/products/class-scan.php @@ -0,0 +1,131 @@ + true, + 'is_free' => true, + ); + } + + /** + * Hits the wpcom api to check scan status. + * + * @todo Maybe add caching. + * + * @return Object|WP_Error + */ + private static function get_state_from_wpcom() { + static $status = null; + + if ( ! is_null( $status ) ) { + return $status; + } + + $site_id = Jetpack_Options::get_option( 'id' ); + + $response = Client::wpcom_json_api_request_as_blog( sprintf( '/sites/%d/scan', $site_id ) . '?force=wpcom', '2', array(), null, 'wpcom' ); + + if ( 200 !== wp_remote_retrieve_response_code( $response ) ) { + return new WP_Error( 'scan_state_fetch_failed' ); + } + + $body = wp_remote_retrieve_body( $response ); + $status = json_decode( $body ); + return $status; + } + + /** + * Checks whether the current plan (or purchases) of the site already supports the product + * + * @return boolean + */ + public static function has_required_plan() { + $scan_data = static::get_state_from_wpcom(); + if ( is_wp_error( $scan_data ) ) { + return false; + } + return is_object( $scan_data ) && isset( $scan_data->state ) && 'unavailable' !== $scan_data->state; + } + +} diff --git a/projects/packages/my-jetpack/src/products/class-search.php b/projects/packages/my-jetpack/src/products/class-search.php new file mode 100644 index 0000000000000..008290b2bf882 --- /dev/null +++ b/projects/packages/my-jetpack/src/products/class-search.php @@ -0,0 +1,108 @@ + true, + 'currency_code' => 'EUR', + 'full_price' => '4.50', + 'promotion_percentage' => '50', + ); + } + + /** + * Checks whether the current plan of the site already supports the product + * + * Returns true if it supports. Return false if a purchase is still required. + * + * Free products will always return true. + * + * @return boolean + */ + public static function has_required_plan() { + return ( new Search_PLan() )->supports_search(); + } +} diff --git a/projects/packages/my-jetpack/src/products/class-videopress.php b/projects/packages/my-jetpack/src/products/class-videopress.php new file mode 100644 index 0000000000000..abff0f858ade7 --- /dev/null +++ b/projects/packages/my-jetpack/src/products/class-videopress.php @@ -0,0 +1,89 @@ + true, + 'currency_code' => 'EUR', + 'full_price' => '9', + 'promotion_percentage' => '50', + ); + } +} diff --git a/projects/packages/my-jetpack/tests/php/assets/backup-mock-plugin.txt b/projects/packages/my-jetpack/tests/php/assets/backup-mock-plugin.txt new file mode 100644 index 0000000000000..62371573b2ebe --- /dev/null +++ b/projects/packages/my-jetpack/tests/php/assets/backup-mock-plugin.txt @@ -0,0 +1,11 @@ +markTestSkipped( 'avoid bug in PHP 5.6 that throws strict mode warnings for abstract static methods.' ); + } + + $this->install_mock_plugins(); + wp_cache_delete( 'plugins', 'plugins' ); + + } + + /** + * Installs the mock plugin present in the test assets folder as if it was the Boost plugin + * + * @return void + */ + public function install_mock_plugins() { + $plugin_dir = WP_PLUGIN_DIR . '/' . Backup::$plugin_slug; + if ( ! file_exists( $plugin_dir ) ) { + mkdir( $plugin_dir, 0777, true ); + } + if ( ! file_exists( WP_PLUGIN_DIR . '/jetpack' ) ) { + mkdir( WP_PLUGIN_DIR . '/jetpack', 0777, true ); + } + copy( __DIR__ . '/assets/backup-mock-plugin.txt', WP_PLUGIN_DIR . '/' . Backup::$plugin_filename ); + copy( __DIR__ . '/assets/jetpack-mock-plugin.txt', WP_PLUGIN_DIR . '/jetpack/jetpack.php' ); + } + + /** + * Returning the environment into its initial state. + * + * @after + */ + public function tear_down() { + + WorDBless_Options::init()->clear_options(); + + } + + /** + * Tests with Jetpack active + */ + public function test_if_jetpack_active_return_true() { + activate_plugin( 'jetpack/jetpack.php' ); + $this->assertTrue( Backup::is_active() ); + } + + /** + * Tests with Backup active + */ + public function test_if_jetpack_inactive_and_backup_active_return_true() { + deactivate_plugins( 'jetpack/jetpack.php' ); + activate_plugins( Backup::$plugin_filename ); + $this->assertTrue( Backup::is_active() ); + } + + /** + * Tests with both inactive + */ + public function test_if_jetpack_inactive_and_backup_inactive_return_false() { + deactivate_plugins( 'jetpack/jetpack.php' ); + deactivate_plugins( Backup::$plugin_filename ); + $this->assertFalse( Backup::is_active() ); + } + +} diff --git a/projects/packages/my-jetpack/tests/php/test-module-product.php b/projects/packages/my-jetpack/tests/php/test-module-product.php new file mode 100644 index 0000000000000..642925cfe3745 --- /dev/null +++ b/projects/packages/my-jetpack/tests/php/test-module-product.php @@ -0,0 +1,131 @@ +markTestSkipped( 'avoid bug in PHP 5.6 that throws strict mode warnings for abstract static methods.' ); + } + + $this->install_mock_plugins(); + wp_cache_delete( 'plugins', 'plugins' ); + + // Mock site connection. + ( new Tokens() )->update_blog_token( 'test.test.1' ); + Jetpack_Options::update_option( 'id', 123 ); + + Initializer::init(); + + self::$user_id = wp_insert_user( + array( + 'user_login' => 'test_admin', + 'user_pass' => '123', + 'role' => 'administrator', + ) + ); + wp_set_current_user( self::$user_id ); + + } + + /** + * Installs the mock plugin present in the test assets folder as if it was the Boost plugin + * + * @return void + */ + public function install_mock_plugins() { + if ( ! file_exists( WP_PLUGIN_DIR . '/jetpack' ) ) { + mkdir( WP_PLUGIN_DIR . '/jetpack', 0777, true ); + } + copy( __DIR__ . '/assets/jetpack-mock-plugin.txt', WP_PLUGIN_DIR . '/jetpack/jetpack.php' ); + } + + /** + * Returning the environment into its initial state. + * + * @after + */ + public function tear_down() { + + WorDBless_Options::init()->clear_options(); + WorDBless_Users::init()->clear_all_users(); + + } + + /** + * Tests exception module name missing + */ + public function test_throws_if_module_name_is_missing() { + $this->expectException( \Exception::class ); + require_once __DIR__ . '/class-broken-product.php'; + Broken_Product::is_module_active(); + } + + /** + * Test plugin slug and filename are overriden + */ + public function test_plugin_slug_and_filename() { + $this->assertSame( Videopress::JETPACK_PLUGIN_SLUG, Videopress::get_plugin_slug() ); + $this->assertSame( Videopress::JETPACK_PLUGIN_FILENAME, Videopress::get_plugin_filename() ); + } + + /** + * Tests activating/deactivating and checking active + */ + public function test_activate_and_check() { + $this->assertFalse( Videopress::is_active() ); + $this->assertTrue( Videopress::activate() ); + $this->assertTrue( Videopress::is_active() ); + $this->assertTrue( Videopress::deactivate() ); + $this->assertFalse( Videopress::is_active() ); + $this->assertFalse( Videopress::is_module_active() ); + $this->assertTrue( Videopress::is_plugin_active() ); + } + + /** + * Assert WP Error is returned if Jetpack fails to activate the module + */ + public function test_return_error_on_activation_failure() { + activate_plugins( 'jetpack/jetpack.php' ); + \Jetpack::$return_false = true; + $this->assertTrue( is_wp_error( Videopress::activate() ) ); + + // also check deactivate returns false. + $this->assertFalse( Videopress::deactivate() ); + } + +} diff --git a/projects/packages/my-jetpack/tests/php/test-products-rest.php b/projects/packages/my-jetpack/tests/php/test-products-rest.php index 2a599d3c3a841..e3620db23695f 100644 --- a/projects/packages/my-jetpack/tests/php/test-products-rest.php +++ b/projects/packages/my-jetpack/tests/php/test-products-rest.php @@ -2,6 +2,8 @@ namespace Automattic\Jetpack\My_Jetpack; +use Automattic\Jetpack\Connection\Tokens; +use Jetpack_Options; use PHPUnit\Framework\TestCase; use WorDBless\Options as WorDBless_Options; use WorDBless\Users as WorDBless_Users; @@ -58,7 +60,16 @@ class Test_Products_Rest extends TestCase { */ public function set_up() { + if ( version_compare( phpversion(), '5.7', '<=' ) ) { + $this->markTestSkipped( 'avoid bug in PHP 5.6 that throws strict mode warnings for abstract static methods.' ); + } + $this->install_mock_plugin(); + wp_cache_delete( 'plugins', 'plugins' ); + + // Mock site connection. + ( new Tokens() )->update_blog_token( 'test.test.1' ); + Jetpack_Options::update_option( 'id', 123 ); global $wp_rest_server; @@ -128,7 +139,7 @@ public function test_get_products() { $data = $response->get_data(); $this->assertEquals( 200, $response->get_status() ); - $this->assertEquals( $products, $data['products'] ); + $this->assertEquals( $products, $data ); } /** @@ -169,7 +180,7 @@ public function test_get_product() { $data = $response->get_data(); $this->assertEquals( 200, $response->get_status() ); - $this->assertEquals( $product, $data['products'][0] ); + $this->assertEquals( $product, $data ); } /** @@ -196,7 +207,8 @@ public function test_activate_boost() { $response = $this->server->dispatch( $this->request ); $data = $response->get_data(); - $this->assertEquals( 'active', $data['products'][0]['status'] ); + $this->assertEquals( 200, $response->get_status() ); + $this->assertEquals( 'active', $data['status'] ); $this->assertTrue( is_plugin_active( $this->boost_mock_filename ) ); } @@ -214,7 +226,8 @@ public function test_deactivate_boost() { $response = $this->server->dispatch( $this->request ); $data = $response->get_data(); - $this->assertEquals( 'inactive', $data['products'][0]['status'] ); + $this->assertEquals( 200, $response->get_status() ); + $this->assertEquals( 'inactive', $data['status'] ); $this->assertFalse( is_plugin_active( $this->boost_mock_filename ) ); } @@ -233,9 +246,8 @@ public function test_activate_uninstallable() { $response = $this->server->dispatch( $this->request ); $data = $response->get_data(); - $this->assertEquals( 'inactive', $data['products'][0]['status'] ); - $this->assertEquals( 'plugin_php_incompatible', $data['error_code'] ); - $this->assertFalse( $data['success'] ); + $this->assertEquals( 400, $response->get_status() ); + $this->assertEquals( 'plugin_php_incompatible', $data['code'] ); $this->assertFalse( is_plugin_active( $this->boost_mock_filename ) ); } diff --git a/projects/packages/partner/CHANGELOG.md b/projects/packages/partner/CHANGELOG.md index 47591032d7dc0..7a9682bad3c90 100644 --- a/projects/packages/partner/CHANGELOG.md +++ b/projects/packages/partner/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.6.4] - 2022-01-25 +### Changed +- Updated package dependencies. + ## [1.6.3] - 2022-01-18 ### Changed - Updated package dependencies. @@ -112,6 +116,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add partner subsidiary id to upgrade URLs. +[1.6.4]: https://github.com/Automattic/jetpack-partner/compare/v1.6.3...v1.6.4 [1.6.3]: https://github.com/Automattic/jetpack-partner/compare/v1.6.2...v1.6.3 [1.6.2]: https://github.com/Automattic/jetpack-partner/compare/v1.6.1...v1.6.2 [1.6.1]: https://github.com/Automattic/jetpack-partner/compare/v1.6.0...v1.6.1 diff --git a/projects/packages/partner/changelog/update-project-scripts-no-install b/projects/packages/partner/changelog/update-project-scripts-no-install deleted file mode 100644 index f45fac5ea79e2..0000000000000 --- a/projects/packages/partner/changelog/update-project-scripts-no-install +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: removed -Comment: Tooling only: Build and test scripts no longer call `composer install` or `pnpm install`. - - diff --git a/projects/packages/password-checker/CHANGELOG.md b/projects/packages/password-checker/CHANGELOG.md index 8ecd21434f877..371ad3435909e 100644 --- a/projects/packages/password-checker/CHANGELOG.md +++ b/projects/packages/password-checker/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.2.2] - 2022-01-25 +### Changed +- Updated package dependencies. + ## [0.2.1] - 2022-01-18 ### Changed - Updated package dependencies. @@ -56,6 +60,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Use `composer update` rather than `install` in scripts, as composer.lock isn't checked in. +[0.2.2]: https://github.com/Automattic/jetpack-password-checker/compare/v0.2.1...v0.2.2 [0.2.1]: https://github.com/Automattic/jetpack-password-checker/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/Automattic/jetpack-password-checker/compare/v0.1.8...v0.2.0 [0.1.8]: https://github.com/Automattic/jetpack-password-checker/compare/v0.1.7...v0.1.8 diff --git a/projects/packages/password-checker/changelog/update-project-scripts-no-install b/projects/packages/password-checker/changelog/update-project-scripts-no-install deleted file mode 100644 index f45fac5ea79e2..0000000000000 --- a/projects/packages/password-checker/changelog/update-project-scripts-no-install +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: removed -Comment: Tooling only: Build and test scripts no longer call `composer install` or `pnpm install`. - - diff --git a/projects/packages/plans/.gitattributes b/projects/packages/plans/.gitattributes new file mode 100644 index 0000000000000..dd08c5ac8f82f --- /dev/null +++ b/projects/packages/plans/.gitattributes @@ -0,0 +1,15 @@ +# Files not needed to be distributed in the package. +.gitattributes export-ignore +.github/ export-ignore +package.json export-ignore + +# Files to include in the mirror repo, but excluded via gitignore +# Remember to end all directories with `/**` to properly tag every file. +# /src/js/example.min.js production-include + +# Files to exclude from the mirror repo, but included in the monorepo. +# Remember to end all directories with `/**` to properly tag every file. +.gitignore production-exclude +changelog/** production-exclude +phpunit.xml.dist production-exclude +tests/** production-exclude diff --git a/projects/packages/plans/.gitignore b/projects/packages/plans/.gitignore new file mode 100644 index 0000000000000..32d2a35ceea33 --- /dev/null +++ b/projects/packages/plans/.gitignore @@ -0,0 +1,3 @@ +vendor/ +node_modules/ +wordpress diff --git a/projects/packages/plans/CHANGELOG.md b/projects/packages/plans/CHANGELOG.md new file mode 100644 index 0000000000000..721294abd00ad --- /dev/null +++ b/projects/packages/plans/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + diff --git a/projects/packages/plans/README.md b/projects/packages/plans/README.md new file mode 100644 index 0000000000000..61fc69d944839 --- /dev/null +++ b/projects/packages/plans/README.md @@ -0,0 +1,20 @@ +# plans + +Fetch information about Jetpack Plans from wpcom + +## How to install plans + +### Installation From Git Repo + +## Contribute + +## Get Help + +## Security + +Need to report a security vulnerability? Go to [https://automattic.com/security/](https://automattic.com/security/) or directly to our security bug bounty site [https://hackerone.com/automattic](https://hackerone.com/automattic). + +## License + +plans is licensed under [GNU General Public License v2 (or later)](./LICENSE.txt) + diff --git a/projects/packages/plans/changelog/.gitkeep b/projects/packages/plans/changelog/.gitkeep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/projects/packages/plans/changelog/extract-jetpack-plans b/projects/packages/plans/changelog/extract-jetpack-plans new file mode 100644 index 0000000000000..65c54db985465 --- /dev/null +++ b/projects/packages/plans/changelog/extract-jetpack-plans @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Package created diff --git a/projects/packages/plans/changelog/update-plans-mirror-repo b/projects/packages/plans/changelog/update-plans-mirror-repo new file mode 100644 index 0000000000000..d7a7b73a40586 --- /dev/null +++ b/projects/packages/plans/changelog/update-plans-mirror-repo @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Core: update composer info to support mirror repo. diff --git a/projects/packages/plans/composer.json b/projects/packages/plans/composer.json new file mode 100644 index 0000000000000..74f0368b39d43 --- /dev/null +++ b/projects/packages/plans/composer.json @@ -0,0 +1,61 @@ +{ + "name": "automattic/jetpack-plans", + "description": "Fetch information about Jetpack Plans from wpcom", + "type": "library", + "license": "GPL-2.0-or-later", + "require": { + "automattic/jetpack-connection": "^1.36" + }, + "require-dev": { + "yoast/phpunit-polyfills": "1.0.3", + "automattic/jetpack-changelogger": "^3.0", + "automattic/jetpack-options": "^1.14", + "automattic/jetpack-status": "^1.10", + "automattic/wordbless": "@dev" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "scripts": { + "phpunit": [ + "./vendor/phpunit/phpunit/phpunit --colors=always" + ], + "test-coverage": [ + "php -dpcov.directory=. ./vendor/bin/phpunit --coverage-clover \"$COVERAGE_DIR/clover.xml\"" + ], + "test-php": [ + "@composer phpunit" + ], + "post-update-cmd": "php -r \"copy('vendor/automattic/wordbless/src/dbless-wpdb.php', 'wordpress/wp-content/db.php');\"", + "build-production": "echo 'Add your build step to composer.json, please!'", + "build-development": "echo 'Add your build step to composer.json, please!'" + }, + "repositories": [ + { + "type": "path", + "url": "../../packages/*", + "options": { + "monorepo": true + } + } + ], + "minimum-stability": "dev", + "prefer-stable": true, + "extra": { + "autotagger": true, + "mirror-repo": "Automattic/jetpack-plans", + "changelogger": { + "link-template": "https://github.com/Automattic/jetpack-plans/compare/v${old}...v${new}" + }, + "branch-alias": { + "dev-master": "0.1.x-dev" + } + }, + "config": { + "allow-plugins": { + "roots/wordpress-core-installer": true + } + } +} diff --git a/projects/packages/plans/package.json b/projects/packages/plans/package.json new file mode 100644 index 0000000000000..f0aefec8c45cb --- /dev/null +++ b/projects/packages/plans/package.json @@ -0,0 +1,29 @@ +{ + "private": true, + "name": "@automattic/jetpack-plans", + "version": "0.1.0-alpha", + "description": "Fetch information about Jetpack Plans from wpcom", + "homepage": "https://jetpack.com", + "bugs": { + "url": "https://github.com/Automattic/jetpack/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/Automattic/jetpack.git" + }, + "license": "GPL-2.0-or-later", + "author": "Automattic", + "scripts": { + "build": "echo 'Not implemented.", + "build-js": "echo 'Not implemented.", + "build-production": "echo 'Not implemented.", + "build-production-js": "echo 'Not implemented.", + "clean": "true" + }, + "devDependencies": {}, + "engines": { + "node": "^14.18.3 || ^16.13.2", + "pnpm": "^6.23.6", + "yarn": "use pnpm instead - see docs/yarn-upgrade.md" + } +} diff --git a/projects/packages/plans/phpunit.xml.dist b/projects/packages/plans/phpunit.xml.dist new file mode 100644 index 0000000000000..3223c32458db2 --- /dev/null +++ b/projects/packages/plans/phpunit.xml.dist @@ -0,0 +1,14 @@ + + + + tests/php + + + + + + + src + + + diff --git a/projects/packages/plans/src/class-current-plan.php b/projects/packages/plans/src/class-current-plan.php new file mode 100644 index 0000000000000..10f71cc109bd8 --- /dev/null +++ b/projects/packages/plans/src/class-current-plan.php @@ -0,0 +1,362 @@ + array( + 'plans' => array( + 'jetpack_free', + ), + 'supports' => array( + 'opentable', + 'calendly', + 'send-a-message', + 'whatsapp-button', + 'social-previews', + 'videopress', + + 'core/video', + 'core/cover', + 'core/audio', + ), + ), + 'personal' => array( + 'plans' => array( + 'jetpack_personal', + 'jetpack_personal_monthly', + 'personal-bundle', + 'personal-bundle-monthly', + 'personal-bundle-2y', + ), + 'supports' => array( + 'akismet', + 'recurring-payments', + 'premium-content/container', + 'videopress', + ), + ), + 'premium' => array( + 'plans' => array( + 'jetpack_premium', + 'jetpack_premium_monthly', + 'value_bundle', + 'value_bundle-monthly', + 'value_bundle-2y', + ), + 'supports' => array( + 'donations', + 'simple-payments', + 'vaultpress', + 'videopress', + 'republicize', + ), + ), + 'security' => array( + 'plans' => array( + 'jetpack_security_daily', + 'jetpack_security_daily_monthly', + 'jetpack_security_realtime', + 'jetpack_security_realtime_monthly', + 'jetpack_security_t1_yearly', + 'jetpack_security_t1_monthly', + 'jetpack_security_t2_yearly', + 'jetpack_security_t2_monthly', + ), + 'supports' => array(), + ), + 'business' => array( + 'plans' => array( + 'jetpack_business', + 'jetpack_business_monthly', + 'business-bundle', + 'business-bundle-monthly', + 'business-bundle-2y', + 'ecommerce-bundle', + 'ecommerce-bundle-monthly', + 'ecommerce-bundle-2y', + ), + 'supports' => array(), + ), + + 'complete' => array( + 'plans' => array( + 'jetpack_complete', + 'jetpack_complete_monthly', + 'vip', + ), + 'supports' => array(), + ), + ); + + /** + * Given a response to the `/sites/%d` endpoint, will parse the response and attempt to set the + * site's plan and products from the response. + * + * @param array $response The response from `/sites/%d`. + * @return bool Was the plan successfully updated? + */ + public static function update_from_sites_response( $response ) { + // Bail if there was an error or malformed response. + if ( is_wp_error( $response ) || ! is_array( $response ) || ! isset( $response['body'] ) ) { + return false; + } + + $body = wp_remote_retrieve_body( $response ); + if ( is_wp_error( $body ) ) { + return false; + } + + // Decode the results. + $results = json_decode( $body, true ); + + if ( ! is_array( $results ) ) { + return false; + } + + if ( isset( $results['products'] ) ) { + // Store the site's products in an option and return true if updated. + self::store_data_in_option( self::SITE_PRODUCTS_OPTION, $results['products'] ); + } + + if ( ! isset( $results['plan'] ) ) { + return false; + } + + $current_plan = get_option( self::PLAN_OPTION, array() ); + + if ( ! empty( $current_plan ) && $current_plan === $results['plan'] ) { + // Bail if the plans array hasn't changed. + return false; + } + + // Store the new plan in an option and return true if updated. + $result = self::store_data_in_option( self::PLAN_OPTION, $results['plan'] ); + + if ( $result ) { + // Reset the cache since we've just updated the plan. + self::$active_plan_cache = null; + } + + return $result; + } + + /** + * Store data in an option. + * + * @param string $option The name of the option that will store the data. + * @param array $data Data to be store in an option. + * @return bool Were the subscriptions successfully updated? + */ + private static function store_data_in_option( $option, $data ) { + $result = update_option( $option, $data, true ); + + // If something goes wrong with the update, so delete the current option and then update it. + if ( ! $result ) { + delete_option( $option ); + $result = update_option( $option, $data, true ); + } + + return $result; + } + + /** + * Make an API call to WordPress.com for plan status + * + * @uses Jetpack_Options::get_option() + * @uses Client::wpcom_json_api_request_as_blog() + * @uses update_option() + * + * @access public + * @static + * + * @return bool True if plan is updated, false if no update + */ + public static function refresh_from_wpcom() { + // Make the API request. + $request = sprintf( '/sites/%d', Jetpack_Options::get_option( 'id' ) ); + $response = Client::wpcom_json_api_request_as_blog( $request, '1.1' ); + + return self::update_from_sites_response( $response ); + } + + /** + * Get the plan that this Jetpack site is currently using. + * + * @uses get_option() + * + * @access public + * @static + * + * @return array Active Jetpack plan details + */ + public static function get() { + // this can be expensive to compute so we cache for the duration of a request. + if ( is_array( self::$active_plan_cache ) && ! empty( self::$active_plan_cache ) ) { + return self::$active_plan_cache; + } + + $plan = get_option( self::PLAN_OPTION, array() ); + + // Set the default options. + $plan = wp_parse_args( + $plan, + array( + 'product_slug' => 'jetpack_free', + 'class' => 'free', + 'features' => array( + 'active' => array(), + ), + ) + ); + + list( $plan['class'], $supports ) = self::get_class_and_features( $plan['product_slug'] ); + + // get available features if Jetpack is active. + if ( class_exists( 'Jetpack' ) ) { + foreach ( Jetpack::get_available_modules() as $module_slug ) { + $module = Jetpack::get_module( $module_slug ); + if ( ! isset( $module ) || ! is_array( $module ) ) { + continue; + } + if ( in_array( 'free', $module['plan_classes'], true ) || in_array( $plan['class'], $module['plan_classes'], true ) ) { + $supports[] = $module_slug; + } + } + } + + $plan['supports'] = $supports; + + self::$active_plan_cache = $plan; + + return $plan; + } + + /** + * Get the site's products. + * + * @uses get_option() + * + * @access public + * @static + * + * @return array Active Jetpack products + */ + public static function get_products() { + return get_option( self::SITE_PRODUCTS_OPTION, array() ); + } + + /** + * Get the class of plan and a list of features it supports + * + * @param string $plan_slug The plan that we're interested in. + * @return array Two item array, the plan class and the an array of features. + */ + private static function get_class_and_features( $plan_slug ) { + $features = array(); + foreach ( self::PLAN_DATA as $class => $details ) { + $features = array_merge( $features, $details['supports'] ); + if ( in_array( $plan_slug, $details['plans'], true ) ) { + return array( $class, $features ); + } + } + return array( 'free', self::PLAN_DATA['free']['supports'] ); + } + + /** + * Gets the minimum plan slug that supports the given feature + * + * @param string $feature The name of the feature. + * @return string|bool The slug for the minimum plan that supports. + * the feature or false if not found + */ + public static function get_minimum_plan_for_feature( $feature ) { + foreach ( self::PLAN_DATA as $details ) { + if ( in_array( $feature, $details['supports'], true ) ) { + return $details['plans'][0]; + } + } + return false; + } + + /** + * Determine whether the active plan supports a particular feature + * + * @uses Jetpack_Plan::get() + * + * @access public + * @static + * + * @param string $feature The module or feature to check. + * + * @return bool True if plan supports feature, false if not + */ + public static function supports( $feature ) { + // Search product bypasses plan feature check. + if ( 'search' === $feature && (bool) get_option( 'has_jetpack_search_product' ) ) { + return true; + } + + // As of Q3 2021 - a videopress free tier is available to all plans. + if ( 'videopress' === $feature ) { + return true; + } + + $plan = self::get(); + + // Manually mapping WordPress.com features to Jetpack module slugs. + foreach ( $plan['features']['active'] as $wpcom_feature ) { + switch ( $wpcom_feature ) { + case 'wordads-jetpack': + // WordAds are supported for this site. + if ( 'wordads' === $feature ) { + return true; + } + break; + } + } + + if ( + in_array( $feature, $plan['supports'], true ) + || in_array( $feature, $plan['features']['active'], true ) + ) { + return true; + } + + return false; + } +} diff --git a/projects/packages/plans/src/class-plans.php b/projects/packages/plans/src/class-plans.php new file mode 100644 index 0000000000000..b96ffdb4dcdbd --- /dev/null +++ b/projects/packages/plans/src/class-plans.php @@ -0,0 +1,80 @@ + 'GET', + 'headers' => array( + 'X-Forwarded-For' => ( new Automattic\Jetpack\Status\Visitor() )->get_ip( true ), + ), + ), + null, + 'rest' + ); + + $body = wp_remote_retrieve_body( $request ); + if ( 200 === wp_remote_retrieve_response_code( $request ) ) { + return json_decode( $body ); + } else { + return $body; + } + } + + /** + * Get plan information for a plan given its slug + * + * @since-jetpack 7.7.0 + * + * @param string $plan_slug Plan slug. + * + * @return object The plan object + */ + public static function get_plan( $plan_slug ) { + $plans = self::get_plans(); + if ( ! is_array( $plans ) ) { + return; + } + + foreach ( $plans as $plan ) { + if ( $plan_slug === $plan->product_slug ) { + return $plan; + } + } + } +} diff --git a/projects/packages/plans/src/example.php b/projects/packages/plans/src/example.php new file mode 100644 index 0000000000000..a788a63305dc4 --- /dev/null +++ b/projects/packages/plans/src/example.php @@ -0,0 +1,8 @@ +get_free_plan(), true ); + + $option = get_option( 'jetpack_active_plan' ); + $this->assertSame( 'jetpack_free', $option['product_slug'] ); + + // Set up an issue where the value in cache does not match the DB, so the DB update fails. + Jetpack_Options::update_raw_option( 'jetpack_active_plan', $this->get_personal_plan(), true ); + + $this->assertTrue( Jetpack_Plan::update_from_sites_response( $this->get_response_personal_plan() ) ); + } + + /** + * @dataProvider get_update_from_sites_response_data + */ + public function test_update_from_sites_response( $response, $expected_plan_slug_after, $expected_return, $initial_option = null ) { + + if ( ! is_null( $initial_option ) ) { + update_option( 'jetpack_active_plan', $initial_option, true ); + } + + $this->assertSame( $expected_return, Jetpack_Plan::update_from_sites_response( $response ) ); + + $plan = Jetpack_Plan::get(); + $this->assertSame( $expected_plan_slug_after, $plan['product_slug'] ); + } + + public function get_update_from_sites_response_data() { + return array( + 'is_errored_response' => array( + $this->get_errored_sites_response(), + 'jetpack_free', + false, + ), + 'response_is_empty' => array( + $this->get_mocked_response( 200, '' ), + 'jetpack_free', + false, + ), + 'response_does_not_have_body' => array( + array( 'code' => 400 ), + 'jetpack_free', + false, + ), + 'response_does_not_have_plan' => array( + array( + 'code' => 200, + array(), + ), + 'jetpack_free', + false, + ), + 'initially_empty_option_to_free' => array( + $this->get_response_free_plan(), + 'jetpack_free', + true, + ), + 'initially_empty_to_personal' => array( + $this->get_response_personal_plan(), + 'jetpack_personal', + true, + ), + 'initially_free_to_personal' => array( + $this->get_response_personal_plan(), + 'jetpack_personal', + true, + $this->get_free_plan(), + ), + 'initially_personal_to_free' => array( + $this->get_response_free_plan(), + 'jetpack_free', + true, + $this->get_personal_plan(), + ), + 'initially_free_no_change' => array( + $this->get_response_free_plan(), + 'jetpack_free', + false, + $this->get_free_plan(), + ), + 'initially_personal_to_changed_personal' => array( + $this->get_response_changed_personal_plan(), + 'jetpack_personal', + true, + $this->get_response_personal_plan(), + ), + ); + } + + private function get_response_free_plan() { + return $this->get_successful_plan_response( $this->get_free_plan() ); + } + + private function get_response_personal_plan() { + return $this->get_successful_plan_response( $this->get_personal_plan() ); + } + + private function get_response_changed_personal_plan() { + return $this->get_successful_plan_response( $this->get_changed_personal_plan() ); + } + + private function get_successful_plan_response( $plan_response ) { + $body = wp_json_encode( + array( + 'plan' => $plan_response, + ) + ); + return $this->get_mocked_response( 200, $body ); + } + + private function get_errored_sites_response() { + return $this->get_mocked_response( 400, new WP_Error() ); + } + + private function get_mocked_response( $code, $body ) { + return array( + 'code' => $code, + 'body' => $body, + ); + } + + private function get_free_plan() { + return array( + 'product_id' => 2002, + 'product_slug' => 'jetpack_free', + 'product_name_short' => 'Free', + 'expired' => false, + 'user_is_owner' => false, + 'is_free' => true, + 'features' => array( + 'active' => array( + 'akismet', + 'support', + ), + 'available' => array( + 'akismet' => array( + 'jetpack_premium', + 'jetpack_business', + 'jetpack_premium_monthly', + 'jetpack_business_monthly', + ), + 'vaultpress-backups' => array( + 'jetpack_premium', + 'jetpack_business', + 'jetpack_premium_monthly', + 'jetpack_business_monthly', + ), + 'vaultpress-backup-archive' => array( + 'jetpack_premium', + 'jetpack_business', + 'jetpack_premium_monthly', + 'jetpack_business_monthly', + ), + 'vaultpress-storage-space' => array( + 'jetpack_premium', + 'jetpack_business', + 'jetpack_premium_monthly', + 'jetpack_business_monthly', + ), + 'vaultpress-automated-restores' => array( + 'jetpack_premium', + 'jetpack_business', + 'jetpack_premium_monthly', + 'jetpack_business_monthly', + ), + 'simple-payments' => array( + 'jetpack_premium', + 'jetpack_business', + 'jetpack_premium_monthly', + 'jetpack_business_monthly', + ), + 'support' => array( + 'jetpack_premium', + 'jetpack_business', + 'jetpack_personal', + 'jetpack_premium_monthly', + 'jetpack_business_monthly', + 'jetpack_personal_monthly', + ), + 'premium-themes' => array( + 'jetpack_business', + 'jetpack_business_monthly', + ), + 'vaultpress-security-scanning' => array( + 'jetpack_business', + 'jetpack_business_monthly', + ), + 'polldaddy' => array( + 'jetpack_business', + 'jetpack_business_monthly', + ), + ), + ), + ); + } + + private function get_changed_personal_plan() { + $changed_personal_plan = $this->get_personal_plan(); + + $changed_personal_plan['features']['available']['test_feature'] = array( 'jetpack_free' ); + return $changed_personal_plan; + } + + private function get_personal_plan() { + return array( + 'product_id' => 2005, + 'product_slug' => 'jetpack_personal', + 'product_name_short' => 'Personal', + 'expired' => false, + 'user_is_owner' => false, + 'is_free' => false, + 'features' => array( + 'active' => array( + 'support', + ), + 'available' => array( + 'akismet' => array( + 'jetpack_free', + 'jetpack_premium', + 'jetpack_business', + 'jetpack_premium_monthly', + 'jetpack_business_monthly', + ), + 'support' => array( + 'jetpack_free', + 'jetpack_premium', + 'jetpack_business', + 'jetpack_premium_monthly', + 'jetpack_business_monthly', + 'jetpack_personal_monthly', + ), + 'vaultpress-backups' => array( + 'jetpack_premium', + 'jetpack_business', + 'jetpack_premium_monthly', + 'jetpack_business_monthly', + ), + 'vaultpress-backup-archive' => array( + 'jetpack_premium', + 'jetpack_business', + 'jetpack_premium_monthly', + 'jetpack_business_monthly', + ), + 'vaultpress-storage-space' => array( + 'jetpack_premium', + 'jetpack_business', + 'jetpack_premium_monthly', + 'jetpack_business_monthly', + ), + 'vaultpress-automated-restores' => array( + 'jetpack_premium', + 'jetpack_business', + 'jetpack_premium_monthly', + 'jetpack_business_monthly', + ), + 'simple-payments' => array( + 'jetpack_premium', + 'jetpack_business', + 'jetpack_premium_monthly', + 'jetpack_business_monthly', + ), + 'premium-themes' => array( + 'jetpack_business', + 'jetpack_business_monthly', + ), + 'vaultpress-security-scanning' => array( + 'jetpack_business', + 'jetpack_business_monthly', + ), + 'polldaddy' => array( + 'jetpack_business', + 'jetpack_business_monthly', + ), + ), + ), + ); + } +} + +// phpcs:enable diff --git a/projects/packages/plugins-installer/.gitattributes b/projects/packages/plugins-installer/.gitattributes new file mode 100644 index 0000000000000..dd08c5ac8f82f --- /dev/null +++ b/projects/packages/plugins-installer/.gitattributes @@ -0,0 +1,15 @@ +# Files not needed to be distributed in the package. +.gitattributes export-ignore +.github/ export-ignore +package.json export-ignore + +# Files to include in the mirror repo, but excluded via gitignore +# Remember to end all directories with `/**` to properly tag every file. +# /src/js/example.min.js production-include + +# Files to exclude from the mirror repo, but included in the monorepo. +# Remember to end all directories with `/**` to properly tag every file. +.gitignore production-exclude +changelog/** production-exclude +phpunit.xml.dist production-exclude +tests/** production-exclude diff --git a/projects/packages/plugins-installer/.gitignore b/projects/packages/plugins-installer/.gitignore new file mode 100644 index 0000000000000..140fd587d2d52 --- /dev/null +++ b/projects/packages/plugins-installer/.gitignore @@ -0,0 +1,2 @@ +vendor/ +node_modules/ diff --git a/projects/packages/plugins-installer/.phpcs.dir.xml b/projects/packages/plugins-installer/.phpcs.dir.xml new file mode 100644 index 0000000000000..fd41c865e8f25 --- /dev/null +++ b/projects/packages/plugins-installer/.phpcs.dir.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/packages/plugins-installer/CHANGELOG.md b/projects/packages/plugins-installer/CHANGELOG.md new file mode 100644 index 0000000000000..3f2733da86b48 --- /dev/null +++ b/projects/packages/plugins-installer/CHANGELOG.md @@ -0,0 +1,17 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 0.1.0 - 2022-02-02 +### Added +- First version +- New functions to safely check plugin statuses + +### Changed +- Build: add missing mirror repo details, so package can be deployed. + +### Fixed +- Fix method logic diff --git a/projects/packages/plugins-installer/README.md b/projects/packages/plugins-installer/README.md new file mode 100644 index 0000000000000..b766b09457636 --- /dev/null +++ b/projects/packages/plugins-installer/README.md @@ -0,0 +1,20 @@ +# plugins-installer + +Handle installation of plugins from WP.org + +## How to install plugins-installer + +### Installation From Git Repo + +## Contribute + +## Get Help + +## Security + +Need to report a security vulnerability? Go to [https://automattic.com/security/](https://automattic.com/security/) or directly to our security bug bounty site [https://hackerone.com/automattic](https://hackerone.com/automattic). + +## License + +plugins-installer is licensed under [GNU General Public License v2 (or later)](./LICENSE.txt) + diff --git a/projects/packages/plugins-installer/changelog/.gitkeep b/projects/packages/plugins-installer/changelog/.gitkeep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/projects/packages/plugins-installer/composer.json b/projects/packages/plugins-installer/composer.json new file mode 100644 index 0000000000000..dd16fd5c3ae33 --- /dev/null +++ b/projects/packages/plugins-installer/composer.json @@ -0,0 +1,51 @@ +{ + "name": "automattic/jetpack-plugins-installer", + "description": "Handle installation of plugins from WP.org", + "type": "library", + "license": "GPL-2.0-or-later", + "require": { + "automattic/jetpack-a8c-mc-stats": "^1.4" + }, + "require-dev": { + "yoast/phpunit-polyfills": "1.0.3", + "automattic/jetpack-changelogger": "^3.0" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "scripts": { + "phpunit": [ + "./vendor/phpunit/phpunit/phpunit --colors=always" + ], + "test-coverage": [ + "php -dpcov.directory=. ./vendor/bin/phpunit --coverage-clover \"$COVERAGE_DIR/clover.xml\"" + ], + "test-php": [ + "@composer phpunit" + ] + }, + "repositories": [ + { + "type": "path", + "url": "../../packages/*", + "options": { + "monorepo": true + } + } + ], + "minimum-stability": "dev", + "prefer-stable": true, + "extra": { + "branch-alias": { + "dev-master": "0.1.x-dev" + }, + "mirror-repo": "Automattic/jetpack-plugins-installer", + "changelogger": { + "link-template": "https://github.com/Automattic/jetpack-plugins-installer/compare/v${old}...v${new}" + }, + "autotagger": true, + "textdomain": "jetpack-plugins-installer" + } +} diff --git a/projects/packages/plugins-installer/phpunit.xml.dist b/projects/packages/plugins-installer/phpunit.xml.dist new file mode 100644 index 0000000000000..3223c32458db2 --- /dev/null +++ b/projects/packages/plugins-installer/phpunit.xml.dist @@ -0,0 +1,14 @@ + + + + tests/php + + + + + + + src + + + diff --git a/projects/packages/plugins-installer/src/class-automatic-install-skin.php b/projects/packages/plugins-installer/src/class-automatic-install-skin.php new file mode 100644 index 0000000000000..ae129c5975b32 --- /dev/null +++ b/projects/packages/plugins-installer/src/class-automatic-install-skin.php @@ -0,0 +1,155 @@ +fs_connect( array( WP_CONTENT_DIR, WP_PLUGIN_DIR ) ); + if ( ! $result ) { + // set the string here since they are not available just yet. + $upgrader->generic_strings(); + $this->feedback( 'fs_unavailable' ); + } + } + + /** + * Overwrites the error function + * + * @param \WP_Error|mixed $error The error object. + */ + public function error( $error ) { + if ( is_wp_error( $error ) ) { + $this->feedback( $error ); + } + } + + /** + * Set the main error code. + * + * Don't set the process_failed as code since it is not that helpful unless we don't have one already set + * + * @param string $code The error code. + * @return void + */ + private function set_main_error_code( $code ) { + $this->main_error_code = ( 'process_failed' === $code && $this->main_error_code ? $this->main_error_code : $code ); + } + + /** + * Set the main error message. + * + * Don't set the process_failed as message since it is not that helpful unless we don't have one already set + * + * @param string $message The error message. + * @param string $code The error code. + * @return void + */ + private function set_main_error_message( $message, $code ) { + $this->main_error_message = ( 'process_failed' === $code && $this->main_error_message ? $this->main_error_message : $message ); + } + + /** + * Get the main error code + * + * @return string + */ + public function get_main_error_code() { + return $this->main_error_code; + } + + /** + * Get the main error message + * + * @return string + */ + public function get_main_error_message() { + return $this->main_error_message; + } + + /** + * Overwrites the feedback function + * + * @param string|array|WP_Error $data Data. + * @param mixed ...$args Optional text replacements. + */ + public function feedback( $data, ...$args ) { + + $current_error = null; + if ( is_wp_error( $data ) ) { + $this->set_main_error_code( $data->get_error_code() ); + $string = $data->get_error_message(); + } elseif ( is_array( $data ) ) { + return; + } else { + $string = $data; + } + + if ( ! empty( $this->upgrader->strings[ $string ] ) ) { + $this->set_main_error_code( $string ); + + $current_error = $string; + $string = $this->upgrader->strings[ $string ]; + } + + if ( strpos( $string, '%' ) !== false ) { + if ( ! empty( $args ) ) { + $string = vsprintf( $string, $args ); + } + } + + $string = trim( $string ); + $string = wp_kses( + $string, + array( + 'a' => array( + 'href' => true, + ), + 'br' => true, + 'em' => true, + 'strong' => true, + ) + ); + + $this->set_main_error_message( $string, $current_error ); + $this->messages[] = $string; + } +} diff --git a/projects/packages/plugins-installer/src/class-plugins-installer.php b/projects/packages/plugins-installer/src/class-plugins-installer.php new file mode 100644 index 0000000000000..bae23baa0a249 --- /dev/null +++ b/projects/packages/plugins-installer/src/class-plugins-installer.php @@ -0,0 +1,238 @@ +install( $zip_url ); + + if ( is_wp_error( $result ) ) { + $mc_stats->add( 'install-plugin', "fail-$slug" ); + return $result; + } + + $plugin = self::get_plugin_id_by_slug( $slug ); + $error_code = 'install_error'; + if ( ! $plugin ) { + $error = __( 'There was an error installing your plugin', 'jetpack-plugins-installer' ); + } + + if ( ! $result ) { + $error_code = $upgrader->skin->get_main_error_code(); + $message = $upgrader->skin->get_main_error_message(); + $error = $message ? $message : __( 'An unknown error occurred during installation', 'jetpack-plugins-installer' ); + } + + if ( ! empty( $error ) ) { + if ( 'download_failed' === $error_code ) { + // For backwards compatibility: versions prior to 3.9 would return no_package instead of download_failed. + $error_code = 'no_package'; + } + + $mc_stats->add( 'install-plugin', "fail-$slug" ); + return new WP_Error( $error_code, $error, 400 ); + } + + $mc_stats->add( 'install-plugin', "success-$slug" ); + return (array) $upgrader->skin->get_upgrade_messages(); + } + + /** + * Get WordPress.org zip download link from a plugin slug + * + * @param string $plugin_slug Plugin slug. + */ + protected static function generate_wordpress_org_plugin_download_link( $plugin_slug ) { + return "https://downloads.wordpress.org/plugin/$plugin_slug.latest-stable.zip"; + } + + /** + * Get the plugin ID (composed of the plugin slug and the name of the main plugin file) from a plugin slug. + * + * @param string $slug Plugin slug. + */ + public static function get_plugin_id_by_slug( $slug ) { + // Check if get_plugins() function exists. This is required on the front end of the + // site, since it is in a file that is normally only loaded in the admin. + if ( ! function_exists( 'get_plugins' ) ) { + require_once ABSPATH . 'wp-admin/includes/plugin.php'; + } + + /** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */ + $plugins = apply_filters( 'all_plugins', get_plugins() ); + if ( ! is_array( $plugins ) ) { + return false; + } + + foreach ( $plugins as $plugin_file => $plugin_data ) { + if ( self::get_slug_from_file_path( $plugin_file ) === $slug ) { + return $plugin_file; + } + } + + return false; + } + + /** + * Get the plugin slug from the plugin ID (composed of the plugin slug and the name of the main plugin file) + * + * @param string $plugin_file Plugin file (ID -- e.g. hello-dolly/hello.php). + */ + protected static function get_slug_from_file_path( $plugin_file ) { + // Similar to get_plugin_slug() method. + $slug = dirname( $plugin_file ); + if ( '.' === $slug ) { + $slug = preg_replace( '/(.+)\.php$/', '$1', $plugin_file ); + } + + return $slug; + } + + /** + * Get the activation status for a plugin. + * + * @since-jetpack 8.9.0 + * + * @param string $plugin_file The plugin file to check. + * @return string Either 'network-active', 'active' or 'inactive'. + */ + public static function get_plugin_status( $plugin_file ) { + if ( self::is_plugin_active_for_network( $plugin_file ) ) { + return 'network-active'; + } + + if ( self::is_plugin_active( $plugin_file ) ) { + return 'active'; + } + + return 'inactive'; + } + + /** + * Safely checks if the plugin is active + * + * @since $next-version$ + * + * @param string $plugin_file The plugin file to check. + * @return bool + */ + public static function is_plugin_active( $plugin_file ) { + self::ensure_plugin_functions_are_loaded(); + return is_plugin_active( $plugin_file ); + } + + /** + * Safely checks if the plugin is active for network + * + * @since $next-version$ + * + * @param string $plugin_file The plugin file to check. + * @return bool + */ + public static function is_plugin_active_for_network( $plugin_file ) { + self::ensure_plugin_functions_are_loaded(); + return is_plugin_active_for_network( $plugin_file ); + } + + /** + * Returns a list of all plugins in the site. + * + * @since-jetpack 8.9.0 + * @uses get_plugins() + * + * @return array + */ + public static function get_plugins() { + self::ensure_plugin_functions_are_loaded(); + /** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */ + $plugins = apply_filters( 'all_plugins', get_plugins() ); + + if ( is_array( $plugins ) && ! empty( $plugins ) ) { + foreach ( $plugins as $plugin_slug => $plugin_data ) { + $plugins[ $plugin_slug ]['active'] = in_array( + self::get_plugin_status( $plugin_slug ), + array( 'active', 'network-active' ), + true + ); + } + return $plugins; + } + + return array(); + } +} diff --git a/projects/packages/plugins-installer/tests/php/bootstrap.php b/projects/packages/plugins-installer/tests/php/bootstrap.php new file mode 100644 index 0000000000000..46763b04a2cdb --- /dev/null +++ b/projects/packages/plugins-installer/tests/php/bootstrap.php @@ -0,0 +1,11 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/packages/publicize/CHANGELOG.md b/projects/packages/publicize/CHANGELOG.md new file mode 100644 index 0000000000000..721294abd00ad --- /dev/null +++ b/projects/packages/publicize/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + diff --git a/projects/packages/publicize/README.md b/projects/packages/publicize/README.md new file mode 100644 index 0000000000000..f2da9fce18e02 --- /dev/null +++ b/projects/packages/publicize/README.md @@ -0,0 +1,3 @@ +# Publicize + +Publicize makes it easy to share your site’s posts on several social media networks automatically when you publish a new post. diff --git a/projects/packages/publicize/changelog/.gitkeep b/projects/packages/publicize/changelog/.gitkeep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/projects/packages/publicize/changelog/add-publicize-composer-package b/projects/packages/publicize/changelog/add-publicize-composer-package new file mode 100644 index 0000000000000..c12b9edd39cf9 --- /dev/null +++ b/projects/packages/publicize/changelog/add-publicize-composer-package @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Added an empty shell package diff --git a/projects/packages/publicize/composer.json b/projects/packages/publicize/composer.json new file mode 100644 index 0000000000000..253cb81cd2d95 --- /dev/null +++ b/projects/packages/publicize/composer.json @@ -0,0 +1,51 @@ +{ + "name": "automattic/jetpack-publicize", + "description": "Publicize makes it easy to share your site’s posts on several social media networks automatically when you publish a new post.", + "type": "library", + "license": "GPL-2.0-or-later", + "require": {}, + "require-dev": { + "yoast/phpunit-polyfills": "1.0.3", + "automattic/jetpack-changelogger": "^3.0" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "scripts": { + "phpunit": [ + "./vendor/phpunit/phpunit/phpunit --colors=always" + ], + "test-coverage": [ + "php -dpcov.directory=. ./vendor/bin/phpunit --coverage-clover \"$COVERAGE_DIR/clover.xml\"" + ], + "test-php": [ + "@composer phpunit" + ], + "build-production": "echo 'Add your build step to composer.json, please!'", + "build-development": "echo 'Add your build step to composer.json, please!'" + }, + "repositories": [ + { + "type": "path", + "url": "../../packages/*", + "options": { + "monorepo": true + } + } + ], + "minimum-stability": "dev", + "prefer-stable": true, + "extra": { + "autotagger": true, + "mirror-repo": "Automattic/jetpack-publicize", + "textdomain": "jetpack-publicize-pkg", + "changelogger": { + "link-template": "https://github.com/Automattic/jetpack-publicize/compare/v${old}...v${new}" + }, + "branch-alias": { + "dev-master": "0.1.x-dev" + } + } +} diff --git a/projects/packages/publicize/package.json b/projects/packages/publicize/package.json new file mode 100644 index 0000000000000..e14b3b8349666 --- /dev/null +++ b/projects/packages/publicize/package.json @@ -0,0 +1,29 @@ +{ + "private": true, + "name": "@automattic/jetpack-publicize", + "version": "0.1.0-alpha", + "description": "Publicize makes it easy to share your site’s posts on several social media networks automatically when you publish a new post.", + "homepage": "https://jetpack.com", + "bugs": { + "url": "https://github.com/Automattic/jetpack/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/Automattic/jetpack.git" + }, + "license": "GPL-2.0-or-later", + "author": "Automattic", + "scripts": { + "build": "echo 'Not implemented.", + "build-js": "echo 'Not implemented.", + "build-production": "echo 'Not implemented.", + "build-production-js": "echo 'Not implemented.", + "clean": "true" + }, + "devDependencies": {}, + "engines": { + "node": "^14.18.3 || ^16.13.2", + "pnpm": "^6.23.6", + "yarn": "use pnpm instead - see docs/yarn-upgrade.md" + } +} diff --git a/projects/packages/publicize/phpunit.xml.dist b/projects/packages/publicize/phpunit.xml.dist new file mode 100644 index 0000000000000..3223c32458db2 --- /dev/null +++ b/projects/packages/publicize/phpunit.xml.dist @@ -0,0 +1,14 @@ + + + + tests/php + + + + + + + src + + + diff --git a/projects/packages/publicize/src/example.php b/projects/packages/publicize/src/example.php new file mode 100644 index 0000000000000..b3715119facc5 --- /dev/null +++ b/projects/packages/publicize/src/example.php @@ -0,0 +1,8 @@ + $accepted_args, + 'function' => $cb, + ); + }; + // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable + $add_action = $add_filter; +} + +/** + * Adds the package slug and version to the package version tracker's data. + * + * @param array $package_versions The package version array. + * + * @return array The packge version array. + */ +function send_version_to_tracker( $package_versions ) { + $package_versions[ JETPACK_SEARCH_PKG__SLUG ] = JETPACK_SEARCH_PKG__VERSION; + return $package_versions; +} + +/** + * Whether Jetpack Search Package's version maps to a public release, or a development version. + */ +function is_development_version() { + return (bool) apply_filters( + 'jetpack_search_pkg_version', + ! preg_match( '/^\d+(\.\d+)+$/', JETPACK_SEARCH_PKG__VERSION ) + ); +} + +// Set up package version hook. +$add_filter( 'jetpack_package_versions', __NAMESPACE__ . '\send_version_to_tracker' ); + +if ( defined( 'WP_CLI' ) && \WP_CLI ) { + \WP_CLI::add_command( 'jetpack-search', __NAMESPACE__ . '\CLI' ); +} diff --git a/projects/packages/search/src/class-cli.php b/projects/packages/search/src/class-cli.php new file mode 100644 index 0000000000000..1f121f9a46a5e --- /dev/null +++ b/projects/packages/search/src/class-cli.php @@ -0,0 +1,35 @@ +auto_config_search(); + WP_CLI::line( 'Jetpack Search: auto config success!' ); + } catch ( \Exception $e ) { + WP_CLI::error( $e->getMessage() ); + } + } +} diff --git a/projects/packages/search/src/class-helper.php b/projects/packages/search/src/class-helper.php index 3e2829a37e6c6..fd82e91265901 100644 --- a/projects/packages/search/src/class-helper.php +++ b/projects/packages/search/src/class-helper.php @@ -712,11 +712,9 @@ public static function is_valid_locale( $locale ) { * @return string $script_version Version number. */ public static function get_asset_version( $file ) { - // TODO: Replace Jetpack:: invocation. - // TODO: Replace JETPACK__PLUGIN_DIR and JETPACK__VERSION. - return Jetpack::is_development_version() && file_exists( JETPACK__PLUGIN_DIR . $file ) - ? filemtime( JETPACK__PLUGIN_DIR . $file ) - : JETPACK__VERSION; + return is_development_version() && file_exists( JETPACK_SEARCH_PKG__DIR . $file ) + ? filemtime( JETPACK_SEARCH_PKG__DIR . $file ) + : JETPACK_SEARCH_PKG__VERSION; } /** diff --git a/projects/packages/search/src/class-plan.php b/projects/packages/search/src/class-plan.php index 49e54f082fe52..4748653058879 100644 --- a/projects/packages/search/src/class-plan.php +++ b/projects/packages/search/src/class-plan.php @@ -43,9 +43,12 @@ public function init_hooks() { */ public function get_plan_info_from_wpcom() { $blog_id = Jetpack_Options::get_option( 'id' ); - $response = Client::wpcom_json_api_request_as_user( + $response = Client::wpcom_json_api_request_as_blog( '/sites/' . $blog_id . '/jetpack-search/plan', - '2' + '2', + array(), + null, + 'wpcom' ); // store plan in options. @@ -84,7 +87,7 @@ public function has_jetpack_search_product() { */ public function supports_instant_search() { $plan_info = $this->get_plan_info(); - return isset( $plan_info['supports_instant_search'] ) && $plan_info['supports_instant_search']; + return ( isset( $plan_info['supports_instant_search'] ) && $plan_info['supports_instant_search'] ) || $this->has_jetpack_search_product(); } /** @@ -92,7 +95,7 @@ public function supports_instant_search() { */ public function supports_search() { $plan_info = $this->get_plan_info(); - return isset( $plan_info['supports_search'] ) && $plan_info['supports_search']; + return ( isset( $plan_info['supports_search'] ) && $plan_info['supports_search'] ) || $this->has_jetpack_search_product(); } /** diff --git a/projects/packages/search/src/customberg/class-customberg2.php b/projects/packages/search/src/customberg/class-customberg2.php index 4acee2f7a15b4..60d91dcc2eb20 100644 --- a/projects/packages/search/src/customberg/class-customberg2.php +++ b/projects/packages/search/src/customberg/class-customberg2.php @@ -98,11 +98,7 @@ public function jetpack_search_admin_page() { * Loads assets for the customization experience. */ public function load_assets() { - if ( defined( 'JETPACK_SEARCH_PACKAGE_DIRECTORY' ) ) { - $this->load_assets_with_parameters( - constant( 'JETPACK_SEARCH_PACKAGE_DIRECTORY' ) - ); - } + $this->load_assets_with_parameters( constant( 'JETPACK_SEARCH_PKG__DIR' ) ); } /** diff --git a/projects/packages/search/src/customberg/lib/_base-styles.scss b/projects/packages/search/src/customberg/lib/_base-styles.scss index f7e9e505161bf..008884d6c98f0 100644 --- a/projects/packages/search/src/customberg/lib/_base-styles.scss +++ b/projects/packages/search/src/customberg/lib/_base-styles.scss @@ -1,3 +1,4 @@ +@use "sass:math"; @import '@wordpress/base-styles/z-index'; // Fill in missing z-layer values from a more recent @wordpress/base-styles version. diff --git a/projects/packages/search/src/dashboard/class-dashboard.php b/projects/packages/search/src/dashboard/class-dashboard.php index d8bb144484027..86935a20d749a 100644 --- a/projects/packages/search/src/dashboard/class-dashboard.php +++ b/projects/packages/search/src/dashboard/class-dashboard.php @@ -47,7 +47,8 @@ class Dashboard { * @param Automattic\Jetpack\Search\Module_Control $module_control - Module_Control instance. */ public function __construct( $plan = null, $connection_manager = null, $module_control = null ) { - $this->plan = $plan ? $plan : new Plan(); + $this->plan = $plan ? $plan : new Plan(); + // TODO: 'jetpack-search' better to be the current plugin where the package is running. $this->connection_manager = $connection_manager ? $connection_manager : new Connection_Manager( 'jetpack-search' ); $this->module_control = $module_control ? $module_control : new Module_Control( $this->plan ); $this->plan->init_hooks(); diff --git a/projects/packages/search/src/dashboard/class-initial-state.php b/projects/packages/search/src/dashboard/class-initial-state.php index 25d16b582f17d..32622c0b76f2c 100644 --- a/projects/packages/search/src/dashboard/class-initial-state.php +++ b/projects/packages/search/src/dashboard/class-initial-state.php @@ -23,7 +23,7 @@ class Initial_State { protected $connection_manager; /** - * Search Moduel Control + * Search Module Control * * @var Module_Control */ @@ -36,6 +36,7 @@ class Initial_State { * @param Module_Control $module_control - Module control instance. */ public function __construct( $connection_manager = null, $module_control = null ) { + // TODO: 'jetpack-search' better to be the current plugin where the package is running. $this->connection_manager = $connection_manager ? $connection_manager : new Connection_Manager( 'jetpack-search' ); $this->module_control = $module_control ? $module_control : new Module_Control(); } @@ -80,6 +81,8 @@ public function get_initial_state() { 'search' => $this->module_control->is_active(), 'instant_search_enabled' => $this->module_control->is_instant_search_enabled(), ), + // phpcs:ignore WordPress.Security.NonceVerification.Recommended + 'features' => array_map( 'sanitize_text_field', explode( ',', $_GET['features'] ) ), ); } diff --git a/projects/packages/search/src/dashboard/components/dashboard/index.jsx b/projects/packages/search/src/dashboard/components/dashboard/index.jsx index 20dafb6411409..a577fde1b4536 100644 --- a/projects/packages/search/src/dashboard/components/dashboard/index.jsx +++ b/projects/packages/search/src/dashboard/components/dashboard/index.jsx @@ -19,6 +19,7 @@ import ModuleControl from 'components/module-control'; import MockedSearch from 'components/mocked-search'; import { STORE_ID } from 'store'; import NoticesList from 'components/global-notices'; +import RecordMeter from 'components/record-meter'; import 'scss/rna-styles.scss'; import './style.scss'; @@ -169,6 +170,10 @@ export default function SearchDashboard() { ); }; + const isRecordMeterEnabled = useSelect( select => + select( STORE_ID ).isFeatureEnabled( 'record-meter' ) + ); + return (
    { isLoading && ( @@ -179,6 +184,7 @@ export default function SearchDashboard() { { renderHeader() } { renderMockedSearchInterface() } { renderModuleControl() } + { isRecordMeterEnabled && } { renderFooter() } ) } diff --git a/projects/packages/search/src/dashboard/components/record-meter/index.jsx b/projects/packages/search/src/dashboard/components/record-meter/index.jsx new file mode 100644 index 0000000000000..3aad19b2091b4 --- /dev/null +++ b/projects/packages/search/src/dashboard/components/record-meter/index.jsx @@ -0,0 +1,28 @@ +/** + * External dependencies + */ +import React from 'react'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import './style.scss'; + +/** + * Generate Record Meter showing how many records the user has indexed + * + * @returns {React.Component} RecordMeter React component + */ +export default function RecordMeter() { + return ( +
    +
    +
    +

    { __( 'Your search records', 'jetpack-search-pkg' ) }

    +
    +
    +
    +
    + ); +} diff --git a/projects/packages/search/src/dashboard/components/record-meter/style.scss b/projects/packages/search/src/dashboard/components/record-meter/style.scss new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/projects/packages/search/src/dashboard/store/reducer/feature.js b/projects/packages/search/src/dashboard/store/reducer/feature.js new file mode 100644 index 0000000000000..f48b1801d45e9 --- /dev/null +++ b/projects/packages/search/src/dashboard/store/reducer/feature.js @@ -0,0 +1,5 @@ +const features = ( state = [] ) => { + return state; +}; + +export default features; diff --git a/projects/packages/search/src/dashboard/store/reducer/index.js b/projects/packages/search/src/dashboard/store/reducer/index.js index cf7340059e8f3..8b739110d9c3a 100644 --- a/projects/packages/search/src/dashboard/store/reducer/index.js +++ b/projects/packages/search/src/dashboard/store/reducer/index.js @@ -10,6 +10,7 @@ import siteData from './site-data'; import userData from './user-data'; import jetpackSettings from './jetpack-settings'; import sitePlan from './site-plan'; +import features from './feature'; import notices from 'components/global-notices/store/reducer'; const reducer = combineReducers( { @@ -17,6 +18,7 @@ const reducer = combineReducers( { jetpackSettings, sitePlan, userData, + features, notices, } ); diff --git a/projects/packages/search/src/dashboard/store/selectors/feature.js b/projects/packages/search/src/dashboard/store/selectors/feature.js new file mode 100644 index 0000000000000..b9beed07d12ce --- /dev/null +++ b/projects/packages/search/src/dashboard/store/selectors/feature.js @@ -0,0 +1,7 @@ +const featureSelectors = { + isFeatureEnabled: ( state, feature ) => { + return Array.isArray( state.features ) && state.features.includes( feature ); + }, +}; + +export default featureSelectors; diff --git a/projects/packages/search/src/dashboard/store/selectors/index.js b/projects/packages/search/src/dashboard/store/selectors/index.js index 8020ea192ae9a..73306f156503c 100644 --- a/projects/packages/search/src/dashboard/store/selectors/index.js +++ b/projects/packages/search/src/dashboard/store/selectors/index.js @@ -6,6 +6,7 @@ import jetpackSettingSelectors from './jetpack-settings'; import sitePlanSelectors from './site-plan'; import userDataSelectors from './user-data'; import noticeSelectors from 'components/global-notices/store/selectors'; +import featureSelectors from './feature'; const selectors = { ...siteDataSelectors, @@ -13,6 +14,7 @@ const selectors = { ...sitePlanSelectors, ...userDataSelectors, ...noticeSelectors, + ...featureSelectors, }; export default selectors; diff --git a/projects/packages/search/src/initializers/class-jetpack-initializer.php b/projects/packages/search/src/initializers/class-jetpack-initializer.php index 28a087b88f39d..3a70c6b0e1451 100644 --- a/projects/packages/search/src/initializers/class-jetpack-initializer.php +++ b/projects/packages/search/src/initializers/class-jetpack-initializer.php @@ -7,6 +7,8 @@ namespace Automattic\Jetpack\Search; +use Automattic\Jetpack\Connection\Manager as Connection_Manager; + /** * Initializer for the main Jetpack plugin. Instantiate to enable Jetpack Search functionality. */ @@ -34,13 +36,8 @@ public static function initialize() { return; } - // TODO: Port the search widget to package for milestone 2. - require_once JETPACK__PLUGIN_DIR . 'modules/widgets/search.php'; - - /** - * Location of built Jetpack Search assets, does not include trailing slash. - */ - define( 'JETPACK_SEARCH_PACKAGE_DIRECTORY', dirname( dirname( __DIR__ ) ) ); + // registers Jetpack Search widget. + add_action( 'widgets_init', array( 'Automattic\Jetpack\Search\Jetpack_Initializer', 'jetpack_search_widget_init' ) ); if ( Options::is_instant_enabled() ) { // Enable the instant search experience. @@ -68,7 +65,8 @@ public static function initialize() { * Check if site has been connected. */ public static function is_connected() { - return \Jetpack::is_connection_ready(); + // TODO: 'jetpack-search' better to be the current plugin where the package is running. + return ( new Connection_Manager( 'jetpack-search' ) )->is_connected(); } /** @@ -77,4 +75,21 @@ public static function is_connected() { public static function is_search_supported() { return ( new Plan() )->supports_search(); } + + /** + * Register the widget if Jetpack Search is available and enabled. + */ + public static function jetpack_search_widget_init() { + if ( + ! self::is_connected() + || ! self::is_search_supported() + || ! ( new Module_Control() )->is_active() + ) { + return; + } + + // There won't be multiple widgets registered when Search stand alone plugin registers it again. + // Because the function tests the hash of the class, if they are the same, just register again. + register_widget( 'Automattic\Jetpack\Search\Search_Widget' ); + } } diff --git a/projects/packages/search/src/instant-search/class-instant-search.php b/projects/packages/search/src/instant-search/class-instant-search.php index cf832d000b744..ae1cdf3b7b0d7 100644 --- a/projects/packages/search/src/instant-search/class-instant-search.php +++ b/projects/packages/search/src/instant-search/class-instant-search.php @@ -70,11 +70,7 @@ public function init_hooks() { * Loads assets for Jetpack Instant Search Prototype featuring Search As You Type experience. */ public function load_assets() { - if ( defined( 'JETPACK_SEARCH_PACKAGE_DIRECTORY' ) ) { - $this->load_assets_with_parameters( - constant( 'JETPACK_SEARCH_PACKAGE_DIRECTORY' ) - ); - } + $this->load_assets_with_parameters( constant( 'JETPACK_SEARCH_PKG__DIR' ) ); } /** @@ -217,7 +213,7 @@ public function instant_api( array $args ) { $request_args = array( 'timeout' => 10, - 'user-agent' => "WordPress/{$wp_version} | Jetpack/" . constant( 'JETPACK__VERSION' ), + 'user-agent' => "WordPress/{$wp_version} | Jetpack-Search/" . constant( 'JETPACK_SEARCH_PKG__VERSION' ), ); $request = wp_remote_get( esc_url_raw( $service_url ), $request_args ); @@ -313,10 +309,6 @@ public function get_search_aggregations_results() { * @since 8.3.0 */ public function auto_config_search() { - if ( ! current_user_can( 'edit_theme_options' ) ) { - return; - } - // Set default result format to "expanded". update_option( Options::OPTION_PREFIX . 'result_format', Options::RESULT_FORMAT_EXPANDED ); @@ -367,6 +359,7 @@ public function auto_config_overlay_sidebar_widgets() { $widget_opt_name = Helper::get_widget_option_name(); $widget_options = get_option( $widget_opt_name, array() ); foreach ( $widget_options as $id => $w ) { + $id = intval( $id ); if ( $id >= $next_id ) { $next_id = $id + 1; } diff --git a/projects/packages/search/src/instant-search/components/search-result-expanded.jsx b/projects/packages/search/src/instant-search/components/search-result-expanded.jsx index d23c99005ce04..fcbdddb48a2af 100644 --- a/projects/packages/search/src/instant-search/components/search-result-expanded.jsx +++ b/projects/packages/search/src/instant-search/components/search-result-expanded.jsx @@ -77,7 +77,7 @@ export default function SearchResultExpanded( props ) {
    { firstImage ? ( { firstImage ? ( module_control = new Module_Control(); parent::__construct( Helper::FILTER_WIDGET_BASE, /** This filter is documented in modules/widgets/facebook-likebox.php */ apply_filters( 'jetpack_widget_name', $name ), array( 'classname' => 'jetpack-filters widget_search', - 'description' => __( 'Instant search and filtering to help visitors quickly find relevant answers and explore your site.', 'jetpack' ), + 'description' => __( 'Instant search and filtering to help visitors quickly find relevant answers and explore your site.', 'jetpack-search-pkg' ), ) ); @@ -111,7 +98,7 @@ public function __construct( $name = null ) { * @since 6.3 */ public function is_search_active() { - return Jetpack::is_module_active( 'search' ); + return $this->module_control->is_active(); } /** @@ -120,7 +107,7 @@ public function is_search_active() { * @since 6.3 */ public function activate_search() { - Jetpack::activate_module( 'search', false, false ); + return $this->module_control->activate(); } /** @@ -129,30 +116,33 @@ public function activate_search() { * @since 5.7.0 */ public function widget_admin_setup() { - wp_enqueue_style( - 'widget-jetpack-search-filters', - plugins_url( 'search/css/search-widget-admin-ui.css', __FILE__ ), - array(), - JETPACK__VERSION - ); - // Register jp-tracks and jp-tracks-functions. Tracking::register_tracks_functions_scripts(); - wp_register_script( + Assets::register_script( 'jetpack-search-widget-admin', - plugins_url( 'search/js/search-widget-admin.js', __FILE__ ), - array( 'jquery', 'jquery-ui-sortable', 'jp-tracks-functions' ), - JETPACK__VERSION, - false + 'js/search-widget-admin.js', + __FILE__, + array( + 'in_footer' => true, + 'textdomain' => 'jetpack-search-pkg', + 'css_path' => 'css/search-widget-admin-ui.css', + 'dependencies' => array( 'jquery', 'jquery-ui-sortable', 'jp-tracks-functions' ), + ) ); + // TODO: 'jetpack-search' better to be the current plugin where the package is running. + $dotcom_data = ( new Connection_Manager( 'jetpack-search' ) )->get_connected_user_data(); + wp_localize_script( 'jetpack-search-widget-admin', 'jetpack_search_filter_admin', array( 'defaultFilterCount' => self::DEFAULT_FILTER_COUNT, - 'tracksUserData' => Jetpack_Tracks_Client::get_connected_user_tracks_identity(), + 'tracksUserData' => ! empty( $dotcom_data ) ? array( + 'userid' => $dotcom_data['ID'], + 'username' => $dotcom_data['login'], + ) : false, 'tracksEventData' => array( 'is_customizer' => (int) is_customize_preview(), ), @@ -165,7 +155,7 @@ public function widget_admin_setup() { ) ); - wp_enqueue_script( 'jetpack-search-widget-admin' ); + Assets::enqueue_script( 'jetpack-search-widget-admin' ); } /** @@ -177,51 +167,48 @@ public function enqueue_frontend_scripts() { if ( ! is_active_widget( false, false, $this->id_base, true ) || Options::is_instant_enabled() ) { return; } - - wp_enqueue_script( + Assets::register_script( 'jetpack-search-widget', - plugins_url( 'search/js/search-widget.js', __FILE__ ), - array(), - JETPACK__VERSION, - true - ); - - wp_enqueue_style( - 'jetpack-search-widget', - plugins_url( 'search/css/search-widget-frontend.css', __FILE__ ), - array(), - JETPACK__VERSION + 'js/search-widget.js', + __FILE__, + array( + 'in_footer' => true, + 'textdomain' => 'jetpack-search-pkg', + // Jetpack the plugin would concatenated the style with other styles and minimize. And the style would be dequeued from WP. + // @see https://github.com/Automattic/jetpack/blob/b3de78dce3d88b0d9b283282a5b04515245c8057/projects/plugins/jetpack/tools/builder/frontend-css.js#L52. + // @see https://github.com/Automattic/jetpack/blob/bb1b6a9a9cfa98600441f8fa31c9f9c4ef9a04a5/projects/plugins/jetpack/class.jetpack.php#L106. + 'css_path' => 'css/search-widget-frontend.css', + ) ); + Assets::enqueue_script( 'jetpack-search-widget' ); } /** * Get the list of valid sort types/orders. * - * @since 5.8.0 - * * @return array The sort orders. + * @since 5.8.0 */ private function get_sort_types() { return array( - 'relevance|DESC' => is_admin() ? esc_html__( 'Relevance (recommended)', 'jetpack' ) : esc_html__( 'Relevance', 'jetpack' ), - 'date|DESC' => esc_html__( 'Newest first', 'jetpack' ), - 'date|ASC' => esc_html__( 'Oldest first', 'jetpack' ), + 'relevance|DESC' => is_admin() ? esc_html__( 'Relevance (recommended)', 'jetpack-search-pkg' ) : esc_html__( 'Relevance', 'jetpack-search-pkg' ), + 'date|DESC' => esc_html__( 'Newest first', 'jetpack-search-pkg' ), + 'date|ASC' => esc_html__( 'Oldest first', 'jetpack-search-pkg' ), ); } /** * Callback for an array_filter() call in order to only get filters for the current widget. * - * @see Jetpack_Search_Widget::widget() - * - * @since 5.7.0 - * * @param array $item Filter item. * * @return bool Whether the current filter item is for the current widget. + * @see Search_Widget::widget() + * + * @since 5.7.0 */ public function is_for_current_widget( $item ) { - return isset( $item['widget_id'] ) && $this->id == $item['widget_id']; // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison + return isset( $item['widget_id'] ) && $this->id == $item['widget_id']; // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual } /** @@ -230,9 +217,8 @@ public function is_for_current_widget( $item ) { * This is meant to provide backwards-compatibility for VIP, and other professional plan users, that manually * configured filters via `Automattic\Jetpack\Search\Classic_Search::set_filters()`. * - * @since 5.7.0 - * * @return bool Whether the widget should display site-wide filters or not. + * @since 5.7.0 */ public function should_display_sitewide_filters() { $filter_widgets = get_option( 'widget_jetpack-search-filters' ); @@ -277,9 +263,9 @@ public function jetpack_search_populate_defaults( $instance ) { /** * Populates the instance array with appropriate default values. * - * @since 8.6.0 * @param array $instance Previously saved values from database. * @return array Instance array with default values approprate for instant search + * @since 8.6.0 */ public function populate_defaults_for_instant_search( $instance ) { return wp_parse_args( @@ -294,10 +280,9 @@ public function populate_defaults_for_instant_search( $instance ) { /** * Responsible for rendering the widget on the frontend. * - * @since 5.0.0 - * * @param array $args Widgets args supplied by the theme. * @param array $instance The current widget instance. + * @since 5.0.0 */ public function widget( $args, $instance ) { $instance = $this->jetpack_search_populate_defaults( $instance ); @@ -307,7 +292,7 @@ public function widget( $args, $instance ) { ?>
    @@ -330,21 +315,20 @@ public function widget( $args, $instance ) { /** * Render the non-instant frontend widget. * - * @since 8.3.0 - * * @param array $args Widgets args supplied by the theme. * @param array $instance The current widget instance. + * @since 8.3.0 */ public function widget_non_instant( $args, $instance ) { $display_filters = false; // Search instance must have been initialized before widget render. - if ( is_search() && Automattic\Jetpack\Search\Classic_Search::instance() ) { + if ( is_search() && Classic_Search::instance() ) { if ( Helper::should_rerun_search_in_customizer_preview() ) { - Automattic\Jetpack\Search\Classic_Search::instance()->update_search_results_aggregations(); + Classic_Search::instance()->update_search_results_aggregations(); } - $filters = Automattic\Jetpack\Search\Classic_Search::instance()->get_filters(); + $filters = Classic_Search::instance()->get_filters(); if ( ! Helper::are_filters_by_widget_disabled() && ! $this->should_display_sitewide_filters() ) { $filters = array_filter( $filters, array( $this, 'is_for_current_widget' ) ); @@ -375,11 +359,10 @@ public function widget_non_instant( $args, $instance ) { * * @module search * - * @since 5.7.0 - * * @param string $title The widget's title * @param string $args['before_title'] The HTML tag to display before the title * @param string $args['after_title'] The HTML tag to display after the title + *@since 5.7.0 */ do_action( 'jetpack_search_render_filters_widget_title', $title, $args['before_title'], $args['after_title'] ); } @@ -391,14 +374,14 @@ public function widget_non_instant( $args, $instance ) { // we need to dynamically inject the sort field into the search box when the search box is enabled, and display // it separately when it's not. if ( ! empty( $instance['search_box_enabled'] ) ) { - Automattic\Jetpack\Search\Template_Tags::render_widget_search_form( $instance['post_types'], $orderby, $order ); + Template_Tags::render_widget_search_form( $instance['post_types'], $orderby, $order ); } if ( ! empty( $instance['search_box_enabled'] ) && ! empty( $instance['user_sort_enabled'] ) ) : ?>

    @@ -794,12 +767,12 @@ class="jetpack-search-filters-widget__sort-controls-enabled" /> - +

    - + false ), 'objects' ) as $post_type ) : ?>

    - +

    @@ -918,11 +890,10 @@ class="widefat" * and native PHP (server-side). This helper function allows for easy rendering * of attributes in both formats. * - * @since 5.8.0 - * * @param string $name Attribute name. * @param string $value Attribute value. * @param bool $is_template Whether this is for an Underscore template or not. + * @since 5.8.0 */ private function render_widget_attr( $name, $value, $is_template ) { echo $is_template ? "<%= $name %>" : esc_attr( $value ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped @@ -933,12 +904,11 @@ private function render_widget_attr( $name, $value, $is_template ) { * and native PHP (server-side). This helper function allows for easy rendering * of the "selected" attribute in both formats. * - * @since 5.8.0 - * * @param string $name Attribute name. * @param string $value Attribute value. * @param string $compare Value to compare to the attribute value to decide if it should be selected. * @param bool $is_template Whether this is for an Underscore template or not. + * @since 5.8.0 */ private function render_widget_option_selected( $name, $value, $compare, $is_template ) { $compare_js = rawurlencode( $compare ); @@ -950,10 +920,9 @@ private function render_widget_option_selected( $name, $value, $compare, $is_tem * * We use this method for two purposes - rendering the fields server-side, and also rendering a script template for Underscore. * - * @since 5.7.0 - * * @param array $filter The filter to render. * @param bool $is_template Whether this is for an Underscore template or not. + * @since 5.7.0 */ public function render_widget_edit_filter( $filter, $is_template = false ) { $args = wp_parse_args( @@ -975,16 +944,16 @@ public function render_widget_edit_filter( $filter, $is_template = false ) {

    @@ -993,7 +962,7 @@ public function render_widget_edit_filter( $filter, $is_template = false ) {

    @@ -1039,13 +1008,13 @@ public function render_widget_edit_filter( $filter, $is_template = false ) {

    @@ -1053,7 +1022,7 @@ public function render_widget_edit_filter( $filter, $is_template = false ) {

    - +

    id ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison + if ( $checkout_id != $buffer->id ) { // phpcs:ignore Universal.Operators.StrictComparisons.LooseNotEqual return new WP_Error( 'buffer_mismatch', 'The buffer you checked in was not checked out' ); } diff --git a/projects/packages/sync/src/modules/class-plugins.php b/projects/packages/sync/src/modules/class-plugins.php index b244834f54699..84c45b6de857e 100644 --- a/projects/packages/sync/src/modules/class-plugins.php +++ b/projects/packages/sync/src/modules/class-plugins.php @@ -205,7 +205,7 @@ private function get_plugin_info( $slug ) { $plugins = get_plugins(); // Get the most up to date info. if ( isset( $plugins[ $slug ] ) ) { return array_merge( array( 'slug' => $slug ), $plugins[ $slug ] ); - }; + } // Try grabbing the info from before the update. return isset( $this->plugins[ $slug ] ) ? array_merge( array( 'slug' => $slug ), $this->plugins[ $slug ] ) : array( 'slug' => $slug ); } diff --git a/projects/packages/terms-of-service/CHANGELOG.md b/projects/packages/terms-of-service/CHANGELOG.md index f9b91333e7dd0..b714f4d9b570b 100644 --- a/projects/packages/terms-of-service/CHANGELOG.md +++ b/projects/packages/terms-of-service/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.9.19] - 2022-01-25 +### Changed +- Updated package dependencies. + ## [1.9.18] - 2022-01-04 ### Changed - Switch to pcov for code coverage. @@ -182,6 +186,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Package: Create new TOS package +[1.9.19]: https://github.com/Automattic/jetpack-terms-of-service/compare/v1.9.18...v1.9.19 [1.9.18]: https://github.com/Automattic/jetpack-terms-of-service/compare/v1.9.17...v1.9.18 [1.9.17]: https://github.com/Automattic/jetpack-terms-of-service/compare/v1.9.16...v1.9.17 [1.9.16]: https://github.com/Automattic/jetpack-terms-of-service/compare/v1.9.15...v1.9.16 diff --git a/projects/packages/terms-of-service/changelog/add-visitor-status b/projects/packages/terms-of-service/changelog/add-visitor-status deleted file mode 100644 index c47cb18e82997..0000000000000 --- a/projects/packages/terms-of-service/changelog/add-visitor-status +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: changed - -Updated package dependencies. diff --git a/projects/packages/terms-of-service/changelog/update-project-scripts-no-install b/projects/packages/terms-of-service/changelog/update-project-scripts-no-install deleted file mode 100644 index f45fac5ea79e2..0000000000000 --- a/projects/packages/terms-of-service/changelog/update-project-scripts-no-install +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: removed -Comment: Tooling only: Build and test scripts no longer call `composer install` or `pnpm install`. - - diff --git a/projects/packages/tracking/CHANGELOG.md b/projects/packages/tracking/CHANGELOG.md index 970ab75772cab..92dcfaa26965d 100644 --- a/projects/packages/tracking/CHANGELOG.md +++ b/projects/packages/tracking/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.14.1] - 2022-01-25 +### Changed +- Updated package dependencies. + ## [1.14.0] - 2022-01-04 ### Changed - Switch to pcov for code coverage. @@ -206,6 +210,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Create package for Jetpack Tracking +[1.14.1]: https://github.com/Automattic/jetpack-tracking/compare/v1.14.0...v1.14.1 [1.14.0]: https://github.com/Automattic/jetpack-tracking/compare/v1.13.19...v1.14.0 [1.13.19]: https://github.com/Automattic/jetpack-tracking/compare/v1.13.18...v1.13.19 [1.13.18]: https://github.com/Automattic/jetpack-tracking/compare/v1.13.17...v1.13.18 diff --git a/projects/packages/tracking/changelog/add-fancy-eslint-ignore b/projects/packages/tracking/changelog/add-fancy-eslint-ignore deleted file mode 100644 index afe95e481cf32..0000000000000 --- a/projects/packages/tracking/changelog/add-fancy-eslint-ignore +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: changed -Comment: Hack eslint config to use `.gitignore` and per-dir `.eslintignore`. - - diff --git a/projects/packages/tracking/changelog/add-visitor-status b/projects/packages/tracking/changelog/add-visitor-status deleted file mode 100644 index c47cb18e82997..0000000000000 --- a/projects/packages/tracking/changelog/add-visitor-status +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: changed - -Updated package dependencies. diff --git a/projects/packages/tracking/changelog/update-project-scripts-no-install b/projects/packages/tracking/changelog/update-project-scripts-no-install deleted file mode 100644 index f45fac5ea79e2..0000000000000 --- a/projects/packages/tracking/changelog/update-project-scripts-no-install +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: removed -Comment: Tooling only: Build and test scripts no longer call `composer install` or `pnpm install`. - - diff --git a/projects/packages/tracking/composer.json b/projects/packages/tracking/composer.json index ea086a77f7ed4..1b4d2e003bc87 100644 --- a/projects/packages/tracking/composer.json +++ b/projects/packages/tracking/composer.json @@ -4,7 +4,7 @@ "type": "jetpack-library", "license": "GPL-2.0-or-later", "require": { - "automattic/jetpack-assets": "^1.16", + "automattic/jetpack-assets": "^1.17", "automattic/jetpack-options": "^1.14", "automattic/jetpack-status": "^1.10", "automattic/jetpack-terms-of-service": "^1.9" diff --git a/projects/packages/waf/.gitattributes b/projects/packages/waf/.gitattributes new file mode 100644 index 0000000000000..9f76af3f06e7e --- /dev/null +++ b/projects/packages/waf/.gitattributes @@ -0,0 +1,16 @@ +# Files not needed to be distributed in the package. +.gitattributes export-ignore +.github/ export-ignore +package.json export-ignore + +# Files to include in the mirror repo, but excluded via gitignore +# Remember to end all directories with `/**` to properly tag every file. +# /src/js/example.min.js production-include + +# Files to exclude from the mirror repo, but included in the monorepo. +# Remember to end all directories with `/**` to properly tag every file. +.gitignore production-exclude +changelog/** production-exclude +phpunit.xml.dist production-exclude +.phpcs.dir.xml production-exclude +tests/** production-exclude diff --git a/projects/packages/waf/.gitignore b/projects/packages/waf/.gitignore new file mode 100644 index 0000000000000..140fd587d2d52 --- /dev/null +++ b/projects/packages/waf/.gitignore @@ -0,0 +1,2 @@ +vendor/ +node_modules/ diff --git a/projects/packages/waf/.phpcs.dir.xml b/projects/packages/waf/.phpcs.dir.xml new file mode 100644 index 0000000000000..0b414c4ced0b6 --- /dev/null +++ b/projects/packages/waf/.phpcs.dir.xml @@ -0,0 +1,32 @@ + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + diff --git a/projects/packages/waf/CHANGELOG.md b/projects/packages/waf/CHANGELOG.md new file mode 100644 index 0000000000000..03a962f457f66 --- /dev/null +++ b/projects/packages/waf/CHANGELOG.md @@ -0,0 +1,6 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). diff --git a/projects/packages/waf/README.md b/projects/packages/waf/README.md new file mode 100644 index 0000000000000..c72f0cf32aa6f --- /dev/null +++ b/projects/packages/waf/README.md @@ -0,0 +1,9 @@ +# waf + +Tools to assist with the Jetpack Web Application Firewall + +Need to report a security vulnerability? Go to [https://automattic.com/security/](https://automattic.com/security/) or directly to our security bug bounty site [https://hackerone.com/automattic](https://hackerone.com/automattic). + +## License + +waf is licensed under [GNU General Public License v2 (or later)](./LICENSE.txt) diff --git a/projects/packages/waf/changelog/.gitkeep b/projects/packages/waf/changelog/.gitkeep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/projects/packages/waf/changelog/add-waf-package b/projects/packages/waf/changelog/add-waf-package new file mode 100644 index 0000000000000..22245f547f57f --- /dev/null +++ b/projects/packages/waf/changelog/add-waf-package @@ -0,0 +1,4 @@ +Significance: major +Type: added + +added Initial version diff --git a/projects/packages/waf/changelog/update-ignored-config-waf b/projects/packages/waf/changelog/update-ignored-config-waf new file mode 100644 index 0000000000000..6a66cee0d2688 --- /dev/null +++ b/projects/packages/waf/changelog/update-ignored-config-waf @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Core: do not ship .phpcs.dir.xml in production builds. diff --git a/projects/packages/waf/composer.json b/projects/packages/waf/composer.json new file mode 100644 index 0000000000000..6978dd41e99fe --- /dev/null +++ b/projects/packages/waf/composer.json @@ -0,0 +1,50 @@ +{ + "name": "automattic/jetpack-waf", + "description": "Tools to assist with the Jetpack Web Application Firewall", + "type": "library", + "license": "GPL-2.0-or-later", + "require": { + "wikimedia/aho-corasick": "^1.0" + }, + "require-dev": { + "yoast/phpunit-polyfills": "1.0.3", + "automattic/jetpack-changelogger": "^3.0" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "scripts": { + "phpunit": [ + "./vendor/phpunit/phpunit/phpunit --colors=always" + ], + "test-coverage": [ + "php -dpcov.directory=. ./vendor/bin/phpunit --coverage-clover \"$COVERAGE_DIR/clover.xml\"" + ], + "test-php": [ + "@composer phpunit" + ] + }, + "repositories": [ + { + "type": "path", + "url": "../../packages/*", + "options": { + "monorepo": true + } + } + ], + "minimum-stability": "dev", + "prefer-stable": true, + "extra": { + "autotagger": true, + "mirror-repo": "Automattic/jetpack-waf", + "changelogger": { + "link-template": "https://github.com/Automattic/jetpack-waf/compare/v${old}...v${new}" + }, + "branch-alias": { + "dev-master": "0.1.x-dev" + } + } +} diff --git a/projects/packages/waf/phpunit.xml.dist b/projects/packages/waf/phpunit.xml.dist new file mode 100644 index 0000000000000..3223c32458db2 --- /dev/null +++ b/projects/packages/waf/phpunit.xml.dist @@ -0,0 +1,14 @@ + + + + tests/php + + + + + + + src + + + diff --git a/projects/packages/waf/src/class-waf-operators.php b/projects/packages/waf/src/class-waf-operators.php new file mode 100644 index 0000000000000..3ad7b537e6674 --- /dev/null +++ b/projects/packages/waf/src/class-waf-operators.php @@ -0,0 +1,286 @@ += intval( $test ) + ? $input + : false; + } + + /** + * Returns true if the input value is greater than the test value. + * If either value cannot be converted to an int it will be treated as 0. + * + * @param mixed $input Input. + * @param mixed $test Test. + * @return int|false + */ + public function gt( $input, $test ) { + return intval( $input ) > intval( $test ) + ? $input + : false; + } + + /** + * Returns true if the input value is less than or equal to the test value. + * If either value cannot be converted to an int it will be treated as 0. + * + * @param mixed $input Input. + * @param mixed $test Test. + * @return int|false + */ + public function le( $input, $test ) { + return intval( $input ) <= intval( $test ) + ? $input + : false; + } + + /** + * Returns true if the input value is less than the test value. + * If either value cannot be converted to an int it will be treated as 0. + * + * @param mixed $input Input. + * @param mixed $test Test. + * @return int|false + */ + public function lt( $input, $test ) { + return intval( $input ) < intval( $test ) + ? $input + : false; + } + + /** + * Returns false. + * + * @return false + */ + public function no_match() { + return false; + } + + /** + * Uses a multi-string matching algorithm to search through $input for a number of given $words. + * + * @param string $input Input. + * @param string[] $words \AhoCorasick\MultiStringMatcher $matcher. + * @return string[]|false Returns the words that were found in $input, or FALSE if no words were found. + */ + public function pm( $input, $words ) { + $results = $this->get_multi_string_matcher( $words )->searchIn( $input ); + + return isset( $results[0] ) + ? array_map( + function ( $r ) { + return $r[1]; }, + $results + ) + : false; + } + + /** + * The last-used pattern-matching algorithm. + * + * @var array + */ + private $last_multi_string_matcher = array( null, null ); + + /** + * Creates a matcher that uses the Aho-Corasick algorithm to efficiently find a number of words in an input string. + * Caches the last-used matcher so that the same word list doesn't have to be compiled multiple times. + * + * @param string[] $words Words. + * @return \AhoCorasick\MultiStringMatcher + */ + private function get_multi_string_matcher( $words ) { + // only create a new matcher entity if we don't have one already for this word list. + if ( $this->last_multi_string_matcher[0] !== $words ) { + $this->last_multi_string_matcher = array( $words, new \AhoCorasick\MultiStringMatcher( $words ) ); + } + + return $this->last_multi_string_matcher[1]; + } + + /** + * Performs a regular expression match on the input subject using the given pattern. + * Returns false if the pattern does not match, or the substring(s) of the input + * that were matched by the pattern. + * + * @param string $subject Subject. + * @param string $pattern Pattern. + * @return string[]|false + */ + public function rx( $subject, $pattern ) { + $matched = preg_match( $pattern, $subject, $matches ); + return 1 === $matched + ? $matches + : false; + } + + /** + * Returns true if the given input string matches the test string. + * + * @param string $input Input. + * @param string $test Test. + * @return string|false + */ + public function streq( $input, $test ) { + return $input === $test + ? $test + : false; + } + + /** + * Returns true. + * + * @param string $input Input. + * @return bool + */ + public function unconditional_match( $input ) { + return $input; + } + + /** + * Checks to see if the input string only contains characters within the given byte range + * + * @param string $input Input. + * @param array $valid_range Valid range. + * @return string + */ + public function validate_byte_range( $input, $valid_range ) { + if ( '' === $input ) { + // an empty string is considered "valid". + return false; + } + $i = 0; + while ( isset( $input[ $i ] ) ) { + $n = ord( $input[ $i ] ); + if ( $n < $valid_range['min'] || $n > $valid_range['max'] ) { + return $input[ $i ]; + } + $valid = false; + foreach ( $valid_range['range'] as $b ) { + if ( $n === $b || is_array( $b ) && $n >= $b[0] && $n <= $b[1] ) { + $valid = true; + break; + } + } + if ( ! $valid ) { + return $input[ $i ]; + } + $i++; + } + + // if there weren't any invalid bytes, return false. + return false; + } + + /** + * Returns true if the input value is found anywhere inside the test value + * (i.e. the inverse of @contains) + * + * @param mixed $input Input. + * @param mixed $test Test. + * @return string|false + */ + public function within( $input, $test ) { + if ( '' === $input || '' === $test ) { + return false; + } + + return stripos( $test, $input ) !== false + ? $input + : false; + } +} diff --git a/projects/packages/waf/src/class-waf-rule-compiler.php b/projects/packages/waf/src/class-waf-rule-compiler.php new file mode 100644 index 0000000000000..9ffc18c3a29a0 --- /dev/null +++ b/projects/packages/waf/src/class-waf-rule-compiler.php @@ -0,0 +1,517 @@ +php[] = sprintf( + "\$rule = (object) array( 'id' => %s, 'reason' => %s, 'tags' => %s );", + var_export( $rule['id'], true ), + isset( $rule['reason'] ) ? $this->expand_macro( $rule['reason'] ) : "''", + var_export( isset( $rule['tags'] ) ? array_map( 'strtolower', $rule['tags'] ) : array(), true ) + ); + $rule_php = $this->compile_rule( $rule ); + $this->add_rule( $rule['id'], isset( $rule['tags'] ) ? $rule['tags'] : array(), $rule_php ); + } elseif ( isset( $rule['actions'] ) ) { + // this is an actions-only rule. + $rule_php = $this->compile_actions( $rule['actions'] ); + $this->add_rule( $rule['id'], isset( $rule['tags'] ) ? $rule['tags'] : array(), $rule_php ); + } elseif ( isset( $rule['marker'] ) ) { + // this is a marker. + $this->add_marker( $rule['marker'] ); + } else { + var_dump( 'UNKNOWN RULE:', $rule ); + exit; + } + } + // check to see if there are any leftover markers. + if ( ! empty( $this->marker_map ) ) { + var_dump( 'Marker Map Is Not Empty!', $this->marker_map ); + exit; + } + } + + /** + * Write rules to file. + * + * @param string $filepath File path. + * @throws \Exception If file writing fails. + */ + public function write_to_file( $filepath ) { + $php_code = implode( PHP_EOL, $this->php ); + + $wp_filesystem = jpwaf_init_filesystem(); + if ( ! $wp_filesystem ) { + throw new \Exception( 'No filesystem available' ); + } + // ensure the folder exists. + if ( ! $wp_filesystem->is_writable( dirname( $filepath ) ) ) { + $wp_filesystem->mkdir( dirname( $filepath ) ); + } + if ( ! $wp_filesystem->put_contents( $filepath, $php_code ) ) { + throw new \Exception( "Failed writing to: $filepath" ); + } + + return true; + } + + /** + * Add rule. + * + * @param string $rule_id Rule id. + * @param array $rule_tags Rule tags. + * @param array $rule_php Rule php. + */ + private function add_rule( $rule_id, $rule_tags, $rule_php ) { + // wrap in a "if rule removed" check (only if a previous rule might be removing this rule). + if ( $this->check_if_maybe_will_change_at_runtime( 'rule', $rule_id, $rule_tags ) ) { + array_unshift( $rule_php, 'if(!$waf->rule_removed($rule->id, $rule->tags)) {' ); + $rule_php[] = '}'; + } + $this->php = array_merge( $this->php, $rule_php ); + // add a marker in case another rules wants to skipAfter this rule. + $this->add_marker( $rule_id ); + } + + /** + * Add marker. + * + * @param string $label Label. + */ + private function add_marker( $label ) { + if ( isset( $this->marker_map[ $label ] ) ) { + $this->php[] = $this->marker_map[ $label ] . ": // $label"; + unset( $this->marker_map[ $label ] ); + } + } + + /** + * Compile actions. + * + * @param array $actions Actions. + */ + private function compile_actions( $actions ) { + return array_map( + function ( $act ) { + switch ( $act['name'] ) { + case 'set_var': + // key, op, value. + $k = $this->expand_macro( strtolower( $act['key'] ) ); + if ( 'x' === $act['op'] ) { + return sprintf( + '$waf->unset_var(%s);', + $k + ); + } else { + $v = $this->expand_macro( $act['value'] ); + $fn = 'set_var'; + if ( '+' === $act['op'] ) { + $fn = 'inc_var'; + } elseif ( '-' === $act['op'] ) { + $fn = 'dec_var'; + } + return sprintf( + '$waf->%s(%s,%s);', + $fn, + $k, + $v + ); + } + case 'remove_target': + // make a note (for compiler use) other rules' + // targets may be updated based on ID or tag. + $this->maybe_will_change_at_runtime( + 'target', + $act['prop'], + $act['value'] + ); + // add a runtime line. + return sprintf( + '$waf->flag_target_for_removal(%s,%s,%s,%s);', + var_export( $act['prop'], true ), + var_export( strtolower( $act['value'] ), true ), + var_export( strtolower( $act['targetName'] ), true ), + var_export( $act['targetProp'], true ) + ); + case 'remove_rule': + // make a note (for compiler use) other rules + // may be removed based on ID or tag. + $this->maybe_will_change_at_runtime( 'rule', $act['prop'], $act['value'] ); + // add a runtime line. + return sprintf( + '$waf->flag_rule_for_removal(%s,%s);', + var_export( $act['prop'], true ), + var_export( $act['value'], true ) + ); + case 'set_reason': + return sprintf( + '$rule->reason = %s;', + $this->expand_macro( $act['reason'] ) + ); + default: + var_dump( $act ); + exit; + } + }, + $actions + ); + } + + /** + * Compile rule. + * + * @param array $rule Rule. + */ + private function compile_rule( $rule ) { + // compile the the disruptive action. + $disruptive_action = ''; + if ( $rule['action'] ) { + switch ( $rule['action']['name'] ) { + case 'block': + case 'deny': + case 'drop': + $disruptive_action = sprintf( + 'return $waf->block(%s,$rule->id,$rule->reason,%s);', + var_export( $rule['action']['name'], true ), + var_export( $rule['action']['status'], true ) + ); + break; + case 'allow': + $disruptive_action = 'return;'; + break; + case 'redirect': + $disruptive_action = sprintf( + 'return $waf->redirect($rule->id,%s);', + var_export( $rule['action']['url'], true ) + ); + break; + case 'skipAfter': + $disruptive_action = sprintf( + 'goto %s;', + $this->get_marker_label( $rule['action']['target'] ) + ); + break; + } + } + // compile the expressions. + return $this->compile_expression( + $rule['expression'], + $rule['id'], + isset( $rule['tags'] ) ? $rule['tags'] : array(), + $disruptive_action ? array( $disruptive_action ) : array(), + $rule + ); + } + + /** + * Add marker. + * + * @param array $expression Expression. + * @param string $rule_id Rule id. + * @param array $rule_tags Rule tags. + * @param array $other_actions Other actions. + * @param array $rule Rule. + */ + private function compile_expression( $expression, $rule_id, $rule_tags, $other_actions, $rule ) { + $php_lines = array(); + if ( 'and' === $expression['operator'] ) { + $php_lines = array_reduce( + array_reverse( $expression['expressions'] ), + function ( $lines, $expr ) use ( $rule_id, $rule_tags, $rule ) { + return $this->compile_expression( $expr, $rule_id, $rule_tags, $lines, $rule ); + }, + $other_actions + ); + } elseif ( 'or' === $expression['operator'] ) { + die( 'or!' ); + } else { + // Simple Expression + // prepare the targets. + $targets = array(); + foreach ( $expression['targets'] as $t ) { + $t2 = $t; + if ( isset( $t2['only'] ) ) { + foreach ( $t2['only'] as $k => $v ) { + $t2['only'][ $k ] = '/' === $v[0] + ? $v + : strtolower( $v ); + } + } + if ( isset( $t2['except'] ) ) { + foreach ( $t2['except'] as $k => $v ) { + $t2['except'][ $k ] = '/' === $v[0] + ? $v + : strtolower( $v ); + } + } + unset( $t2['name'] ); + $targets[ strtolower( $t['name'] ) ] = $t2; + } + $targets = var_export( $targets, true ); + // if the targets for this rule may have been changed, then pass the targets + // to a method to update them at runtime. + if ( $this->check_if_maybe_will_change_at_runtime( 'target', $rule_id, $rule_tags ) ) { + $targets = sprintf( + '$waf->update_targets(%s, $rule->id, $rule->tags)', + $targets + ); + } + // prepare the operation. + $op_name = strtolower( $expression['operator'] ); + $op_value = $expression['value']; + // these operators support macro expansion, which we can do some of ahead of time. + // the rest have their values directly printed out in PHP. + $expand_macro_operators = array( + 'beginswith', + 'contains', + 'containsword', + 'endswith', + 'eq', + 'ge', + 'gt', + 'le', + 'lt', + 'rsub', + 'streq', + 'within', + '', + ); + if ( in_array( $op_name, $expand_macro_operators, true ) ) { + $op_value = $this->expand_macro( $op_value ); + } else { + if ( 'validatebyterange' === $op_name ) { + $op_value = self::parse_byte_range( $op_value ); + } + $op_value = var_export( $op_value, true ); + } + // write the condition. + $php_lines[] = sprintf( + 'if($waf->match_targets(%s,%s,%s,%s,%s,%s)) {', + var_export( isset( $rule['transforms'] ) ? $rule['transforms'] : array(), true ), + $targets, + var_export( $op_name, true ), + $op_value, + $expression['not'] ? 'true' : 'false', + $expression['capture'] ? 'true' : 'false' + ); + + // add the actions. + $php_lines = array_merge( + $php_lines, + $this->compile_actions( + isset( $expression['actions'] ) + ? $expression['actions'] + : array() + ), + $other_actions + ); + // close the condition block. + $php_lines[] = '}'; + } + + return $php_lines; + } + + /** + * Expand macro. + * + * @param string $v Value. + */ + private function expand_macro( $v ) { + if ( '' === $v ) { + return "''"; + } + $matched = array(); + $replaced = preg_replace_callback( + '/%\{[\w\.\-]+\}/', + function ( $m ) use ( &$matched ) { + $k = strtolower( substr( $m[0], 2, -1 ) ); + if ( 1 === preg_match( '/^(tx|ip)\./', $k ) ) { + $matched[] = '$waf->get_var(' . var_export( $k, true ) . ')'; + } elseif ( strpos( $k, 'request_headers.' ) === 0 ) { + $matched[] = "\$waf->meta('headers', " . var_export( substr( $k, 16 ), true ) . ')'; + } else { + switch ( $k ) { + case 'matched_var': + $matched[] = '$waf->matched_var'; + break; + case 'matched_var_name': + $matched[] = '$waf->matched_var_name'; + break; + case 'remote_addr': + case 'request_line': + $matched[] = '$waf->meta(\'' . $k . '\')'; + break; + case 'rule.msg': + case 'rule.reason': + $matched[] = '$rule->reason'; + break; + case 'reqbody_error_msg': + $matched[] = ''; + // these are unsupported macros from modsecurity. + break; + default: + $matched[] = ''; + var_dump( 'Unknown macro:', $m ); + } + } + return "\r\f\r"; + }, + $v + ); + $parts = array_filter( + preg_split( '/\r+/', $replaced ), + function ( $s ) { + return '' !== $s; } + ); + $parts = array_map( + function ( $s ) use ( &$matched ) { + return "\f" === $s + ? array_shift( $matched ) + : var_export( $s, true ); + }, + $parts + ); + $parts = array_filter( + $parts, + function ( $s ) { + return '' !== $s; + } + ); + $string = implode( '.', $parts ); + if ( preg_match( '/\.$/', $string ) ) { + var_dump( + $v, + $parts, + array_filter( + $parts, + function ( $p ) { + return null !== $p; + } + ), + $string + ); + exit; + } + + return $string; + } + + /** + * Maybe will change at runtime. + * + * @param string $type Type. + * @param string $prop Prop. + * @param string $value Value. + */ + private function maybe_will_change_at_runtime( $type, $prop, $value ) { + $key = strtolower( "$type/$prop/$value" ); + $this->maybe_will_change[ $key ] = true; + } + + /** + * Check if maybe will change at runtime. + * + * @param string $type Type. + * @param string $rule_id Rule id. + * @param array $rule_tags Rule tags. + */ + private function check_if_maybe_will_change_at_runtime( $type, $rule_id, $rule_tags ) { + // check to see if the rule ID might be targeted by a runtime action. + if ( isset( $this->maybe_will_change[ "$type/id/$rule_id" ] ) ) { + return true; + } + // check to see if one of the tags might be targeted by a runtime action. + foreach ( $rule_tags as $tag ) { + if ( isset( $this->maybe_will_change[ "$type/tag/$tag" ] ) ) { + return true; + } + } + // None of the rule's attributes are being targeted. + return false; + } + + /** + * Get marker label. + * + * @param string $name Name. + */ + private function get_marker_label( $name ) { + if ( ! isset( $this->marker_map[ $name ] ) ) { + $this->marker_map[ $name ] = preg_replace( '/\W/', '_', uniqid( 'marker_', true ) ); + } + return $this->marker_map[ $name ]; + } + + /** + * Given an array of byte numbers and/or ranges of numbers, compile into a data structure that will + * be easier to evaluate at runtime. + * + * @param mixed $ranges Ranges. + * @return array + */ + public static function parse_byte_range( $ranges ) { + $range = array(); + $min = PHP_INT_MAX; + $max = 0; + foreach ( $ranges as $b ) { + if ( false === strpos( $b, '-' ) ) { + $b = intval( $b ); + $min = min( $b, $min ); + $max = max( $b, $max ); + $range[] = $b; + } else { + list( $b0, $b1 ) = preg_split( '/\s*-\s*/', $b ); + $b0 = intval( $b0 ); + $b1 = intval( $b1 ); + $min = min( $b0, $min ); + $max = max( $b1, $max ); + $range[] = array( $b0, $b1 ); + } + } + + return array( + 'min' => $min, + 'max' => $max, + 'range' => $range, + ); + } +} diff --git a/projects/packages/waf/src/class-waf-runtime.php b/projects/packages/waf/src/class-waf-runtime.php new file mode 100644 index 0000000000000..b4af3dbdad069 --- /dev/null +++ b/projects/packages/waf/src/class-waf-runtime.php @@ -0,0 +1,643 @@ + array(), + 'tag' => array(), + ); + + /** + * Targets to remove. + * + * @var array[] + */ + private $targets_to_remove = array( + 'id' => array(), + 'tag' => array(), + ); + + /** + * Constructor method. + * + * @param WafTransforms $transforms Transforms. + * @param WafOperators $operators Operators. + */ + public function __construct( $transforms, $operators ) { + $this->transforms = $transforms; + $this->operators = $operators; + } + + /** + * Rule removed method. + * + * @param string $id Ids. + * @param string[] $tags Tags. + */ + public function rule_removed( $id, $tags ) { + if ( isset( $this->rules_to_remove['id'][ $id ] ) ) { + return true; + } + foreach ( $tags as $tag ) { + if ( isset( $this->rules_to_remove['tag'][ $tag ] ) ) { + return true; + } + } + return false; + } + + /** + * Update Targets. + * + * @param array $targets Targets. + * @param string $rule_id Rule id. + * @param string[] $rule_tags Rule tags. + */ + public function update_targets( $targets, $rule_id, $rule_tags ) { + $updates = array(); + // look for target updates based on the rule's ID. + if ( isset( $this->targets_to_remove['id'][ $rule_id ] ) ) { + foreach ( $this->targets_to_remove['id'][ $rule_id ] as $name => $props ) { + $updates[] = array( $name, $props ); + } + } + // look for target updates based on the rule's tags. + foreach ( $rule_tags as $tag ) { + if ( isset( $this->targets_to_remove['tag'][ $tag ] ) ) { + foreach ( $this->targets_to_remove['tag'][ $tag ] as $name => $props ) { + $updates[] = array( $name, $props ); + } + } + } + // apply any found target updates. + + foreach ( $updates as list( $name, $props ) ) { + if ( isset( $targets[ $name ] ) ) { + // we only need to remove targets that exist. + if ( true === $props ) { + // if the entire target is being removed, remove it. + unset( $targets[ $name ] ); + } else { + // otherwise just mark single props to ignore. + $targets[ $name ]['except'] = array_merge( + isset( $targets[ $name ]['except'] ) ? $targets[ $name ]['except'] : array(), + $props + ); + } + } + } + return $targets; + } + + /** + * Return TRUE if at least one of the targets matches the rule. + * + * @param string[] $transforms One of the transform methods defined in the JetpackWafTransforms class. + * @param mixed $targets Targets. + * @param string $match_operator Match operator. + * @param mixed $match_value Match value. + * @param bool $match_not Match not. + * @param bool $capture Capture. + * @return bool + */ + public function match_targets( $transforms, $targets, $match_operator, $match_value, $match_not, $capture = false ) { + $this->matched_vars = array(); + $this->matched_var_names = array(); + $this->matched_var = ''; + $this->matched_var_name = ''; + $match_found = false; + + // get values. + $values = $this->normalize_targets( $targets ); + + // apply transforms. + foreach ( $transforms as $t ) { + foreach ( $values as &$v ) { + $v['value'] = $this->transforms->$t( $v['value'] ); + } + } + + // pass each target value to the operator to find any that match. + $matched = array(); + $captures = array(); + foreach ( $values as $v ) { + $match = $this->operators->{$match_operator}( $v['value'], $match_value ); + $did_match = false !== $match; + if ( $match_not !== $did_match ) { + // If either: + // - rule is negated ("not" flag set) and the target was not matched + // - rule not negated and the target was matched + // then this is considered a match. + $match_found = true; + $this->matched_var_names[] = $v['source']; + $this->matched_vars[] = $v['value']; + $this->matched_var_name = end( $this->matched_var_names ); + $this->matched_var = end( $this->matched_vars ); + $matched[] = array( $v, $match ); + // Set any captured matches into state if the rule has the "capture" flag. + if ( $capture ) { + $captures = is_array( $match ) ? $match : array( $match ); + foreach ( array_slice( $captures, 0, 10 ) as $i => $c ) { + $this->set_var( "tx.$i", $c ); + } + } + } + } + + return $match_found; + } + + /** + * Block. + * + * @param string $action Action. + * @param string $rule_id Rule id. + * @param string $reason Block reason. + * @param int $status_code Http status code. + */ + public function block( $action, $rule_id, $reason, $status_code = 403 ) { + if ( ! $reason ) { + $reason = "rule $rule_id"; + } + jpwaf_write_blocklog( $rule_id, $reason ); + error_log( "Jetpack WAF Blocked Request\t$action\t$rule_id\t$status_code\t$reason" ); + header( "X-JetpackWAF-Blocked: $status_code $reason" ); + if ( defined( 'JETPACK_WAF_MODE' ) && 'normal' === JETPACK_WAF_MODE ) { + header( $_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden', true, $status_code ); + die( "rule $rule_id" ); + } + } + + /** + * Redirect. + * + * @param string $rule_id Rule id. + * @param string $url Url. + */ + public function redirect( $rule_id, $url ) { + error_log( "Jetpack WAF Redirected Request.\tRule:$rule_id\t$url" ); + header( "Location: $url" ); + exit; + } + + /** + * Flag rule for removal. + * + * @param string $prop Prop. + * @param string $value Value. + */ + public function flag_rule_for_removal( $prop, $value ) { + if ( 'id' === $prop ) { + $this->rules_to_remove['id'][ $value ] = true; + } else { + $this->rules_to_remove['tag'][ $value ] = true; + } + } + + /** + * Flag target for removal. + * + * @param string $id_or_tag Id or tag. + * @param string $id_or_tag_value Id or tag value. + * @param string $name Name. + * @param string $prop Prop. + */ + public function flag_target_for_removal( $id_or_tag, $id_or_tag_value, $name, $prop = null ) { + if ( null === $prop ) { + $this->targets_to_remove[ $id_or_tag ][ $id_or_tag_value ][ $name ] = true; + } else { + if ( + ! isset( $this->targets_to_remove[ $id_or_tag ][ $id_or_tag_value ][ $name ] ) + // if the entire target is already being removed then it would be redundant to remove a single property. + || true !== $this->targets_to_remove[ $id_or_tag ][ $id_or_tag_value ][ $name ] + ) { + $this->targets_to_remove[ $id_or_tag ][ $id_or_tag_value ][ $name ][] = $prop; + } + } + } + + /** + * Get variable value. + * + * @param string $key Key. + */ + public function get_var( $key ) { + return isset( $this->state[ $key ] ) + ? $this->state[ $key ] + : ''; + } + + /** + * Set variable value. + * + * @param string $key Key. + * @param string $value Value. + */ + public function set_var( $key, $value ) { + $this->state[ $key ] = $value; + } + + /** + * Increment variable. + * + * @param string $key Key. + * @param mixed $value Value. + */ + public function inc_var( $key, $value ) { + if ( ! isset( $this->state[ $key ] ) ) { + $this->state[ $key ] = 0; + } + $this->state[ $key ] += floatval( $value ); + } + + /** + * Decrement variable. + * + * @param string $key Key. + * @param mixed $value Value. + */ + public function dec_var( $key, $value ) { + if ( ! isset( $this->state[ $key ] ) ) { + $this->state[ $key ] = 0; + } + $this->state[ $key ] -= floatval( $value ); + } + + /** + * Unset variable. + * + * @param string $key Key. + */ + public function unset_var( $key ) { + unset( $this->state[ $key ] ); + } + + /** + * Meta. + * + * @param string $key Key. + * @param string $prop Prop. + */ + public function meta( $key, $prop = false ) { + if ( ! isset( $this->metadata[ $key ] ) ) { + $value = null; + switch ( $key ) { + case 'headers': + $value = array(); + foreach ( $_SERVER as $k => $v ) { + $k = strtolower( $k ); + if ( 'http_' === substr( $k, 0, 5 ) ) { + $value[ $this->normalizeHeaderName( substr( $k, 0, 5 ) ) ] = $v; + } elseif ( 'content_type' === $k ) { + $value['content-type'] = $v; + } elseif ( 'content_length' === $k ) { + $value['content-length'] = $v; + } + } + $value['content-type'] = ( ! isset( $value['content-type'] ) || '' === $value['content-type'] ) + // default Content-Type per RFC 7231 section 3.1.5.5. + ? 'application/octet-stream' + : $value['content-type']; + $value['content-length'] = ( isset( $value['content-length'] ) && '' !== $value['content-length'] ) + ? $value['content-length'] + // if the content-length header is missing, default it to zero. + : '0'; + break; + case 'remote_addr': + $value = ''; + if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) { + $value = $_SERVER['HTTP_CLIENT_IP']; + } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) { + $value = $_SERVER['HTTP_X_FORWARDED_FOR']; + } elseif ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) { + $value = $_SERVER['REMOTE_ADDR']; + } + break; + case 'request_method': + $value = empty( $_SERVER['REQUEST_METHOD'] ) + ? 'GET' + : $_SERVER['REQUEST_METHOD']; + break; + case 'request_protocol': + $value = empty( $_SERVER['SERVER_PROTOCOL'] ) + ? ( empty( $_SERVER['HTTPS'] ) ? 'HTTP' : 'HTTPS' ) + : $_SERVER['SERVER_PROTOCOL']; + break; + case 'request_uri': + $value = isset( $_SERVER['REQUEST_URI'] ) + ? $_SERVER['REQUEST_URI'] + : ''; + break; + case 'request_uri_raw': + $value = ( isset( $_SERVER['https'] ) ? 'https://' : 'http://' ) . $_SERVER['SERVER_NAME'] . $this->meta( 'request_uri' ); + break; + case 'request_filename': + $value = strtok( + isset( $_SERVER['REQUEST_URI'] ) + ? $_SERVER['REQUEST_URI'] + : '', + '?' + ); + break; + case 'request_line': + $value = sprintf( + '%s %s %s', + $this->meta( 'request_method' ), + $this->meta( 'request_uri' ), + $this->meta( 'request_protocol' ) + ); + break; + case 'request_basename': + $value = basename( $this->meta( 'request_filename' ) ); + break; + case 'request_body': + $value = file_get_contents( 'php://input' ); + break; + case 'query_string': + $value = isset( $_SERVER['QUERY_STRING'] ) ? $_SERVER['QUERY_STRING'] : ''; + } + $this->metadata[ $key ] = $value; + } + + return false === $prop + ? $this->metadata[ $key ] + : ( isset( $this->metadata[ $key ][ $prop ] ) ? $this->metadata[ $key ][ $prop ] : '' ); + } + + /** + * State values. + * + * @param string $prefix Prefix. + */ + private function state_values( $prefix ) { + $output = array(); + $len = strlen( $prefix ); + foreach ( $this->state as $k => $v ) { + if ( 0 === stripos( $k, $prefix ) ) { + $output[ substr( $k, $len ) ] = $v; + } + } + + return $output; + } + + /** + * Change a string to all lowercase and replace spaces and underscores with dashes. + * + * @param string $name Name. + * @return string + */ + public function normalize_header_name( $name ) { + return str_replace( array( ' ', '_' ), '-', strtolower( $name ) ); + } + + /** + * Normalize targets. + * + * @param array $targets Targets. + */ + public function normalize_targets( $targets ) { + $return = array(); + foreach ( $targets as $k => $v ) { + $count_only = isset( $v['count'] ); + $only = isset( $v['only'] ) ? $v['only'] : array(); + $except = isset( $v['except'] ) ? $v['except'] : array(); + $_k = strtolower( $k ); + switch ( $_k ) { + case 'request_headers': + $only = array_map( + function ( $t ) { + return '/' === $t[0] ? $t : $this->normalize_header_name( $t ); + }, + $only + ); + $except = array_map( + function ( $t ) { + return '/' === $t[0] ? $t : $this->normalize_header_name( $t ); + }, + $except + ); + $this->normalize_array_target( $this->meta( 'headers' ), $only, $except, $k, $return, $count_only ); + continue 2; + case 'request_headers_names': + $this->normalize_array_target( array_keys( $this->meta( 'headers' ) ), array(), array(), $k, $return, $count_only ); + continue 2; + case 'request_method': + case 'request_protocol': + case 'request_uri': + case 'request_uri_raw': + case 'request_filename': + case 'remote_addr': + case 'request_basename': + case 'request_body': + case 'query_string': + case 'request_line': + $v = $this->meta( $_k ); + break; + case 'tx': + case 'ip': + $this->normalize_array_target( $this->state_values( "$k." ), $only, $except, $k, $return, $count_only ); + continue 2; + case 'request_cookies': + $this->normalize_array_target( $_COOKIE, $only, $except, $k, $return, $count_only ); + continue 2; + case 'request_cookies_names': + $this->normalize_array_target( array_keys( $_COOKIE ), array(), array(), $k, $return, $count_only ); + continue 2; + case 'args': + $this->normalize_array_target( $_REQUEST, $only, $except, $k, $return, $count_only ); + continue 2; + case 'args_names': + $this->normalize_array_target( array_keys( $_REQUEST ), array(), array(), $k, $return, $count_only ); + continue 2; + case 'args_get': + $this->normalize_array_target( $_GET, $only, $except, $k, $return, $count_only ); + continue 2; + case 'args_get_names': + $this->normalize_array_target( array_keys( $_GET ), array(), array(), $k, $return, $count_only ); + continue 2; + case 'args_post': + $this->normalize_array_target( $_POST, $only, $except, $k, $return, $count_only ); + continue 2; + case 'args_post_names': + $this->normalize_array_target( array_keys( $_POST ), array(), array(), $k, $return, $count_only ); + continue 2; + case 'files': + $names = array_map( + function ( $f ) { + return $f['name']; + }, + $_FILES + ); + $this->normalize_array_target( $names, $only, $except, $k, $return, $count_only ); + continue 2; + case 'files_names': + $this->normalize_array_target( array_keys( $_FILES ), $only, $except, $k, $return, $count_only ); + continue 2; + default: + var_dump( 'Unknown target', $k, $v ); + exit; + } + $return[] = array( + 'name' => $k, + 'value' => $v, + 'source' => $k, + ); + } + + return $return; + } + + /** + * Normalize array target. + * + * @param array $source Source. + * @param array $only Only. + * @param array $excl Excl. + * @param string $name Name. + * @param array $results Results. + * @param bool $count_only Count only. + */ + private function normalize_array_target( $source, $only, $excl, $name, &$results, $count_only ) { + $output = array(); + $has_only = isset( $only[0] ); + $has_excl = isset( $excl[0] ); + + if ( $has_only ) { + foreach ( $only as $prop ) { + if ( isset( $source[ $prop ] ) && $this->key_matches( $prop, $only ) ) { + $output[ $prop ] = $source[ $prop ]; + } + } + } else { + $output = $source; + } + + if ( $has_excl ) { + foreach ( array_keys( $output ) as $k ) { + if ( $this->key_matches( $k, $excl ) ) { + unset( $output[ $k ] ); + } + } + } + + // todo: normalize nested arrays in values?? + if ( $count_only ) { + $results[] = array( + 'name' => $name, + 'value' => count( $output ), + 'source' => '&' . $name, + ); + } else { + foreach ( $output as $tk => $tv ) { + $results[] = array( + 'name' => $tk, + 'value' => $tv, + 'source' => "$name:$tk", + ); + } + } + + return $results; + } + + /** + * Key matches. + * + * @param string $input Input. + * @param array $patterns Patterns. + */ + private function key_matches( $input, $patterns ) { + foreach ( $patterns as $p ) { + if ( '/' === $p[0] ) { + if ( 1 === preg_match( $p, $input ) ) { + return true; + } + } else { + if ( 0 === strcasecmp( $p, $input ) ) { + return true; + } + } + } + + return false; + } +} diff --git a/projects/packages/waf/src/class-waf-transforms.php b/projects/packages/waf/src/class-waf-transforms.php new file mode 100644 index 0000000000000..496a1fa315a9f --- /dev/null +++ b/projects/packages/waf/src/class-waf-transforms.php @@ -0,0 +1,342 @@ +normalize_path( str_replace( '\\', '/', $value ) ); + } + + /** + * Removes all NUL bytes from input. + * + * @param string $value value to be filtered. + * @return string + */ + public function remove_nulls( $value ) { + return str_replace( "\x0", '', $value ); + } + + /** + * Remove all whitespace characters from input. + * + * @param string $value value to be filtered. + * @return string + */ + public function remove_whitespace( $value ) { + return preg_replace( '/\s/', '', $value ); + } + + /** + * Replaces each occurrence of a C-style comment (/ * ... * /) with a single space. + * Unterminated comments will also be replaced with a space. However, a standalone termination of a comment (* /) will not be acted upon. + * + * @param string $value value to be filtered. + * @return string + */ + public function replace_comments( $value ) { + $value = preg_replace( '~/\*.*?\*/|/\*.*?$~Ds', ' ', $value ); + return explode( '/*', $value, 2 )[0]; + } + + /** + * Removes common comments chars (/ *, * /, --, #). + * + * @param string $value value to be filtered. + * @return string + */ + public function remove_comments_char( $value ) { + return preg_replace( '~/*|*/|--|#|//~', '', $value ); + } + + /** + * Replaces each NUL byte in input with a space. + * + * @param string $value value to be filtered. + * @return string + */ + public function replace_nulls( $value ) { + return str_replace( "\x0", ' ', $value ); + } + + /** + * Decode a URL-encoded input string. + * + * @param string $value value to be decoded. + * @return string + */ + public function url_decode( $value ) { + return urldecode( $value ); + } + + /** + * Decode a URL-encoded input string. + * + * @param string $value value to be decoded. + * @return string + */ + public function url_decode_uni( $value ) { + error_log( 'JETPACKWAF TRANSFORM NOT IMPLEMENTED: urlDecodeUni' ); + return $value; + } + + /** + * Decode a json encoded input string. + * + * @param string $value value to be decoded. + * @return string + */ + public function js_decode( $value ) { + error_log( 'JETPACKWAF TRANSFORM NOT IMPLEMENTED: jsDecode' ); + return $value; + } + + /** + * Convert all characters to uppercase. + * + * @param string $value value to be encoded. + * @return string + */ + public function uppercase( $value ) { + return strtoupper( $value ); + } + + /** + * Calculate a SHA1 hash from the input string. + * + * @param mixed $value value to be hashed. + * @return string + */ + public function sha1( $value ) { + return sha1( $value, true ); + } + + /** + * Remove whitespace from the left side of the input string. + * + * @param string $value value to be trimmed. + * @return string + */ + public function trim_left( $value ) { + return ltrim( $value ); + } + + /** + * Remove whitespace from the right side of the input string. + * + * @param string $value value to be trimmed. + * @return string + */ + public function trim_right( $value ) { + return rtrim( $value ); + } + + /** + * Remove whitespace from both sides of the input string. + * + * @param string $value value to be trimmed. + * @return string + */ + public function trim( $value ) { + return trim( $value ); + } + + /** + * Convert utf-8 characters to unicode characters + * + * @param string $value value to be encoded. + * @return string + */ + public function utf8_to_unicode( $value ) { + return preg_replace( '/\\\u(?=[a-f0-9]{4})/', '%u', substr( json_encode( $value ), 1, -1 ) ); + } +} diff --git a/projects/packages/waf/tests/php/bootstrap.php b/projects/packages/waf/tests/php/bootstrap.php new file mode 100644 index 0000000000000..46763b04a2cdb --- /dev/null +++ b/projects/packages/waf/tests/php/bootstrap.php @@ -0,0 +1,11 @@ +o = new WafOperators(); + } + + /** + * Main test function + * + * @param string $ofn The name of the operator function that is being tested. + * @param array ...$tests The tests cases. + * + * @dataProvider transformDataProvider + */ + public function testOperators( $ofn, ...$tests ) { + $n = 1; + for ( $i = 0, $z = count( $tests ); $i < $z; $i += 3 ) { + $input = $tests[ $i ]; + $param = $tests[ $i + 1 ]; + $expected = $tests[ $i + 2 ]; + $this->assertSame( + $expected, + $this->o->$ofn( $input, $param ), + sprintf( 'Failed %s assertion #%d with input: %s ', $ofn, $n, $input ) + ); + $n++; + } + } + + /** + * Test data provider + */ + public function transformDataProvider() { + yield array( + 'begins_with', + // input, paramToMatch, expected_return. + '', + '', + '', + 'TestCase', + '', + '', + 'abcdef', + 'abcdef', + 'abcdef', + 'abcdefghi', + 'abcdef', + 'abcdef', + '', + 'TestCase', + false, + 'abc', + 'abcdef', + false, + ); + + yield array( + 'contains', + // input, paramToMatch, expected_return. + '', + '', + false, + 'TestCase', + '', + false, + 'abcdefghi', + 'abc', + 'abc', + 'abcdefghi', + 'ghi', + 'ghi', + 'x', + 'x', + 'x', + 'xyz', + 'y', + 'y', + 'hidinX<-not quite, but is later on->hiding', + 'hiding', + 'hiding', + ); + + yield array( + 'contains_word', + // input, paramToMatch, expected_return. + '', + '', + '', + 'TestCase', + '', + '', + 'abc def ghi', + 'abc', + 'abc', + 'abc def ghi', + 'def', + 'def', + 'abc def ghi', + 'ghi', + 'ghi', + "abc\0def ghi", + 'abc', + 'abc', + "abc\0def ghi", + 'def', + 'def', + 'x', + 'x', + 'x', + ' x ', + 'x', + 'x', + 'hidingX<-not on word boundary, but is later on->hiding', + 'hiding', + 'hiding', + '', + 'TestCase', + false, + 'abcdefghi', + 'abc', + false, + 'abcdefghi', + 'def', + false, + 'abcdefghi', + 'ghi', + false, + 'xyz', + 'y', + false, + ); + + yield array( + 'ends_with', + // input, paramToMatch, expected_return. + '', + '', + '', + 'TestCase', + '', + '', + 'abcdefghi', + 'ghi', + 'ghi', + "abcdef\0ghi", + 'ghi', + 'ghi', + '', + 'TestCase', + false, + 'abcdefghi', + 'abc', + false, + 'abcdefghi', + 'def', + false, + ); + + yield array( + 'eq', + // input, paramToMatch, expected_return. + '', + '0', + '', + '0', + 'xxx', + '0', + 'xxx', + '0', + 'xxx', + '0', + '0', + '0', + '5', + '5', + '5', + '-5', + '-5', + '-5', + '', + '5', + false, + '5', + 'xxx', + false, + '-1', + 'xxx', + false, + 'xxx', + '5', + false, + '-5', + '0', + false, + '5', + '0', + false, + '0', + '5', + false, + '10', + '5', + false, + ); + + yield array( + 'ge', + // input, paramToMatch, expected_return. + '', + '0', + '', + '5', + 'xxx', + '5', + 'xxx', + '0', + 'xxx', + '0', + '0', + '0', + '5', + '0', + '5', + '5', + '5', + '5', + '10', + '5', + '10', + '', + '5', + false, + '-1', + 'xxx', + false, + 'xxx', + '5', + false, + '-5', + '', + false, + '0', + '5', + false, + ); + + yield array( + 'gt', + // input, paramToMatch, expected_return. + '5', + 'xxx', + '5', + 'xxx', + '-1', + 'xxx', + '5', + '0', + '5', + '10', + '5', + '10', + '', + '0', + false, + '', + '5', + false, + '-1', + 'xxx', + false, + 'xxx', + '5', + false, + '-5', + '0', + false, + '0', + '0', + false, + '0', + '5', + false, + '5', + '5', + false, + ); + + yield array( + 'le', + // input, paramToMatch, expected_return. + '', + '0', + '', + '', + '5', + '', + '5', + 'xxx', + false, + '-1', + 'xxx', + '-1', + 'xxx', + '0', + 'xxx', + 'xxx', + '5', + 'xxx', + '-5', + '0', + '-5', + '0', + '0', + '0', + '5', + '0', + false, + '0', + '5', + '0', + '5', + '5', + '5', + '10', + '5', + false, + ); + + yield array( + 'lt', + // input, paramToMatch, expected_return. + '', + '0', + false, + '', + '5', + '', + '5', + 'xxx', + false, + '-1', + 'xxx', + '-1', + 'xxx', + '-1', + false, + 'xxx', + '5', + 'xxx', + '-5', + '0', + '-5', + '0', + '0', + false, + '5', + '0', + false, + '0', + '5', + '0', + '5', + '5', + false, + '10', + '5', + false, + ); + + yield array( + 'no_match', + // input, paramToMatch, expected_return. + '', + '', + false, + 'TestCase', + '', + false, + '', + 'TestCase', + false, + ); + + yield array( + 'rx', + // input, paramToMatch, expected_return. + '', + '//Ds', + array( '' ), + '', + '/TestCase/Ds', + false, + 'TestCase', + '//Ds', + array( '' ), + 'abcdefghi', + '/abc/Ds', + array( 'abc' ), + 'abcdefghi', + '/def/Ds', + array( 'def' ), + 'abcdefghi', + '/ghi/Ds', + array( 'ghi' ), + 'abcdefghi', + '/ghij/Ds', + false, + 'SELECT pg_sleep(10);', + '/(?i:(sleep\\((\\s*?)(\\d*?)(\\s*?)\\)|benchmark\\((.*?)\\,(.*?)\\)))/Ds', + array( 'sleep(10)', 'sleep(10)', '', '10', '' ), + ); + + yield array( + 'streq', + // input, paramToMatch, expected_return. + '', + '', + '', + '', + 'TestCase', + false, + 'TestCase', + '', + false, + 'abcdefghi', + 'abc', + false, + 'abcdefghi', + 'def', + false, + 'abcdefghi', + 'ghi', + false, + 'abcdefghi', + 'abcdefghi', + 'abcdefghi', + ); + + yield array( + 'unconditional_match', + // input, paramToMatch, expected_return. + '', + '', + '', + '', + 'TestCase', + '', + 'TestCase', + '', + 'TestCase', + ); + + $a2i = ord( 'a' ) . '-' . ord( 'i' ); + yield array( + 'validate_byte_range', + // input, paramToMatch, expected_return. + '', + WafRuleCompiler::parse_byte_range( array( '0-255' ) ), + false, + 'abcdefghi', + WafRuleCompiler::parse_byte_range( array( '0-255' ) ), + false, + 'abcdefghi', + WafRuleCompiler::parse_byte_range( array( $a2i ) ), + false, + 'abcdefghij', + WafRuleCompiler::parse_byte_range( array( $a2i ) ), + 'j', + ); + + yield array( + 'within', + // input, paramToMatch, expected_return. + '', + '', + false, + '', + 'TestCase', + false, + 'TestCase', + '', + false, + 'abc', + 'abcdefghi', + 'abc', + 'def', + 'abcdefghi', + 'def', + 'ghi', + 'abcdefghi', + 'ghi', + 'ghij', + 'abcdefghi', + false, + ); + } +} diff --git a/projects/packages/waf/tests/php/test-waf-runtime.php b/projects/packages/waf/tests/php/test-waf-runtime.php new file mode 100644 index 0000000000000..e4d932bcc0e92 --- /dev/null +++ b/projects/packages/waf/tests/php/test-waf-runtime.php @@ -0,0 +1,281 @@ +runtime = new WafRuntime( new WafTransforms(), new WafOperators() ); + } + + /** + * Test removing rule by id + */ + public function testRemovingRuleById() { + $this->runtime->flag_rule_for_removal( 'id', '111' ); + $this->assertTrue( $this->runtime->rule_removed( '111', array() ) ); + $this->assertFalse( $this->runtime->rule_removed( '222', array() ) ); + } + + /** + * Test removing rule by tag + */ + public function testRemovingRuleByTag() { + $this->runtime->flag_rule_for_removal( 'tag', 'abc' ); + $this->assertTrue( $this->runtime->rule_removed( '111', array( 'abc' ) ) ); + $this->assertTrue( $this->runtime->rule_removed( '111', array( 'abc', 'def' ) ) ); + $this->assertTrue( $this->runtime->rule_removed( '111', array( '789', 'abc', 'def' ) ) ); + $this->assertFalse( $this->runtime->rule_removed( '111', array() ) ); + $this->assertFalse( $this->runtime->rule_removed( '111', array( 'abcdef' ) ) ); + } + + /** + * Test removing target rule by id + */ + public function testRemovingTargetByRuleId() { + $this->runtime->flag_target_for_removal( 'id', '111', 'args' ); + $this->assertEquals( + array( 'auth_type' => array() ), + $this->runtime->update_targets( + array( + 'args' => array(), + 'auth_type' => array(), + ), + '111', + array() + ), + 'Did not remove target' + ); + $this->assertEquals( + array( + 'auth_type' => array(), + 'args' => array(), + ), + $this->runtime->update_targets( + array( + 'args' => array(), + 'auth_type' => array(), + ), + '222', + array() + ), + 'Incorrectly removed target of non-matching rule' + ); + } + + /** + * Test removing targed prop by rule id + */ + public function testRemovingTargetPropByRuleId() { + $this->runtime->flag_target_for_removal( 'id', '111', 'args', 'p' ); + $this->assertEquals( + array( + 'auth_type' => array(), + 'args' => array( 'except' => array( 'p' ) ), + ), + $this->runtime->update_targets( + array( + 'args' => array(), + 'auth_type' => array(), + ), + '111', + array() + ), + 'Did not create except list for removed prop' + ); + $this->assertEquals( + array( + 'auth_type' => array(), + 'args' => array( 'except' => array( 'o', 'p' ) ), + ), + $this->runtime->update_targets( + array( + 'args' => array( 'except' => array( 'o' ) ), + 'auth_type' => array(), + ), + '111', + array() + ), + 'Did not add prop to existing except list' + ); + $this->assertEquals( + array( + 'auth_type' => array(), + 'args' => array( + 'only' => array( 'z' ), + 'except' => array( 'o', 'p' ), + ), + ), + $this->runtime->update_targets( + array( + 'args' => array( + 'only' => array( 'z' ), + 'except' => array( 'o' ), + ), + 'auth_type' => array(), + ), + '111', + array() + ) + ); + $this->assertEquals( + array( + 'auth_type' => array(), + 'args' => array(), + ), + $this->runtime->update_targets( + array( + 'args' => array(), + 'auth_type' => array(), + ), + '222', + array() + ), + 'Incorrectly updated target of non-matching rule' + ); + } + + /** + * Test removing targed by rule tag + */ + public function testRemovingTargetByRuleTag() { + $this->runtime->flag_target_for_removal( 'tag', 'abc', 'args' ); + $this->assertEquals( + array( 'auth_type' => array() ), + $this->runtime->update_targets( + array( + 'args' => array(), + 'auth_type' => array(), + ), + '111', + array( 'abc' ) + ), + 'Did not remove target' + ); + $this->assertEquals( + array( + 'auth_type' => array(), + 'args' => array(), + ), + $this->runtime->update_targets( + array( + 'args' => array(), + 'auth_type' => array(), + ), + '222', + array( 'def' ) + ), + 'Incorrectly removed target of non-matching rule' + ); + } + + /** + * Test removing targed prop by rule tag + */ + public function testRemovingTargetPropByRuleTag() { + $this->runtime->flag_target_for_removal( 'tag', 'abc', 'args', 'p' ); + $this->assertEquals( + array( + 'auth_type' => array(), + 'args' => array( 'except' => array( 'p' ) ), + ), + $this->runtime->update_targets( + array( + 'args' => array(), + 'auth_type' => array(), + ), + '111', + array( 'abc' ) + ), + 'Did not create except list for removed prop' + ); + $this->assertEquals( + array( + 'auth_type' => array(), + 'args' => array( 'except' => array( 'o', 'p' ) ), + ), + $this->runtime->update_targets( + array( + 'args' => array( 'except' => array( 'o' ) ), + 'auth_type' => array(), + ), + '222', + array( 'abc' ) + ), + 'Did not add prop to existing except list' + ); + $this->assertEquals( + array( + 'auth_type' => array(), + 'args' => array( + 'only' => array( 'z' ), + 'except' => array( 'o', 'p' ), + ), + ), + $this->runtime->update_targets( + array( + 'args' => array( + 'only' => array( 'z' ), + 'except' => array( 'o' ), + ), + 'auth_type' => array(), + ), + '333', + array( 'abc' ) + ) + ); + $this->assertEquals( + array( + 'auth_type' => array(), + 'args' => array(), + ), + $this->runtime->update_targets( + array( + 'args' => array(), + 'auth_type' => array(), + ), + '444', + array( 'def' ) + ), + 'Incorrectly updated target of non-matching rule' + ); + } + + /** + * Test vars + */ + public function testVars() { + $this->assertSame( '', $this->runtime->get_var( 'abc' ) ); + $this->runtime->set_var( 'abc', '123' ); + $this->assertSame( '123', $this->runtime->get_var( 'abc' ) ); + $this->runtime->inc_var( 'abc', 3 ); + $this->assertEquals( 126, $this->runtime->get_var( 'abc' ) ); + $this->runtime->dec_var( 'abc', 10 ); + $this->assertEquals( 116, $this->runtime->get_var( 'abc' ) ); + $this->runtime->inc_var( 'def', 2 ); + $this->assertSame( 2.0, $this->runtime->get_var( 'def' ) ); + $this->runtime->unset_var( 'abc' ); + $this->assertSame( '', $this->runtime->get_var( 'abc' ) ); + } +} diff --git a/projects/packages/waf/tests/php/test-waf-transforms.php b/projects/packages/waf/tests/php/test-waf-transforms.php new file mode 100644 index 0000000000000..4e1ed160e24b0 --- /dev/null +++ b/projects/packages/waf/tests/php/test-waf-transforms.php @@ -0,0 +1,379 @@ +t = new GlobalWafTransforms(); + } + + /** + * Main test function + * + * @param string $tfn The name of the transform function that is being tested. + * @param array $tests The tests cases, each key in the array is the raw value with the value being the expected transformed value. + * + * @dataProvider transformDataProvider + */ + public function testTransforms( $tfn, $tests ) { + $i = 1; + foreach ( $tests as $in => $out ) { + $this->assertSame( $out, $this->t->$tfn( $in ), "Failed #$i with input: $in" ); + $i++; + } + } + + /** + * Test data provider + */ + public function transformDataProvider() { + yield array( + 'base64_decode', + array( + '' => '', + 'VGVzdENhc2U=' => 'TestCase', + 'VGVzdENhc2Ux' => 'TestCase1', + 'VGVzdENhc2UxMg==' => 'TestCase12', + ), + ); + + yield array( + 'base64_encode', + array( + '' => '', + 'TestCase' => 'VGVzdENhc2U=', + 'TestCase1' => 'VGVzdENhc2Ux', + 'TestCase12' => 'VGVzdENhc2UxMg==', + "Test\0Case" => 'VGVzdABDYXNl', + ), + ); + + yield array( + 'compress_whitespace', + array( + '' => '', + 'TestCase' => 'TestCase', + "Test\0Case" => "Test\0Case", + 'Test Case' => 'Test Case', + " Test \t Case " => ' Test Case ', + "This is a test case with a tab \t, vtab \x0b, newline \x0a, return \x0d, formfeed \f, and a NUL\0 in it with a CRLF at the end.\x0d\x0a" => "This is a test case with a tab , vtab , newline , return , formfeed , and a NUL\0 in it with a CRLF at the end. ", + ), + ); + + yield array( + 'hex_decode', + array( + '' => '', + '5465737443617365' => 'TestCase', + '546573740043617365' => "Test\0Case", + // todo: these are invalid hex strings that PHP handles differently than modsecurity's code + // '01234567890a0z01234567890a' => "\x01#Eg\x89\x0a#\x01#Eg\x89\x0a", + // '01234567890az' => "\x01#Eg\x89\x0a", + // '01234567890a0' => "\x01#Eg\x89\x0a", . + ), + ); + + yield array( + 'hex_encode', + array( + 'TestCase' => '5465737443617365', + "Test\0Case" => '546573740043617365', + ), + ); + + yield array( + 'html_entity_decode', + array( + '' => '', + 'TestCase' => 'TestCase', + "Test\0Case" => "Test\0Case", + // todo: PHP's html_entity_decode works differently than modsecurity, fails these tests + // "�� � \0d"&<> " => "\0\0\x20\x20\0\x20\0\x64\"&<>\xa0", + // "�� � \0d"&<> " => "\0\0\x20\x20\0\x20\0\x64\"&<>\xa0", + // "&#xg;&#Xg;&#xg0;g;&#a;\0&#a2;a&#a00;a0; a;&foo;" => "&#xg;&#Xg;&#xg0;\x02g;&#a;\0&#a2;\x03a&#a00;\x01a0;\x0aa;&foo;", + // "&#xg&#Xg&#xg0g&#a\0&#a2a&#a00a0 a&foo" => "&#xg&#Xg&#xg0\x02g&#a\0&#a2\x03a&#a00\x01a0\x0aa&foo", . + ), + ); + + yield array( + 'length', + array( + '0123456789abcdef' => 16, + "0123456789\tabcdef" => 17, + "Test\0Case" => 9, + ), + ); + + yield array( + 'lowercase', + array( + '' => '', + 'testcase' => 'testcase', + "test\0case" => "test\0case", + 'TestCase' => 'testcase', + "Test\0Case" => "test\0case", + ), + ); + + yield array( + 'md5', + array( + '' => "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42\x7e", + 'TestCase' => "\xc9\xab\xa2\xc3\xe6\x01\x26\x16\x9e\x80\xe9\xa2\x6b\xa2\x73\xc1", + "\x00\x01\x02\x03\x04\x05\x06\x07\x08" => "\xa6\xe7\xd3\xb4\x6f\xdf\xaf\x0b\xde\x2a\x1f\x83\x2a\x00\xd2\xde", + ), + ); + + yield array( + 'normalize_path', + array( + '' => '', + '/foo/bar/baz' => '/foo/bar/baz', + "/foo/bar\0/baz" => "/foo/bar\0/baz", + 'x' => 'x', + '.' => '', + './' => '', + './..' => '..', + './../' => '../', + '..' => '..', + '../' => '../', + '../.' => '..', + '.././' => '../', + '../..' => '../..', + '../../' => '../../', + '/dir/foo//bar' => '/dir/foo/bar', + 'dir/foo//bar/' => 'dir/foo/bar/', + 'dir/../foo' => 'foo', + 'dir/../../foo' => '../foo', + 'dir/./.././../../foo/bar' => '../../foo/bar', + 'dir/./.././../../foo/bar/.' => '../../foo/bar', + 'dir/./.././../../foo/bar/./' => '../../foo/bar/', + 'dir/./.././../../foo/bar/..' => '../../foo', + 'dir/./.././../../foo/bar/../' => '../../foo/', + 'dir/./.././../../foo/bar/' => '../../foo/bar/', + 'dir//.//..//.//..//..//foo//bar' => '../../foo/bar', + 'dir//.//..//.//..//..//foo//bar//' => '../../foo/bar/', + 'dir/subdir/subsubdir/subsubsubdir/../../..' => 'dir', + 'dir/./subdir/./subsubdir/./subsubsubdir/../../..' => 'dir', + 'dir/./subdir/../subsubdir/../subsubsubdir/..' => 'dir', + '/dir/./subdir/../subsubdir/../subsubsubdir/../' => '/dir/', + // todo: I have no idea how the input is supposed to turn into the output for this test: + // "/./.././../../../../../../../\0/../etc/./passwd" => '/etc/passwd', . + ), + ); + + yield array( + 'normalize_path_win', + array( + '' => '', + '\\foo\\bar\\baz' => '/foo/bar/baz', + "\\foo\\bar\0\\baz" => "/foo/bar\0/baz", + 'x' => 'x', + '.' => '', + '.\\' => '', + '.\\..' => '..', + '.\\..\\' => '../', + '..' => '..', + '..\\' => '../', + '..\\.' => '..', + '..\\.\\' => '../', + '..\\..' => '../..', + '..\\..\\' => '../../', + '\\dir\\foo\\\\bar' => '/dir/foo/bar', + 'dir\\foo\\\\bar\\' => 'dir/foo/bar/', + 'dir\\..\\foo' => 'foo', + 'dir\\..\\..\\foo' => '../foo', + 'dir\\.\\..\\.\\..\\..\\foo\\bar' => '../../foo/bar', + 'dir\\.\\..\\.\\..\\..\\foo\\bar\\.' => '../../foo/bar', + 'dir\\.\\..\\.\\..\\..\\foo\\bar\\.\\' => '../../foo/bar/', + 'dir\\.\\..\\.\\..\\..\\foo\\bar\\..' => '../../foo', + 'dir\\.\\..\\.\\..\\..\\foo\\bar\\../' => '../../foo/', + 'dir\\.\\..\\.\\..\\..\\foo\\bar\\' => '../../foo/bar/', + 'dir\\\\.\\\\..\\\\.\\\\..\\\\..\\\\foo\\\\bar' => '../../foo/bar', + 'dir\\\\.\\\\..\\\\.\\\\..\\\\..\\\\foo\\\\bar\\\\' => '../../foo/bar/', + 'dir\\subdir\\subsubdir\\subsubsubdir\\..\\..\\..' => 'dir', + 'dir\\.\\subdir\\.\\subsubdir\\.\\subsubsubdir\\..\\..\\..' => 'dir', + 'dir\\.\\subdir\\..\\subsubdir\\..\\subsubsubdir\\..' => 'dir', + '\\dir\\.\\subdir\\..\\subsubdir\\..\\subsubsubdir\\..\\' => '/dir/', + // todo: I have no idea how the input is supposed to turn into the output for this test: + // "\\.\\..\\.\\..\\..\\..\\..\\..\\..\\..\\\0\\..\\etc\\./passwd" => '/etc/passwd', . + ), + ); + + yield array( + 'remove_nulls', + array( + '' => '', + 'TestCase' => 'TestCase', + "Test\x01Case" => "Test\x01Case", + "\0TestCase" => 'TestCase', + "Test\0Case" => 'TestCase', + "Test\0\0Case" => 'TestCase', + "TestCase\0" => 'TestCase', + "\0Test\0Case\0" => 'TestCase', + ), + ); + + yield array( + 'remove_whitespace', + array( + '' => '', + 'TestCase' => 'TestCase', + "Test\0Case" => "Test\0Case", + " Test \t Case " => 'TestCase', + "This is a test case with a tab \t, vtab \x0b, newline \x0a, return \x0d, formfeed \f, and a NUL\0 in it with a CRLF at the end.\x0d\x0a" => "Thisisatestcasewithatab,vtab,newline,return,formfeed,andaNUL\0initwithaCRLFattheend.", + ), + ); + + yield array( + 'replace_comments', + array( + '' => '', + 'TestCase' => 'TestCase', + "Test\0Case" => "Test\0Case", + '/* TestCase */' => ' ', + '/*TestCase*/' => ' ', + '/* TestCase*/' => ' ', + '/*TestCase */' => ' ', + 'Before/* TestCase */After' => 'Before After', + 'Before /* TestCase */ After' => 'Before After', + "/* Test\nCase */" => ' ', + "/* Test\x0d\x0aCase */" => ' ', + "/* Test\x0aCase */" => ' ', + "/* Test\x0dCase */" => ' ', + "Before/* Test\x0d\x0aCase " => 'Before ', + "Before /* Test\x0aCase " => 'Before ', + "Before/* Test\x0d\x0aCase " => 'Before ', + "Before /* Test\x0aCase " => 'Before ', + "Test\x0d\x0aCase */After" => "Test\x0d\x0aCase */After", + "Test\x0aCase */ After" => "Test\x0aCase */ After", + "Test\x0d\x0aCase */After" => "Test\x0d\x0aCase */After", + "Test\x0aCase */ After" => "Test\x0aCase */ After", + ), + ); + + yield array( + 'replace_nulls', + array( + '' => '', + 'TestCase' => 'TestCase', + "\0TestCase" => ' TestCase', + "Test\0Case" => 'Test Case', + "Test\0\0Case" => 'Test Case', + "TestCase\0" => 'TestCase ', + "\0Test\0Case\0" => ' Test Case ', + ), + ); + + yield array( + 'sha1', + array( + '' => "\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09", + 'TestCase' => "\xa7\x0c\xe3\x83\x89\xe3\x18\xbd\x2b\xe1\x8a\x01\x11\xc6\xdc\x76\xbd\x2c\xd9\xed", + "\x00\x01\x02\x03\x04\x05\x06\x07\x08" => "\x63\xbf\x60\xc7\x10\x5a\x07\xa2\xb1\x25\xbb\xf8\x9e\x61\xab\xda\xbc\x69\x78\xc2", + ), + ); + + yield array( + 'trim', + array( + '' => '', + 'TestCase' => 'TestCase', + "Test\0Case" => "Test\0Case", + ' TestCase' => 'TestCase', + 'TestCase ' => 'TestCase', + ' TestCase ' => 'TestCase', + ' Test Case ' => 'Test Case', + " Test \0 Case " => "Test \0 Case", + " Test \0 Case \r\n " => "Test \0 Case", + ), + ); + + yield array( + 'trim_left', + array( + '' => '', + 'TestCase' => 'TestCase', + "Test\0Case" => "Test\0Case", + 'TestCase ' => 'TestCase ', + ' TestCase' => 'TestCase', + ' TestCase ' => 'TestCase ', + ' Test Case ' => 'Test Case ', + " Test \0 Case " => "Test \0 Case ", + " Test \0 Case \r\n " => "Test \0 Case \r\n ", + ), + ); + + yield array( + 'trim_right', + array( + '' => '', + 'TestCase' => 'TestCase', + ' TestCase' => ' TestCase', + 'TestCase ' => 'TestCase', + ' TestCase ' => ' TestCase', + ' Test Case ' => ' Test Case', + " Test \0 Case " => " Test \0 Case", + " Test \0 Case \r\n " => " Test \0 Case", + ), + ); + + yield array( + 'url_decode', + array( + '' => '', + 'TestCase' => 'TestCase', + "Test\0Case" => "Test\0Case", + '+%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c%2d%2e%2f%30%31%32%33%34%35%36%37%38%39%3a%3b%3c%3d%3e%3f%40%41%42%43%44%45%46%47%48%49%4a%4b%4c%4d%4e%4f%50%51%52%53%54%55%56%57%58%59%5a%5b%5c%5d%5e%5f%60%61%62%63%64%65%66%67%68%69%6a%6b%6c%6d%6e%6f%70%71%72%73%74%75%76%77%78%79%7a%7b%7c%7d%7e%7f%80%81%82%83%84%85%86%87%88%89%8a%8b%8c%8d%8e%8f%90%91%92%93%94%95%96%97%98%99%9a%9b%9c%9d%9e%9f%a0%a1%a2%a3%a4%a5%a6%a7%a8%a9%aa%ab%ac%ad%ae%af%b0%b1%b2%b3%b4%b5%b6%b7%b8%b9%ba%bb%bc%bd%be%bf%c0%c1%c2%c3%c4%c5%c6%c7%c8%c9%ca%cb%cc%cd%ce%cf%d0%d1%d2%d3%d4%d5%d6%d7%d8%d9%da%db%dc%dd%de%df%e0%e1%e2%e3%e4%e5%e6%e7%e8%e9%ea%eb%ec%ed%ee%ef%f0%f1%f2%f3%f4%f5%f6%f7%f8%f9%fa%fb%fc%fd%fe%ff' => " \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f \x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + 'Test+Case' => 'Test Case', + '%+' => '% ', + '%%20' => '% ', + '%0g%20' => '%0g ', + '%0%20' => '%0 ', + '%g0%20' => '%g0 ', + '%g%20' => '%g ', + '%0%1%2%3%4%5%6%7%8%9%0%a%b%c%d%e%f' => '%0%1%2%3%4%5%6%7%8%9%0%a%b%c%d%e%f', + '%g0%g1%g2%g3%g4%g5%g6%g7%g8%g9%g0%ga%gb%gc%gd%ge%gf' => '%g0%g1%g2%g3%g4%g5%g6%g7%g8%g9%g0%ga%gb%gc%gd%ge%gf', + '%0g%1g%2g%3g%4g%5g%6g%7g%8g%9g%0g%ag%bg%cg%dg%eg%fg' => '%0g%1g%2g%3g%4g%5g%6g%7g%8g%9g%0g%ag%bg%cg%dg%eg%fg', + '%' => '%', + '%%' => '%%', + '%0g' => '%0g', + '%gg' => '%gg', + ), + ); + + yield array( + 'utf8_to_unicode', + array( + 'Ā ā Ă ă Ą ą Ć ć Ĉ ĉ Ċ ċ Č č Ď ď Đ đ Ē ē Ĕ ĕ Ė ė Ę ę Ě ě Ĝ ĝ Ğ ğ Ġ ġ Ģ ģ Ĥ ĥ Ħ ħ Ĩ ĩ Ī ī Ĭ ĭ Į į İ ı IJ ij Ĵ ĵ Ķ ķ ĸ Ĺ ĺ Ļ ļ Ľ ľ Ŀ ŀ Ł ł Ń ń Ņ ņ Ň ň ʼn Ŋ ŋ Ō ō Ŏ ŏ Ő ő Œ œ Ŕ ŕ Ŗ ŗ Ř ř Ś ś Ŝ ŝ Ş ş Š š Ţ ţ Ť ť Ŧ ŧ Ũ ũ Ū ū Ŭ ŭ Ů ů Ű ű Ų ų Ŵ ŵ Ŷ ŷ Ÿ Ź ź Ż ż Ž ž ſ' => '%u0100 %u0101 %u0102 %u0103 %u0104 %u0105 %u0106 %u0107 %u0108 %u0109 %u010a %u010b %u010c %u010d %u010e %u010f %u0110 %u0111 %u0112 %u0113 %u0114 %u0115 %u0116 %u0117 %u0118 %u0119 %u011a %u011b %u011c %u011d %u011e %u011f %u0120 %u0121 %u0122 %u0123 %u0124 %u0125 %u0126 %u0127 %u0128 %u0129 %u012a %u012b %u012c %u012d %u012e %u012f %u0130 %u0131 %u0132 %u0133 %u0134 %u0135 %u0136 %u0137 %u0138 %u0139 %u013a %u013b %u013c %u013d %u013e %u013f %u0140 %u0141 %u0142 %u0143 %u0144 %u0145 %u0146 %u0147 %u0148 %u0149 %u014a %u014b %u014c %u014d %u014e %u014f %u0150 %u0151 %u0152 %u0153 %u0154 %u0155 %u0156 %u0157 %u0158 %u0159 %u015a %u015b %u015c %u015d %u015e %u015f %u0160 %u0161 %u0162 %u0163 %u0164 %u0165 %u0166 %u0167 %u0168 %u0169 %u016a %u016b %u016c %u016d %u016e %u016f %u0170 %u0171 %u0172 %u0173 %u0174 %u0175 %u0176 %u0177 %u0178 %u0179 %u017a %u017b %u017c %u017d %u017e %u017f', + 'Ѐ Ё Ђ Ѓ Є Ѕ І Ї Ј Љ Њ Ћ Ќ Ѝ Ў Џ А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ы Ь Э Ю Я а б в г д е ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ы ь э ю я ѐ ё ђ ѓ є ѕ і ї ј љ њ ћ ќ ѝ ў џ Ѡ ѡ Ѣ ѣ Ѥ ѥ Ѧ ѧ Ѩ ѩ Ѫ ѫ Ѭ ѭ Ѯ ѯ Ѱ ѱ Ѳ ѳ Ѵ ѵ Ѷ ѷ Ѹ ѹ Ѻ ѻ Ѽ ѽ Ѿ ѿ Ҁ ҁ ҂ ҈ ҉ Ҋ ҋ Ҍ ҍ Ҏ ҏ Ґ ґ Ғ ғ Ҕ ҕ Җ җ Ҙ ҙ Қ қ Ҝ ҝ Ҟ ҟ Ҡ ҡ Ң ң Ҥ ҥ Ҧ ҧ Ҩ ҩ Ҫ ҫ Ҭ ҭ Ү ү Ұ ұ Ҳ ҳ Ҵ ҵ Ҷ ҷ Ҹ ҹ Һ һ Ҽ ҽ Ҿ ҿ Ӏ Ӂ ӂ Ӄ ӄ Ӆ ӆ Ӈ ӈ Ӊ ӊ Ӌ ӌ Ӎ ӎ ӏ Ӑ ӑ Ӓ ӓ Ӕ ӕ Ӗ ӗ Ә ә Ӛ ӛ Ӝ ӝ Ӟ ӟ Ӡ ӡ Ӣ ӣ Ӥ ӥ Ӧ ӧ Ө ө Ӫ ӫ Ӭ ӭ Ӯ ӯ Ӱ ӱ Ӳ ӳ Ӵ ӵ Ӷ ӷ Ӹ ӹ Ӻ ӻ Ӽ ӽ Ӿ ӿ ͵ ͺ ͻ ͼ ͽ ΄ ΅ Ά Έ Ή Ί Ό Ύ Ώ ΐ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ Φ Χ Ψ Ω Ϊ Ϋ ά έ ή ί ΰ α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ ς σ τ υ φ χ ψ ω ϊ ϋ ό ύ ώ ϐ ϑ ϒ ϓ ϔ ϕ ϖ ϗ Ϙ ϙ Ϛ ϛ Ϝ ϝ Ϟ ϟ Ϡ ϡ Ϣ ϣ Ϥ ϥ Ϧ ϧ Ϩ ϩ Ϫ ϫ Ϭ ϭ Ϯ ϯ ϰ ϱ ϲ ϳ ϴ ϵ ϶ Ϸ ϸ Ϲ Ϻ ϻ ϼ Ͻ Ͼ Ͽ ־ ׀ ׃ ׆ א ב ג ד ה ו ז ח ט י ך כ ל ם מ ן נ ס ע ף פ ץ צ ק ר ש ת װ ױ ײ ׳ ״' => '%u0400 %u0401 %u0402 %u0403 %u0404 %u0405 %u0406 %u0407 %u0408 %u0409 %u040a %u040b %u040c %u040d %u040e %u040f %u0410 %u0411 %u0412 %u0413 %u0414 %u0415 %u0416 %u0417 %u0418 %u0419 %u041a %u041b %u041c %u041d %u041e %u041f %u0420 %u0421 %u0422 %u0423 %u0424 %u0425 %u0426 %u0427 %u0428 %u0429 %u042a %u042b %u042c %u042d %u042e %u042f %u0430 %u0431 %u0432 %u0433 %u0434 %u0435 %u0436 %u0437 %u0438 %u0439 %u043a %u043b %u043c %u043d %u043e %u043f %u0440 %u0441 %u0442 %u0443 %u0444 %u0445 %u0446 %u0447 %u0448 %u0449 %u044a %u044b %u044c %u044d %u044e %u044f %u0450 %u0451 %u0452 %u0453 %u0454 %u0455 %u0456 %u0457 %u0458 %u0459 %u045a %u045b %u045c %u045d %u045e %u045f %u0460 %u0461 %u0462 %u0463 %u0464 %u0465 %u0466 %u0467 %u0468 %u0469 %u046a %u046b %u046c %u046d %u046e %u046f %u0470 %u0471 %u0472 %u0473 %u0474 %u0475 %u0476 %u0477 %u0478 %u0479 %u047a %u047b %u047c %u047d %u047e %u047f %u0480 %u0481 %u0482 %u0488 %u0489 %u048a %u048b %u048c %u048d %u048e %u048f %u0490 %u0491 %u0492 %u0493 %u0494 %u0495 %u0496 %u0497 %u0498 %u0499 %u049a %u049b %u049c %u049d %u049e %u049f %u04a0 %u04a1 %u04a2 %u04a3 %u04a4 %u04a5 %u04a6 %u04a7 %u04a8 %u04a9 %u04aa %u04ab %u04ac %u04ad %u04ae %u04af %u04b0 %u04b1 %u04b2 %u04b3 %u04b4 %u04b5 %u04b6 %u04b7 %u04b8 %u04b9 %u04ba %u04bb %u04bc %u04bd %u04be %u04bf %u04c0 %u04c1 %u04c2 %u04c3 %u04c4 %u04c5 %u04c6 %u04c7 %u04c8 %u04c9 %u04ca %u04cb %u04cc %u04cd %u04ce %u04cf %u04d0 %u04d1 %u04d2 %u04d3 %u04d4 %u04d5 %u04d6 %u04d7 %u04d8 %u04d9 %u04da %u04db %u04dc %u04dd %u04de %u04df %u04e0 %u04e1 %u04e2 %u04e3 %u04e4 %u04e5 %u04e6 %u04e7 %u04e8 %u04e9 %u04ea %u04eb %u04ec %u04ed %u04ee %u04ef %u04f0 %u04f1 %u04f2 %u04f3 %u04f4 %u04f5 %u04f6 %u04f7 %u04f8 %u04f9 %u04fa %u04fb %u04fc %u04fd %u04fe %u04ff %u0375 %u037a %u037b %u037c %u037d %u0384 %u0385 %u0386 %u0388 %u0389 %u038a %u038c %u038e %u038f %u0390 %u0391 %u0392 %u0393 %u0394 %u0395 %u0396 %u0397 %u0398 %u0399 %u039a %u039b %u039c %u039d %u039e %u039f %u03a0 %u03a1 %u03a3 %u03a4 %u03a5 %u03a6 %u03a7 %u03a8 %u03a9 %u03aa %u03ab %u03ac %u03ad %u03ae %u03af %u03b0 %u03b1 %u03b2 %u03b3 %u03b4 %u03b5 %u03b6 %u03b7 %u03b8 %u03b9 %u03ba %u03bb %u03bc %u03bd %u03be %u03bf %u03c0 %u03c1 %u03c2 %u03c3 %u03c4 %u03c5 %u03c6 %u03c7 %u03c8 %u03c9 %u03ca %u03cb %u03cc %u03cd %u03ce %u03d0 %u03d1 %u03d2 %u03d3 %u03d4 %u03d5 %u03d6 %u03d7 %u03d8 %u03d9 %u03da %u03db %u03dc %u03dd %u03de %u03df %u03e0 %u03e1 %u03e2 %u03e3 %u03e4 %u03e5 %u03e6 %u03e7 %u03e8 %u03e9 %u03ea %u03eb %u03ec %u03ed %u03ee %u03ef %u03f0 %u03f1 %u03f2 %u03f3 %u03f4 %u03f5 %u03f6 %u03f7 %u03f8 %u03f9 %u03fa %u03fb %u03fc %u03fd %u03fe %u03ff %u05be %u05c0 %u05c3 %u05c6 %u05d0 %u05d1 %u05d2 %u05d3 %u05d4 %u05d5 %u05d6 %u05d7 %u05d8 %u05d9 %u05da %u05db %u05dc %u05dd %u05de %u05df %u05e0 %u05e1 %u05e2 %u05e3 %u05e4 %u05e5 %u05e6 %u05e7 %u05e8 %u05e9 %u05ea %u05f0 %u05f1 %u05f2 %u05f3 %u05f4', + 'ب ة ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ـ ف ق ك ل م ن ه و ى ي ٖ ٗ ٘ ٙ ٠ ١ ٢ ٣ ٤ ٥ ٦ ٧ ٨ ٩ ٪ ٫ ٬ ٭ ٮ ٯ ٱ ٲ ٳ ٴ ٵ ٶ ٷ ٸ ٹ ٺ ٻ ټ ٽ پ ٿ ڀ ځ ڂ ڃ ڄ څ چ ڇ ڈ ډ ڊ ڋ ڌ ڍ ڎ ڏ ڐ ڑ ڒ ړ ڔ ڕ ږ ڗ ژ ڙ ښ ڛ ڜ ڝ ڞ ڟ ڠ ڡ ڢ ڣ ڤ ڥ ڦ ڧ ڨ ک ڪ ګ ڬ ڭ ڮ گ ڰ ڱ ڲ ڳ ڴ ڵ ڶ ڷ ڸ ڹ ں ڻ ڼ ڽ ھ ڿ ۀ ہ ۂ ۃ ۄ ۅ ۆ ۇ ۈ ۉ ۊ ۋ ی ۍ ێ ۏ ې ۑ ے ۓ ۔ ە ۝ ۞ ۥ ۦ ۩ ۮ ۯ ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ ۺ ۻ ۼ ۽ ۾ ' => '%u0628 %u0629 %u062a %u062b %u062c %u062d %u062e %u062f %u0630 %u0631 %u0632 %u0633 %u0634 %u0635 %u0636 %u0637 %u0638 %u0639 %u063a %u0640 %u0641 %u0642 %u0643 %u0644 %u0645 %u0646 %u0647 %u0648 %u0649 %u064a %u0656 %u0657 %u0658 %u0659 %u0660 %u0661 %u0662 %u0663 %u0664 %u0665 %u0666 %u0667 %u0668 %u0669 %u066a %u066b %u066c %u066d %u066e %u066f %u0671 %u0672 %u0673 %u0674 %u0675 %u0676 %u0677 %u0678 %u0679 %u067a %u067b %u067c %u067d %u067e %u067f %u0680 %u0681 %u0682 %u0683 %u0684 %u0685 %u0686 %u0687 %u0688 %u0689 %u068a %u068b %u068c %u068d %u068e %u068f %u0690 %u0691 %u0692 %u0693 %u0694 %u0695 %u0696 %u0697 %u0698 %u0699 %u069a %u069b %u069c %u069d %u069e %u069f %u06a0 %u06a1 %u06a2 %u06a3 %u06a4 %u06a5 %u06a6 %u06a7 %u06a8 %u06a9 %u06aa %u06ab %u06ac %u06ad %u06ae %u06af %u06b0 %u06b1 %u06b2 %u06b3 %u06b4 %u06b5 %u06b6 %u06b7 %u06b8 %u06b9 %u06ba %u06bb %u06bc %u06bd %u06be %u06bf %u06c0 %u06c1 %u06c2 %u06c3 %u06c4 %u06c5 %u06c6 %u06c7 %u06c8 %u06c9 %u06ca %u06cb %u06cc %u06cd %u06ce %u06cf %u06d0 %u06d1 %u06d2 %u06d3 %u06d4 %u06d5 %u06dd %u06de %u06e5 %u06e6 %u06e9 %u06ee %u06ef %u06f0 %u06f1 %u06f2 %u06f3 %u06f4 %u06f5 %u06f6 %u06f7 %u06f8 %u06f9 %u06fa %u06fb %u06fc %u06fd %u06fe ', + '■ □ ▢ ▣ ▤ ▥ ▦ ▧ ▨ ▩ ▪ ▫ ▬ ▭ ▮ ▯ ▰ ▱ ▲ △ ▴ ▵ ▶ ▷ ▸ ▹ ► ▻ ▼ ▽ ▾ ▿ ◀ ◁ ◂ ◃ ◄ ◅ ◆ ◇ ◈ ◉ ◊ ○ ◌ ◍ ◎ ● ◐ ◑ ◒ ◓ ◔ ◕ ◖ ◗ ◘ ◙ ◚ ◛ ◜ ◝ ◞ ◟ ◠ ◡ ◢ ◣ ◤ ◥ ◦ ◧ ◨ ◩ ◪ ◫ ◬ ◭ ◮ ◯ ◰ ◱ ◲ ◳ ◴ ◵ ◶ ◷ ◸ ◹ ◺ ◻ ◼ ◽ ◾ ◿' => '%u25a0 %u25a1 %u25a2 %u25a3 %u25a4 %u25a5 %u25a6 %u25a7 %u25a8 %u25a9 %u25aa %u25ab %u25ac %u25ad %u25ae %u25af %u25b0 %u25b1 %u25b2 %u25b3 %u25b4 %u25b5 %u25b6 %u25b7 %u25b8 %u25b9 %u25ba %u25bb %u25bc %u25bd %u25be %u25bf %u25c0 %u25c1 %u25c2 %u25c3 %u25c4 %u25c5 %u25c6 %u25c7 %u25c8 %u25c9 %u25ca %u25cb %u25cc %u25cd %u25ce %u25cf %u25d0 %u25d1 %u25d2 %u25d3 %u25d4 %u25d5 %u25d6 %u25d7 %u25d8 %u25d9 %u25da %u25db %u25dc %u25dd %u25de %u25df %u25e0 %u25e1 %u25e2 %u25e3 %u25e4 %u25e5 %u25e6 %u25e7 %u25e8 %u25e9 %u25ea %u25eb %u25ec %u25ed %u25ee %u25ef %u25f0 %u25f1 %u25f2 %u25f3 %u25f4 %u25f5 %u25f6 %u25f7 %u25f8 %u25f9 %u25fa %u25fb %u25fc %u25fd %u25fe %u25ff', + ' ✁ ✂ ✃ ✄ ✅ ✆ ✇ ✈ ✉ ✊ ✋ ✌ ✍ ✎ ✏ ✐ ✑ ✒ ✓ ✔ ✕ ✖ ✗ ✘ ✙ ✚ ✛ ✜ ✝ ✞ ✟ ✠ ✡ ✢ ✣ ✤ ✥ ✦ ✧ ✨ ✩ ✪ ✫ ✬ ✭ ✮ ✯ ✰ ✱ ✲ ✳ ✴ ✵ ✶ ✷ ✸ ✹ ✺ ✻ ✼ ✽ ✾ ✿ ❀ ❁ ❂ ❃ ❄ ❅ ❆ ❇ ❈ ❉ ❊ ❋ ❌ ❍ ❎ ❏ ❐ ❑ ❒ ❓ ❔ ❕ ❖ ❗ ❘ ❙ ❚ ❛ ❜ ❝ ❣ ❤ ❥ ❦ ❧ ❨ ❩ ❪ ❫ ❬ ❭ ❮ ❯ ❰ ❱ ❲ ❳ ❴ ❵ ❶ ❷ ❸ ❹ ❺ ❻ ❼ ❽ ❾ ❿ ➀ ➁ ➂ ➃ ➄ ➅ ➆ ➇ ➈ ➉ ➊ ➋ ➌ ➍ ➎ ➏ ➐ ➑ ➒ ➓ ➔ ➘ ➙ ➚ ➛ ➜ ➝ ➞ ➟ ➠ ➡ ➢ ➣ ➤ ➥ ➦ ➧ ➨ ➩ ➪ ➫ ➬ ➭ ➮ ➯ ➰ ➱ ➲ ➳ ➴ ➵ ➶ ➷ ➸ ➹ ➺ ➻ ➼ ➽ ➾ ➿' => ' %u2701 %u2702 %u2703 %u2704 %u2705 %u2706 %u2707 %u2708 %u2709 %u270a %u270b %u270c %u270d %u270e %u270f %u2710 %u2711 %u2712 %u2713 %u2714 %u2715 %u2716 %u2717 %u2718 %u2719 %u271a %u271b %u271c %u271d %u271e %u271f %u2720 %u2721 %u2722 %u2723 %u2724 %u2725 %u2726 %u2727 %u2728 %u2729 %u272a %u272b %u272c %u272d %u272e %u272f %u2730 %u2731 %u2732 %u2733 %u2734 %u2735 %u2736 %u2737 %u2738 %u2739 %u273a %u273b %u273c %u273d %u273e %u273f %u2740 %u2741 %u2742 %u2743 %u2744 %u2745 %u2746 %u2747 %u2748 %u2749 %u274a %u274b %u274c %u274d %u274e %u274f %u2750 %u2751 %u2752 %u2753 %u2754 %u2755 %u2756 %u2757 %u2758 %u2759 %u275a %u275b %u275c %u275d %u2763 %u2764 %u2765 %u2766 %u2767 %u2768 %u2769 %u276a %u276b %u276c %u276d %u276e %u276f %u2770 %u2771 %u2772 %u2773 %u2774 %u2775 %u2776 %u2777 %u2778 %u2779 %u277a %u277b %u277c %u277d %u277e %u277f %u2780 %u2781 %u2782 %u2783 %u2784 %u2785 %u2786 %u2787 %u2788 %u2789 %u278a %u278b %u278c %u278d %u278e %u278f %u2790 %u2791 %u2792 %u2793 %u2794 %u2798 %u2799 %u279a %u279b %u279c %u279d %u279e %u279f %u27a0 %u27a1 %u27a2 %u27a3 %u27a4 %u27a5 %u27a6 %u27a7 %u27a8 %u27a9 %u27aa %u27ab %u27ac %u27ad %u27ae %u27af %u27b0 %u27b1 %u27b2 %u27b3 %u27b4 %u27b5 %u27b6 %u27b7 %u27b8 %u27b9 %u27ba %u27bb %u27bc %u27bd %u27be %u27bf', + ' ⟀ ⟁ ⟂ ⟃ ⟄ ⟅ ⟆ ⟇ ⟈ ⟉ ⟊ ⟌ ⟐ ⟑ ⟒ ⟓ ⟔ ⟕ ⟖ ⟗ ⟘ ⟙ ⟚ ⟛ ⟜ ⟝ ⟞ ⟟ ⟠ ⟡ ⟢ ⟣ ⟤ ⟥ ⟦ ⟧ ⟨ ⟩ ⟪ ⟫ ⟬ ⟭ ⟮ ⟯' => ' %u27c0 %u27c1 %u27c2 %u27c3 %u27c4 %u27c5 %u27c6 %u27c7 %u27c8 %u27c9 %u27ca %u27cc %u27d0 %u27d1 %u27d2 %u27d3 %u27d4 %u27d5 %u27d6 %u27d7 %u27d8 %u27d9 %u27da %u27db %u27dc %u27dd %u27de %u27df %u27e0 %u27e1 %u27e2 %u27e3 %u27e4 %u27e5 %u27e6 %u27e7 %u27e8 %u27e9 %u27ea %u27eb %u27ec %u27ed %u27ee %u27ef', + ' ⟰ ⟱ ⟲ ⟳ ⟴ ⟵ ⟶ ⟷ ⟸ ⟹ ⟺ ⟻ ⟼ ⟽ ⟾ ⟿' => ' %u27f0 %u27f1 %u27f2 %u27f3 %u27f4 %u27f5 %u27f6 %u27f7 %u27f8 %u27f9 %u27fa %u27fb %u27fc %u27fd %u27fe %u27ff', + ), + ); + } +} diff --git a/projects/plugins/backup/CHANGELOG.md b/projects/plugins/backup/CHANGELOG.md index bfacd050ec085..5c04e6a47b115 100644 --- a/projects/plugins/backup/CHANGELOG.md +++ b/projects/plugins/backup/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 1.1.0-beta - 2022-01-13 +## 1.1.0 - 2022-01-26 ### Added - Added My Jetpack page work in progress behind a feature flag. - Added pricing information to Jetpack Connection screen. diff --git a/projects/js-packages/storybook/changelog/add-10.1-changelog b/projects/plugins/backup/changelog/2022-01-25-15-58-16-336664 similarity index 100% rename from projects/js-packages/storybook/changelog/add-10.1-changelog rename to projects/plugins/backup/changelog/2022-01-25-15-58-16-336664 diff --git a/projects/js-packages/storybook/changelog/add-changelogger-squash-command b/projects/plugins/backup/changelog/2022-01-27-11-15-38-111622 similarity index 100% rename from projects/js-packages/storybook/changelog/add-changelogger-squash-command rename to projects/plugins/backup/changelog/2022-01-27-11-15-38-111622 diff --git a/projects/js-packages/storybook/changelog/add-idc-errors b/projects/plugins/backup/changelog/2022-02-02-15-16-49-411998 similarity index 100% rename from projects/js-packages/storybook/changelog/add-idc-errors rename to projects/plugins/backup/changelog/2022-02-02-15-16-49-411998 diff --git a/projects/plugins/vaultpress/changelog/add-idc-customizate-labels b/projects/plugins/backup/changelog/add-anti-spam-my-jetpack similarity index 100% rename from projects/plugins/vaultpress/changelog/add-idc-customizate-labels rename to projects/plugins/backup/changelog/add-anti-spam-my-jetpack diff --git a/projects/js-packages/storybook/changelog/add-idc-non-admin b/projects/plugins/backup/changelog/add-dependency-analysis-in-cli similarity index 100% rename from projects/js-packages/storybook/changelog/add-idc-non-admin rename to projects/plugins/backup/changelog/add-dependency-analysis-in-cli diff --git a/projects/js-packages/storybook/changelog/add-jetpack-spinner-to-storybook b/projects/plugins/backup/changelog/add-disconnect-modal-click-events similarity index 100% rename from projects/js-packages/storybook/changelog/add-jetpack-spinner-to-storybook rename to projects/plugins/backup/changelog/add-disconnect-modal-click-events diff --git a/projects/js-packages/storybook/changelog/add-js-packages-exports b/projects/plugins/backup/changelog/add-idc-safe-mode-bar similarity index 100% rename from projects/js-packages/storybook/changelog/add-js-packages-exports rename to projects/plugins/backup/changelog/add-idc-safe-mode-bar diff --git a/projects/js-packages/storybook/changelog/add-my-jetpack-sections b/projects/plugins/backup/changelog/add-my-jetpack-plugin-installation similarity index 100% rename from projects/js-packages/storybook/changelog/add-my-jetpack-sections rename to projects/plugins/backup/changelog/add-my-jetpack-plugin-installation diff --git a/projects/js-packages/storybook/changelog/renovate-storybook-monorepo#6 b/projects/plugins/backup/changelog/add-my_jetpack_has_plan similarity index 54% rename from projects/js-packages/storybook/changelog/renovate-storybook-monorepo#6 rename to projects/plugins/backup/changelog/add-my_jetpack_has_plan index 302aa8cf46b5c..650406ad22bff 100644 --- a/projects/js-packages/storybook/changelog/renovate-storybook-monorepo#6 +++ b/projects/plugins/backup/changelog/add-my_jetpack_has_plan @@ -1,4 +1,4 @@ Significance: patch Type: changed -Updated package dependencies +updated lock file diff --git a/projects/plugins/vaultpress/changelog/add-idc-customizer-tags b/projects/plugins/backup/changelog/add-my_jetpack_has_plan#2 similarity index 100% rename from projects/plugins/vaultpress/changelog/add-idc-customizer-tags rename to projects/plugins/backup/changelog/add-my_jetpack_has_plan#2 diff --git a/projects/plugins/vaultpress/changelog/add-rna-connect-screen-required-plan b/projects/plugins/backup/changelog/add-plugins-install-mirror-repo similarity index 100% rename from projects/plugins/vaultpress/changelog/add-rna-connect-screen-required-plan rename to projects/plugins/backup/changelog/add-plugins-install-mirror-repo diff --git a/projects/js-packages/storybook/changelog/add-new-attach-license-method b/projects/plugins/backup/changelog/fix-connection-status-card-display_name similarity index 100% rename from projects/js-packages/storybook/changelog/add-new-attach-license-method rename to projects/plugins/backup/changelog/fix-connection-status-card-display_name diff --git a/projects/plugins/vaultpress/changelog/feature-sync-error-capture b/projects/plugins/backup/changelog/fix-my-jetpack-tests similarity index 100% rename from projects/plugins/vaultpress/changelog/feature-sync-error-capture rename to projects/plugins/backup/changelog/fix-my-jetpack-tests diff --git a/projects/js-packages/storybook/changelog/renovate-storybook-monorepo#4 b/projects/plugins/backup/changelog/renovate-wordpress-monorepo similarity index 100% rename from projects/js-packages/storybook/changelog/renovate-storybook-monorepo#4 rename to projects/plugins/backup/changelog/renovate-wordpress-monorepo diff --git a/projects/js-packages/storybook/changelog/add-rna-connect-screen-required-plan#2 b/projects/plugins/backup/changelog/renovate-wordpress-monorepo#2 similarity index 100% rename from projects/js-packages/storybook/changelog/add-rna-connect-screen-required-plan#2 rename to projects/plugins/backup/changelog/renovate-wordpress-monorepo#2 diff --git a/projects/js-packages/storybook/changelog/add-user-license-activate-notice-2 b/projects/plugins/backup/changelog/update-better-structure-for-i18n-loader similarity index 100% rename from projects/js-packages/storybook/changelog/add-user-license-activate-notice-2 rename to projects/plugins/backup/changelog/update-better-structure-for-i18n-loader diff --git a/projects/plugins/backup/changelog/update-changelog-readme b/projects/plugins/backup/changelog/update-changelog-readme new file mode 100644 index 0000000000000..74d631b06c790 --- /dev/null +++ b/projects/plugins/backup/changelog/update-changelog-readme @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated changelog and readme with 1.1.0 version identifier diff --git a/projects/js-packages/storybook/changelog/add-user-license-activate-notice-2#2 b/projects/plugins/backup/changelog/update-move-i18n-loader-pkg-path-into-assets similarity index 100% rename from projects/js-packages/storybook/changelog/add-user-license-activate-notice-2#2 rename to projects/plugins/backup/changelog/update-move-i18n-loader-pkg-path-into-assets diff --git a/projects/js-packages/storybook/changelog/backup-branch-1.1.0 b/projects/plugins/backup/changelog/update-my-jetpack-styles similarity index 100% rename from projects/js-packages/storybook/changelog/backup-branch-1.1.0 rename to projects/plugins/backup/changelog/update-my-jetpack-styles diff --git a/projects/plugins/backup/composer.json b/projects/plugins/backup/composer.json index 462cc8e0b7c17..d57f24e6fbecd 100644 --- a/projects/plugins/backup/composer.json +++ b/projects/plugins/backup/composer.json @@ -4,16 +4,16 @@ "type": "library", "license": "GPL-2.0-or-later", "require": { - "automattic/jetpack-assets": "1.16.x-dev", + "automattic/jetpack-assets": "1.17.x-dev", "automattic/jetpack-admin-ui": "0.2.x-dev", "automattic/jetpack-autoloader": "2.10.x-dev", "automattic/jetpack-backup": "1.2.x-dev", - "automattic/jetpack-composer-plugin": "1.0.x-dev", + "automattic/jetpack-composer-plugin": "1.1.x-dev", "automattic/jetpack-config": "1.6.x-dev", "automattic/jetpack-connection": "1.36.x-dev", "automattic/jetpack-connection-ui": "2.3.x-dev", - "automattic/jetpack-identity-crisis": "0.6.x-dev", - "automattic/jetpack-my-jetpack": "0.4.x-dev", + "automattic/jetpack-identity-crisis": "0.7.x-dev", + "automattic/jetpack-my-jetpack": "0.5.x-dev", "automattic/jetpack-sync": "1.29.x-dev", "automattic/jetpack-status": "1.10.x-dev" }, diff --git a/projects/plugins/backup/composer.lock b/projects/plugins/backup/composer.lock index 89904c6485ed5..12a44dfd7877b 100644 --- a/projects/plugins/backup/composer.lock +++ b/projects/plugins/backup/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f6c6a6654288c4971fe6b4c1cb93f238", + "content-hash": "c3a6891977d5f9e3a9b540f58682effe", "packages": [ { "name": "automattic/jetpack-a8c-mc-stats", @@ -60,7 +60,7 @@ "dist": { "type": "path", "url": "../../packages/admin-ui", - "reference": "e9c471e1ac68c4dd7cf656fd17a4b96fdc4c6ff1" + "reference": "bbb92b9b9852760e84b7aaee877ee081616efcb3" }, "require-dev": { "automattic/jetpack-changelogger": "^3.0", @@ -71,6 +71,7 @@ "extra": { "autotagger": true, "mirror-repo": "Automattic/jetpack-admin-ui", + "textdomain": "jetpack-admin-ui", "changelogger": { "link-template": "https://github.com/Automattic/jetpack-admin-ui/compare/${old}...${new}" }, @@ -115,7 +116,7 @@ "dist": { "type": "path", "url": "../../packages/assets", - "reference": "558a4eabba5541257e2b496aeba6da3a06e169f5" + "reference": "810134d18a0baedd94aae5398f2f506f213bac7b" }, "require": { "automattic/jetpack-constants": "^1.6" @@ -135,7 +136,7 @@ "link-template": "https://github.com/Automattic/jetpack-assets/compare/v${old}...v${new}" }, "branch-alias": { - "dev-master": "1.16.x-dev" + "dev-master": "1.17.x-dev" } }, "autoload": { @@ -147,11 +148,21 @@ ] }, "scripts": { + "build-development": [ + "pnpm run build" + ], + "build-production": [ + "pnpm run build-production" + ], "phpunit": [ "./vendor/phpunit/phpunit/phpunit --colors=always" ], "test-coverage": [ - "php -dpcov.directory=. ./vendor/bin/phpunit --coverage-clover \"$COVERAGE_DIR/clover.xml\"" + "php -dpcov.directory=. ./vendor/bin/phpunit --coverage-clover \"$COVERAGE_DIR/php/clover.xml\"", + "pnpm run test-coverage" + ], + "test-js": [ + "pnpm run test" ], "test-php": [ "@composer phpunit" @@ -291,7 +302,7 @@ "dist": { "type": "path", "url": "../../packages/composer-plugin", - "reference": "d9a79b97dbf363bdffb2f748e0dbed8216753c36" + "reference": "c3fc0e4cf179c619f896174a6c9db8e70cff74c3" }, "require": { "composer-plugin-api": "^2.1.0" @@ -310,7 +321,7 @@ }, "autotagger": true, "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { @@ -450,14 +461,14 @@ "dist": { "type": "path", "url": "../../packages/connection-ui", - "reference": "73a9cff560f04b981ca97d26225cc8fbb91c0be5" + "reference": "af0b68a96950278824fbd56aad4fc5f5a2af4240" }, "require": { - "automattic/jetpack-assets": "^1.16", + "automattic/jetpack-assets": "^1.17", "automattic/jetpack-connection": "^1.36", "automattic/jetpack-constants": "^1.6", "automattic/jetpack-device-detection": "^1.4", - "automattic/jetpack-identity-crisis": "^0.6" + "automattic/jetpack-identity-crisis": "^0.7" }, "require-dev": { "automattic/jetpack-changelogger": "^3.0" @@ -644,10 +655,10 @@ "dist": { "type": "path", "url": "../../packages/identity-crisis", - "reference": "daea57d4601da806be82d3265429cb9c2a304c00" + "reference": "80cc6904f5337f7cfa194199ad307e054fece278" }, "require": { - "automattic/jetpack-assets": "^1.16", + "automattic/jetpack-assets": "^1.17", "automattic/jetpack-connection": "^1.36", "automattic/jetpack-constants": "^1.6", "automattic/jetpack-logo": "^1.5", @@ -672,7 +683,7 @@ "link-template": "https://github.com/Automattic/jetpack-identity-crisis/compare/v${old}...v${new}" }, "branch-alias": { - "dev-master": "0.6.x-dev" + "dev-master": "0.7.x-dev" } }, "autoload": { @@ -767,17 +778,20 @@ "dist": { "type": "path", "url": "../../packages/my-jetpack", - "reference": "a5d7c6f0f3652d649cac7b11dfe35db034634fb7" + "reference": "0a4354d247242a1fbc56373c2ddd4ccacab62d52" }, "require": { "automattic/jetpack-admin-ui": "^0.2", - "automattic/jetpack-assets": "^1.16", + "automattic/jetpack-assets": "^1.17", "automattic/jetpack-connection": "^1.36", + "automattic/jetpack-plugins-installer": "^0.1", "automattic/jetpack-terms-of-service": "^1.9", "automattic/jetpack-tracking": "^1.14" }, "require-dev": { "automattic/jetpack-changelogger": "^3.0", + "automattic/jetpack-options": "^1.14", + "automattic/jetpack-search": "^0.7", "automattic/wordbless": "@dev", "yoast/phpunit-polyfills": "1.0.3" }, @@ -790,7 +804,7 @@ "link-template": "https://github.com/Automattic/jetpack-my-jetpack/compare/${old}...${new}" }, "branch-alias": { - "dev-master": "0.4.x-dev" + "dev-master": "0.5.x-dev" } }, "autoload": { @@ -933,6 +947,58 @@ "relative": true } }, + { + "name": "automattic/jetpack-plugins-installer", + "version": "dev-master", + "dist": { + "type": "path", + "url": "../../packages/plugins-installer", + "reference": "19c930344c337c188d411a51938c7c870ea511a1" + }, + "require": { + "automattic/jetpack-a8c-mc-stats": "^1.4" + }, + "require-dev": { + "automattic/jetpack-changelogger": "^3.0", + "yoast/phpunit-polyfills": "1.0.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.1.x-dev" + }, + "mirror-repo": "Automattic/jetpack-plugins-installer", + "changelogger": { + "link-template": "https://github.com/Automattic/jetpack-plugins-installer/compare/v${old}...v${new}" + }, + "autotagger": true, + "textdomain": "jetpack-plugins-installer" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "scripts": { + "phpunit": [ + "./vendor/phpunit/phpunit/phpunit --colors=always" + ], + "test-coverage": [ + "php -dpcov.directory=. ./vendor/bin/phpunit --coverage-clover \"$COVERAGE_DIR/clover.xml\"" + ], + "test-php": [ + "@composer phpunit" + ] + }, + "license": [ + "GPL-2.0-or-later" + ], + "description": "Handle installation of plugins from WP.org", + "transport-options": { + "monorepo": true, + "relative": true + } + }, { "name": "automattic/jetpack-redirect", "version": "dev-master", @@ -1092,13 +1158,13 @@ "dist": { "type": "path", "url": "../../packages/sync", - "reference": "cad6e550e4c76cc17cab3ddef0829b67e2c04838" + "reference": "08c63a81a1ac29072c140383f3bf9266a4c3c6be" }, "require": { "automattic/jetpack-connection": "^1.36", "automattic/jetpack-constants": "^1.6", "automattic/jetpack-heartbeat": "^1.4", - "automattic/jetpack-identity-crisis": "^0.6", + "automattic/jetpack-identity-crisis": "^0.7", "automattic/jetpack-options": "^1.14", "automattic/jetpack-password-checker": "^0.2", "automattic/jetpack-roles": "^1.4", @@ -1211,10 +1277,10 @@ "dist": { "type": "path", "url": "../../packages/tracking", - "reference": "ed6f897aaaa8e843271556d271e6c7a829cb8727" + "reference": "60dd2a4462221bcc460aadf9f86daeb308fd8027" }, "require": { - "automattic/jetpack-assets": "^1.16", + "automattic/jetpack-assets": "^1.17", "automattic/jetpack-options": "^1.14", "automattic/jetpack-status": "^1.10", "automattic/jetpack-terms-of-service": "^1.9" @@ -1423,9 +1489,6 @@ "require": { "php": "^7.1 || ^8.0" }, - "replace": { - "myclabs/deep-copy": "self.version" - }, "require-dev": { "doctrine/collections": "^1.0", "doctrine/common": "^2.6", diff --git a/projects/plugins/backup/package.json b/projects/plugins/backup/package.json index 5c9a0d3570a08..2c22996fe254b 100644 --- a/projects/plugins/backup/package.json +++ b/projects/plugins/backup/package.json @@ -24,20 +24,20 @@ "extends @wordpress/browserslist-config" ], "dependencies": { - "@automattic/jetpack-api": "workspace:^0.8.3-alpha", - "@automattic/jetpack-components": "workspace:^0.10.3-alpha", - "@automattic/jetpack-connection": "workspace:^0.14.0-alpha", - "@wordpress/api-fetch": "5.2.6", - "@wordpress/data": "6.1.5", - "@wordpress/element": "4.0.4", - "@wordpress/date": "4.2.3", - "@wordpress/i18n": "4.2.4", + "@automattic/jetpack-api": "workspace:^0.8.4-alpha", + "@automattic/jetpack-components": "workspace:^0.10.5-alpha", + "@automattic/jetpack-connection": "workspace:^0.15.1-alpha", + "@wordpress/api-fetch": "6.0.0", + "@wordpress/data": "6.2.0", + "@wordpress/element": "4.1.0", + "@wordpress/date": "4.3.0", + "@wordpress/i18n": "4.3.0", "react": "17.0.2", "react-dom": "17.0.2" }, "devDependencies": { - "@automattic/jetpack-base-styles": "workspace:^0.1.7-alpha", - "@automattic/jetpack-webpack-config": "workspace:^1.0.3-alpha", + "@automattic/jetpack-base-styles": "workspace:^0.1.8-alpha", + "@automattic/jetpack-webpack-config": "workspace:^1.1.2-alpha", "@babel/core": "7.16.0", "@babel/preset-env": "7.16.4", "@babel/register": "7.16.0", diff --git a/projects/plugins/backup/readme.txt b/projects/plugins/backup/readme.txt index 28e2b6b77d369..786c204352019 100644 --- a/projects/plugins/backup/readme.txt +++ b/projects/plugins/backup/readme.txt @@ -4,7 +4,7 @@ Tags: jetpack Requires at least: 5.8 Requires PHP: 5.6 Tested up to: 5.9 -Stable tag: 1.0.1 +Stable tag: 1.1.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -158,7 +158,7 @@ No, Jetpack Backup does not currently support split site or split home URLs. 2. Your site backups are stored in multiple locations on our world-class cloud infrastructure so you can recover them at any moment. == Changelog == -### 1.1.0-beta - 2022-01-13 +### 1.1.0 - 2022-01-26 #### Added - Added My Jetpack page work in progress behind a feature flag. - Added pricing information to Jetpack Connection screen. diff --git a/projects/plugins/backup/src/js/components/Admin.js b/projects/plugins/backup/src/js/components/Admin.js index 2724a00d0c7dd..1398091f32028 100644 --- a/projects/plugins/backup/src/js/components/Admin.js +++ b/projects/plugins/backup/src/js/components/Admin.js @@ -9,7 +9,7 @@ import { AdminPage, AdminSection, AdminSectionHero, - Row, + Container, Col, getRedirectUrl, PricingCard, @@ -84,7 +84,7 @@ const Admin = () => { 'jetpack-backup' ); return ( - +

    { __( 'Secure your site with a Backup subscription.', 'jetpack-backup' ) }

    @@ -115,7 +115,7 @@ const Admin = () => { title={ __( 'Jetpack Backup', 'jetpack-backup' ) } /> - + ); }; @@ -130,11 +130,11 @@ const Admin = () => { } return ( - + { renderConnectScreen() } - + ); } @@ -154,11 +154,11 @@ const Admin = () => { // Render an error state, this shouldn't occurr since we've passed userConnected checks if ( capabilitiesError ) { return ( - + { capabilitiesError } - + ); } @@ -168,7 +168,7 @@ const Admin = () => { // Renders additional segments under the jp-hero area condition on having a backup plan const renderBackupSegments = () => { return ( - +

    { __( 'Your cloud backups', 'jetpack-backup' ) }

    @@ -218,7 +218,7 @@ const Admin = () => { { renderConnectionStatusCard() } - + ); }; diff --git a/projects/plugins/beta/changelog/renovate-major-eslint-packages b/projects/plugins/beta/changelog/renovate-major-eslint-packages new file mode 100644 index 0000000000000..f8a4b188c86c1 --- /dev/null +++ b/projects/plugins/beta/changelog/renovate-major-eslint-packages @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +Added docs to JS file. diff --git a/projects/plugins/beta/src/admin/updates.js b/projects/plugins/beta/src/admin/updates.js index badcf5e315c2c..6ac54c55e5c62 100644 --- a/projects/plugins/beta/src/admin/updates.js +++ b/projects/plugins/beta/src/admin/updates.js @@ -1,4 +1,6 @@ /** + * Update message hooks. + * * @param {jQuery} $ - jQuery object. * @param {object} wp - WP object. * @param {object} i18n - I18n data. diff --git a/projects/plugins/boost/.phpcs.dir.xml b/projects/plugins/boost/.phpcs.dir.xml index de9dcf15a11a6..0d50ca55e7c99 100644 --- a/projects/plugins/boost/.phpcs.dir.xml +++ b/projects/plugins/boost/.phpcs.dir.xml @@ -21,4 +21,38 @@ + + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + diff --git a/projects/plugins/boost/app/admin/class-admin.php b/projects/plugins/boost/app/admin/class-admin.php index 014fc768c3b77..4cfe6eb0e9b69 100644 --- a/projects/plugins/boost/app/admin/class-admin.php +++ b/projects/plugins/boost/app/admin/class-admin.php @@ -10,14 +10,14 @@ use Automattic\Jetpack\Admin_UI\Admin_Menu; use Automattic\Jetpack\Status; +use Automattic\Jetpack_Boost\Features\Optimizations\Critical_CSS\Critical_CSS; +use Automattic\Jetpack_Boost\Features\Optimizations\Optimizations; +use Automattic\Jetpack_Boost\Features\Speed_Score\Speed_Score; use Automattic\Jetpack_Boost\Jetpack_Boost; use Automattic\Jetpack_Boost\Lib\Analytics; use Automattic\Jetpack_Boost\Lib\Environment_Change_Detector; -use Automattic\Jetpack_Boost\Lib\Speed_Score; +use Automattic\Jetpack_Boost\REST_API\Permissions\Nonce; -/** - * Class Admin - */ class Admin { /** @@ -45,7 +45,7 @@ class Admin { * * @var Jetpack_Boost Plugin. */ - private $jetpack_boost; + private $modules; /** * Speed_Score class instance. @@ -54,21 +54,13 @@ class Admin { */ private $speed_score; - /** - * Initialize the class and set its properties. - * - * @param Jetpack_Boost $jetpack_boost Main plugin instance. - * - * @since 1.0.0 - */ - public function __construct( Jetpack_Boost $jetpack_boost ) { - $this->jetpack_boost = $jetpack_boost; - $this->speed_score = new Speed_Score( $jetpack_boost ); + public function __construct( Optimizations $modules ) { + $this->modules = $modules; + $this->speed_score = new Speed_Score( $modules ); Environment_Change_Detector::init(); add_action( 'init', array( new Analytics(), 'init' ) ); add_filter( 'plugin_action_links_' . JETPACK_BOOST_PLUGIN_BASE, array( $this, 'plugin_page_settings_link' ) ); - add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) ); add_action( 'admin_notices', array( $this, 'show_notices' ) ); add_action( 'wp_ajax_set_show_rating_prompt', array( $this, 'handle_set_show_rating_prompt' ) ); add_filter( 'jetpack_boost_js_constants', array( $this, 'add_js_constants' ) ); @@ -102,7 +94,7 @@ public function enqueue_styles() { $internal_path = apply_filters( 'jetpack_boost_asset_internal_path', 'app/assets/dist/' ); wp_enqueue_style( - $this->jetpack_boost->get_plugin_name() . '-css', + 'jetpack-boost-css', plugins_url( $internal_path . 'jetpack-boost.css', JETPACK_BOOST_PATH ), array( 'wp-components' ), JETPACK_BOOST_VERSION @@ -117,7 +109,7 @@ public function enqueue_styles() { public function enqueue_scripts() { $internal_path = apply_filters( 'jetpack_boost_asset_internal_path', 'app/assets/dist/' ); - $admin_js_handle = $this->jetpack_boost->get_plugin_name() . '-admin'; + $admin_js_handle = 'jetpack-boost-admin'; wp_register_script( $admin_js_handle, @@ -127,6 +119,7 @@ public function enqueue_scripts() { true ); + $optimizations = ( new Optimizations() )->get_status(); // Prepare configuration constants for JavaScript. $constants = array( 'version' => JETPACK_BOOST_VERSION, @@ -134,8 +127,7 @@ public function enqueue_scripts() { 'namespace' => JETPACK_BOOST_REST_NAMESPACE, 'prefix' => JETPACK_BOOST_REST_PREFIX, ), - 'modules' => $this->jetpack_boost->get_available_modules(), - 'config' => $this->jetpack_boost->config()->get_data(), + 'optimizations' => $optimizations, 'locale' => get_locale(), 'site' => array( 'url' => get_home_url(), @@ -146,6 +138,14 @@ public function enqueue_scripts() { 'preferences' => array( 'showRatingPrompt' => $this->get_show_rating_prompt(), ), + + /** + * A bit of necessary magic, + * Explained more in the Nonce class. + * + * Nonces are automatically generated when registering routes. + */ + 'nonces' => Nonce::get_generated_nonces(), ); // Give each module an opportunity to define extra constants. @@ -179,7 +179,7 @@ public function plugin_page_settings_link( $links ) { */ public function render_settings() { wp_localize_script( - $this->jetpack_boost->get_plugin_name() . '-admin', + 'jetpack-boost-admin', 'wpApiSettings', array( 'root' => esc_url_raw( rest_url() ), @@ -200,49 +200,6 @@ public function check_for_permissions() { return current_user_can( 'manage_options' ); } - /** - * Register REST routes for settings. - * - * @return void - */ - public function register_rest_routes() { - // Activate and deactivate a module. - register_rest_route( - JETPACK_BOOST_REST_NAMESPACE, - JETPACK_BOOST_REST_PREFIX . '/module/(?P[a-z\-]+)/status', - array( - 'methods' => \WP_REST_Server::EDITABLE, - 'callback' => array( $this, 'set_module_status' ), - 'permission_callback' => array( $this, 'check_for_permissions' ), - ) - ); - } - - /** - * Handler for the /module/(?P[a-z\-]+)/status endpoint. - * - * @param \WP_REST_Request $request The request object. - * - * @return \WP_REST_Response|\WP_Error The response. - */ - public function set_module_status( $request ) { - $params = $request->get_json_params(); - - if ( ! isset( $params['status'] ) ) { - return new \WP_Error( - 'jetpack_boost_error_missing_module_status_param', - __( 'Missing status param', 'jetpack-boost' ) - ); - } - - $module_slug = $request['slug']; - $this->jetpack_boost->set_module_status( (bool) $params['status'], $module_slug ); - - return rest_ensure_response( - $this->jetpack_boost->get_module_status( $module_slug ) - ); - } - /** * Show any admin notices from enabled modules. */ @@ -250,7 +207,7 @@ public function show_notices() { // Determine if we're already on the settings page. // phpcs:ignore WordPress.Security.NonceVerification.Recommended $on_settings_page = isset( $_GET['page'] ) && self::MENU_SLUG === $_GET['page']; - $notices = $this->jetpack_boost->get_admin_notices(); + $notices = $this->get_admin_notices(); // Filter out any that have been dismissed, unless newer than the dismissal. $dismissed_notices = \get_option( self::DISMISSED_NOTICE_OPTION, array() ); @@ -281,7 +238,7 @@ function ( $notice ) use ( $dismissed_notices ) { * @return array List of notice ids. */ private function get_shown_admin_notice_ids() { - $notices = $this->jetpack_boost->get_admin_notices(); + $notices = $this->get_admin_notices(); $ids = array(); foreach ( $notices as $notice ) { $ids[] = $notice->get_id(); @@ -290,6 +247,18 @@ private function get_shown_admin_notice_ids() { return $ids; } + /** + * Returns a list of admin notices to show. Asks each module to provide admin notices the user needs to see. + * + * @TODO: This is still a code smell. We're carrying the whole modules instance just to get a list of admin notices. + * + * @return \Automattic\Jetpack_Boost\Admin\Admin_Notice[] + */ + public function get_admin_notices() { + $critical_css = new Critical_CSS(); + return $critical_css->get_admin_notices(); + } + /** * Check for a GET parameter used to dismiss an admin notice. * diff --git a/projects/plugins/boost/app/assets/src/js/api/api.ts b/projects/plugins/boost/app/assets/src/js/api/api.ts index bc6831bcecfb8..51d37883c4cd9 100644 --- a/projects/plugins/boost/app/assets/src/js/api/api.ts +++ b/projects/plugins/boost/app/assets/src/js/api/api.ts @@ -15,6 +15,7 @@ import { ApiError } from './api-error'; import type { JSONObject } from '../utils/json-types'; function getEndpointUrl( path: string ): string { + // eslint-disable-next-line camelcase return wpApiSettings.root + Jetpack_Boost.api.namespace + Jetpack_Boost.api.prefix + path; } diff --git a/projects/plugins/boost/app/assets/src/js/api/speed-scores.ts b/projects/plugins/boost/app/assets/src/js/api/speed-scores.ts index 4d4cf27bd128a..014133d6eba8e 100644 --- a/projects/plugins/boost/app/assets/src/js/api/speed-scores.ts +++ b/projects/plugins/boost/app/assets/src/js/api/speed-scores.ts @@ -43,6 +43,7 @@ export async function requestSpeedScores( force = false ): Promise< SpeedScoresS // Request metrics const response = parseResponse( await api.post( force ? '/speed-scores/refresh' : '/speed-scores', { + // eslint-disable-next-line camelcase url: Jetpack_Boost.site.url, } ) ); @@ -121,6 +122,7 @@ async function pollRequest(): Promise< SpeedScoresSet > { timeoutError: __( 'Timed out while waiting for speed-score.', 'jetpack-boost' ), callback: async resolve => { const response = parseResponse( + // eslint-disable-next-line camelcase await api.post( '/speed-scores', { url: Jetpack_Boost.site.url } ) ); diff --git a/projects/plugins/boost/app/assets/src/js/global.d.ts b/projects/plugins/boost/app/assets/src/js/global.d.ts index 16d75ef98e167..b341177e5a5a8 100644 --- a/projects/plugins/boost/app/assets/src/js/global.d.ts +++ b/projects/plugins/boost/app/assets/src/js/global.d.ts @@ -12,7 +12,7 @@ import type { BrowserInterfaceIframe, generateCriticalCSS } from 'jetpack-boost- */ import type { ConnectionStatus } from './stores/connection'; import type { CriticalCssStatus } from './stores/critical-css-status'; -import type { ModulesState } from './stores/modules'; +import type { Optimizations } from './stores/modules'; declare global { const wpApiSettings: { @@ -35,15 +35,17 @@ declare global { connection: ConnectionStatus; criticalCssStatus?: CriticalCssStatus; showRatingPromptNonce?: string; - criticalCssDismissRecommendationsNonce?: string; criticalCssDismissedRecommendations: string[]; site: { url: string; online: boolean; assetPath: string; }; - config: ModulesState; + optimizations: Optimizations; shownAdminNoticeIds: string[]; + nonces: { + [ key: string ]: string; + }; }; // Critical CSS Generator library. diff --git a/projects/plugins/boost/app/assets/src/js/pages/settings/elements/RatingCard.svelte b/projects/plugins/boost/app/assets/src/js/pages/settings/elements/RatingCard.svelte index cbca5742929f0..9371e4dd16fb7 100644 --- a/projects/plugins/boost/app/assets/src/js/pages/settings/elements/RatingCard.svelte +++ b/projects/plugins/boost/app/assets/src/js/pages/settings/elements/RatingCard.svelte @@ -24,6 +24,7 @@ await makeAdminAjaxRequest( { action: 'set_show_rating_prompt', value: false, + // eslint-disable-next-line camelcase nonce: Jetpack_Boost.showRatingPromptNonce, } ); diff --git a/projects/plugins/boost/app/assets/src/js/pages/settings/sections/Score.svelte b/projects/plugins/boost/app/assets/src/js/pages/settings/sections/Score.svelte index 248947810c484..b2f62e26d96c1 100644 --- a/projects/plugins/boost/app/assets/src/js/pages/settings/sections/Score.svelte +++ b/projects/plugins/boost/app/assets/src/js/pages/settings/sections/Score.svelte @@ -25,6 +25,7 @@ */ import { __ } from '@wordpress/i18n'; + // eslint-disable-next-line camelcase const siteIsOnline = Jetpack_Boost.site.online; let loadError; @@ -120,6 +121,7 @@ } }, 2000 ); + // eslint-disable-next-line camelcase const respawnRatingPrompt = writable( Jetpack_Boost.preferences.showRatingPrompt ); const showRatingCard = derived( diff --git a/projects/plugins/boost/app/assets/src/js/stores/connection.ts b/projects/plugins/boost/app/assets/src/js/stores/connection.ts index f0849625e2c4d..c8ddcf54ca75b 100644 --- a/projects/plugins/boost/app/assets/src/js/stores/connection.ts +++ b/projects/plugins/boost/app/assets/src/js/stores/connection.ts @@ -14,6 +14,7 @@ export type ConnectionStatus = { error: null | string; }; +// eslint-disable-next-line camelcase const initialState = Jetpack_Boost.connection; const { subscribe, update } = writable< ConnectionStatus >( initialState ); diff --git a/projects/plugins/boost/app/assets/src/js/stores/critical-css-recommendations.ts b/projects/plugins/boost/app/assets/src/js/stores/critical-css-recommendations.ts index 4f80206670bc4..ee0f67931040f 100644 --- a/projects/plugins/boost/app/assets/src/js/stores/critical-css-recommendations.ts +++ b/projects/plugins/boost/app/assets/src/js/stores/critical-css-recommendations.ts @@ -6,11 +6,11 @@ import { writable, derived } from 'svelte/store'; /** * Internal dependencies */ +import api from '../api/api'; import { CriticalCssErrorDetails, criticalCssStatus } from './critical-css-status'; import type { JSONObject } from '../utils/json-types'; import { objectFilter } from '../utils/object-filter'; import { sortByFrequency } from '../utils/sort-by-frequency'; -import { makeAdminAjaxRequest } from '../utils/make-admin-ajax-request'; import { castToString } from '../utils/cast-to-string'; const importantProviders = [ @@ -20,6 +20,7 @@ const importantProviders = [ 'singular_post', ]; +// eslint-disable-next-line camelcase const initialState = Jetpack_Boost.criticalCssDismissedRecommendations || []; const dismissed = writable< string[] >( initialState ); @@ -118,10 +119,10 @@ export function setDismissalError( title: string, error: JSONObject ): void { * @param {string} key Key of recommendation to dismiss. */ export async function dismissRecommendation( key: string ): Promise< void > { - await makeAdminAjaxRequest( { - action: 'dismiss_recommendations', + await api.post( '/recommendations/dismiss', { providerKey: key, - nonce: Jetpack_Boost.criticalCssDismissRecommendationsNonce, + // eslint-disable-next-line camelcase + nonce: Jetpack_Boost.nonces[ 'recommendations/dismiss' ], } ); dismissed.update( keys => [ ...keys, key ] ); } @@ -130,9 +131,9 @@ export async function dismissRecommendation( key: string ): Promise< void > { * Clear all the dismissed recommendations. */ export async function clearDismissedRecommendations(): Promise< void > { - await makeAdminAjaxRequest( { - action: 'reset_dismissed_recommendations', - nonce: Jetpack_Boost.criticalCssDismissRecommendationsNonce, + await api.post( '/recommendations/reset', { + // eslint-disable-next-line camelcase + nonce: Jetpack_Boost.nonces[ 'recommendations/reset' ], } ); dismissed.set( [] ); } diff --git a/projects/plugins/boost/app/assets/src/js/stores/critical-css-status.ts b/projects/plugins/boost/app/assets/src/js/stores/critical-css-status.ts index 7f9a7d82e8f7d..1254c3f1d107a 100644 --- a/projects/plugins/boost/app/assets/src/js/stores/critical-css-status.ts +++ b/projects/plugins/boost/app/assets/src/js/stores/critical-css-status.ts @@ -47,6 +47,7 @@ export interface CriticalCssStatus { const success = 'success'; const fail = 'fail'; +// eslint-disable-next-line camelcase const initialState = Jetpack_Boost.criticalCssStatus || { generating: false, progress: 0, diff --git a/projects/plugins/boost/app/assets/src/js/stores/modules.ts b/projects/plugins/boost/app/assets/src/js/stores/modules.ts index f9accfb9b2544..668f0771c61e6 100644 --- a/projects/plugins/boost/app/assets/src/js/stores/modules.ts +++ b/projects/plugins/boost/app/assets/src/js/stores/modules.ts @@ -9,6 +9,10 @@ import { writable } from 'svelte/store'; import config from './config'; import { setModuleState } from '../api/modules'; +export type Optimizations = { + [ slug: string ]: boolean; +}; + export type ModulesState = { [ slug: string ]: { enabled: boolean; @@ -16,7 +20,13 @@ export type ModulesState = { }; }; -const initialState = config.config; +const initialState = {}; +for ( const [ name, value ] of Object.entries( config.optimizations ) ) { + initialState[ name ] = { + enabled: value, + }; +} + const { subscribe, update } = writable< ModulesState >( initialState ); // Keep a subscribed copy for quick reading. diff --git a/projects/plugins/boost/app/assets/src/js/utils/analytics.ts b/projects/plugins/boost/app/assets/src/js/utils/analytics.ts index 73da7fe910d27..fa35b4d6f29e9 100644 --- a/projects/plugins/boost/app/assets/src/js/utils/analytics.ts +++ b/projects/plugins/boost/app/assets/src/js/utils/analytics.ts @@ -5,6 +5,7 @@ export function recordBoostEvent( ): void { // eslint-disable-next-line camelcase if ( ! ( 'boost_version' in eventProp ) && 'version' in Jetpack_Boost ) { + // eslint-disable-next-line camelcase eventProp.boost_version = Jetpack_Boost.version; } diff --git a/projects/plugins/boost/app/assets/src/js/utils/generate-critical-css.ts b/projects/plugins/boost/app/assets/src/js/utils/generate-critical-css.ts index 9e931710023bb..a76d34c2321d6 100644 --- a/projects/plugins/boost/app/assets/src/js/utils/generate-critical-css.ts +++ b/projects/plugins/boost/app/assets/src/js/utils/generate-critical-css.ts @@ -76,12 +76,12 @@ export default async function generateCriticalCss( hasGenerateRun = true; let cancelling = false; - if ( reset ) { - await clearDismissedRecommendations(); - updateGenerateStatus( true, 0 ); - } - try { + if ( reset ) { + await clearDismissedRecommendations(); + updateGenerateStatus( true, 0 ); + } + // Fetch a list of provider keys and URLs while loading the Critical CSS lib. const cssStatus = await requestGeneration( reset, isShowstopperRetry ); diff --git a/projects/plugins/boost/app/assets/src/js/utils/load-critical-css-library.ts b/projects/plugins/boost/app/assets/src/js/utils/load-critical-css-library.ts index 366c27df0f3dc..c0f7b43742607 100644 --- a/projects/plugins/boost/app/assets/src/js/utils/load-critical-css-library.ts +++ b/projects/plugins/boost/app/assets/src/js/utils/load-critical-css-library.ts @@ -15,6 +15,7 @@ export async function loadCriticalCssLibrary(): Promise< void > { loadLibraryPromise = new Promise< void >( ( resolve, reject ) => { const scriptUrl = + // eslint-disable-next-line camelcase Jetpack_Boost.site.assetPath + '/critical-css-gen.js?ver=' + Jetpack_Boost.version; const scriptTag = document.createElement( 'script' ); scriptTag.src = scriptUrl; diff --git a/projects/plugins/boost/app/assets/src/js/utils/remove-admin-notices.ts b/projects/plugins/boost/app/assets/src/js/utils/remove-admin-notices.ts index df7502bb5ce5d..7338403ee25d1 100644 --- a/projects/plugins/boost/app/assets/src/js/utils/remove-admin-notices.ts +++ b/projects/plugins/boost/app/assets/src/js/utils/remove-admin-notices.ts @@ -4,6 +4,7 @@ * @param {string} moduleSlug Module Slug */ export function removeShownAdminNotices( moduleSlug: string ): void { + // eslint-disable-next-line camelcase for ( const adminNoticeId of Jetpack_Boost.shownAdminNoticeIds ) { if ( adminNoticeId.includes( moduleSlug ) ) { const notice = document.getElementById( adminNoticeId ); diff --git a/projects/plugins/boost/app/class-jetpack-boost.php b/projects/plugins/boost/app/class-jetpack-boost.php index cbef9b8fcd3f3..02ac717a4041c 100644 --- a/projects/plugins/boost/app/class-jetpack-boost.php +++ b/projects/plugins/boost/app/class-jetpack-boost.php @@ -12,19 +12,17 @@ namespace Automattic\Jetpack_Boost; -use Automattic\Jetpack\Config as Jetpack_Config; use Automattic\Jetpack_Boost\Admin\Admin; +use Automattic\Jetpack_Boost\Features\Optimizations\Critical_CSS\Critical_CSS; +use Automattic\Jetpack_Boost\Features\Optimizations\Critical_CSS\Critical_CSS_Storage; +use Automattic\Jetpack_Boost\Features\Optimizations\Critical_CSS\Regenerate_Admin_Notice; +use Automattic\Jetpack_Boost\Features\Optimizations\Optimizations; use Automattic\Jetpack_Boost\Lib\Analytics; use Automattic\Jetpack_Boost\Lib\CLI; -use Automattic\Jetpack_Boost\Lib\Config; use Automattic\Jetpack_Boost\Lib\Connection; -use Automattic\Jetpack_Boost\Lib\Speed_Score_History; -use Automattic\Jetpack_Boost\Lib\Viewport; -use Automattic\Jetpack_Boost\Modules\Critical_CSS\Critical_CSS; -use Automattic\Jetpack_Boost\Modules\Critical_CSS\Regenerate_Admin_Notice; -use Automattic\Jetpack_Boost\Modules\Lazy_Images\Lazy_Images; -use Automattic\Jetpack_Boost\Modules\Module; -use Automattic\Jetpack_Boost\Modules\Render_Blocking_JS\Render_Blocking_JS; +use Automattic\Jetpack_Boost\Lib\Setup; +use Automattic\Jetpack_Boost\REST_API\Endpoints\Optimization_Status; +use Automattic\Jetpack_Boost\REST_API\REST_API; /** * The core plugin class. @@ -40,28 +38,6 @@ */ class Jetpack_Boost { - const MODULES = array( - Critical_CSS::MODULE_SLUG => Critical_CSS::class, - Lazy_Images::MODULE_SLUG => Lazy_Images::class, - Render_Blocking_JS::MODULE_SLUG => Render_Blocking_JS::class, - ); - - /** - * Default enabled modules. - */ - const ENABLED_MODULES_DEFAULT = array(); - - /** - * Default available modules. - */ - const AVAILABLE_MODULES_DEFAULT = array( - Critical_CSS::MODULE_SLUG, - Render_Blocking_JS::MODULE_SLUG, - Lazy_Images::MODULE_SLUG, - ); - - const CURRENT_CONFIG_ID = 'default'; - /** * The unique identifier of this plugin. * @@ -78,21 +54,6 @@ class Jetpack_Boost { */ private $version; - /** - * The config - * - * @since 1.0.0 - * @var Config|null $config The configuration object - */ - private $config; - - /** - * Store all plugin module instances here - * - * @var array - */ - private $modules = array(); - /** * The Jetpack Boost Connection manager instance. * @@ -127,20 +88,12 @@ public function __construct() { \WP_CLI::add_command( 'jetpack-boost', $cli_instance ); } - // Initialize the config module separately. - $this->init_config(); - - $this->prepare_modules(); + $optimizations = new Optimizations(); + Setup::add( $optimizations ); // Initialize the Admin experience. - $this->init_admin(); - - // Module readiness filter. - add_action( 'wp_head', array( $this, 'display_meta_field_module_ready' ) ); - - add_action( 'init', array( $this, 'initialize_modules' ) ); + $this->init_admin( $optimizations ); add_action( 'init', array( $this, 'init_textdomain' ) ); - add_action( 'init', array( $this, 'register_cache_clear_actions' ) ); add_action( 'handle_theme_change', array( $this, 'handle_theme_change' ) ); @@ -156,307 +109,23 @@ private function register_deactivation_hook() { register_deactivation_hook( $plugin_file, array( $this, 'deactivate' ) ); } - /** - * Wipe all cached values. - */ - public function clear_cache() { - do_action( 'jetpack_boost_clear_cache' ); - } - /** * Plugin deactivation handler. Clear cache, and reset admin notices. */ public function deactivate() { do_action( 'jetpack_boost_deactivate' ); - - $this->clear_cache(); - Admin::clear_dismissed_notices(); - } - - /** - * Plugin uninstallation handler. Delete all settings and cache. - */ - public function uninstall() { - do_action( 'jetpack_boost_uninstall' ); - - Speed_Score_History::clear_all(); - $this->clear_cache(); - delete_option( apply_filters( 'jetpack_boost_options_store_key_name', 'jetpack_boost_config' ) ); - } - - /** - * Handlers for clearing module caches go here, so that caches get cleared even if the module is not enabled. - */ - public function register_cache_clear_actions() { - add_action( 'jetpack_boost_clear_cache', array( $this, 'record_clear_cache_event' ) ); - } - - /** - * Record the clear cache event. - */ - public function record_clear_cache_event() { + do_action( 'jetpack_boost_clear_cache' ); Analytics::record_user_event( 'clear_cache' ); - } - - /** - * Initialize modules. - * - * Note: this method ignores the nonce verification linter rule, as jb-disable-modules is intended to work - * without a nonce. - * - * phpcs:disable WordPress.Security.NonceVerification.Recommended - */ - public function prepare_modules() { - $available_modules = $this->get_available_modules(); - - $forced_disabled_modules = array(); - - // Get the lists of modules explicitly disabled from the 'jb-disable-modules' query string. - // The parameter is a comma separated value list of module slug. - if ( ! empty( $_GET['jb-disable-modules'] ) ) { - // phpcs:disable WordPress.Security.ValidatedSanitizedInput.MissingUnslash - // phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized - $forced_disabled_modules = array_map( 'sanitize_key', explode( ',', $_GET['jb-disable-modules'] ) ); - } - - foreach ( self::MODULES as $module_slug => $module_class ) { - // Don't register modules that have been forcibly disabled from the url 'jb-disable-modules' query string parameter. - if ( in_array( $module_slug, $forced_disabled_modules, true ) || in_array( 'all', $forced_disabled_modules, true ) ) { - continue; - } - - // All Jetpack Boost modules should extend Module class. - if ( ! is_subclass_of( $module_class, Module::class ) ) { - continue; - } - - // Don't register modules that aren't available. - if ( ! in_array( $module_slug, $available_modules, true ) ) { - continue; - } - - $module = new $module_class(); - $this->modules[ $module_slug ] = $module; - } - - do_action( 'jetpack_boost_modules_loaded' ); - } - - /** - * Initialize modules when WordPress is ready - */ - public function initialize_modules() { - foreach ( $this->modules as $module_slug => $module ) { - if ( true === $this->get_module_status( $module_slug ) ) { - $module->initialize(); - } - } - } - - /** - * Returns the list of available modules. - * - * @return array The available modules. - */ - public function get_available_modules() { - $available_modules = self::AVAILABLE_MODULES_DEFAULT; - - // Add the Lazy Images module if Jetpack Lazy Images module is enabled. - if ( Lazy_Images::is_jetpack_lazy_images_module_enabled() ) { - $available_modules = array_unique( array_merge( self::AVAILABLE_MODULES_DEFAULT, array( Lazy_Images::MODULE_SLUG ) ) ); - } - - return apply_filters( - 'jetpack_boost_modules', - $available_modules - ); - } - - /** - * Returns an array of active modules. - */ - public function get_active_modules() { - // Cache active modules. - static $active_modules = null; - if ( null !== $active_modules ) { - return $active_modules; - } - - return array_filter( - $this->modules, - function ( $module, $module_slug ) { - return true === $this->get_module_status( $module_slug ); - }, - ARRAY_FILTER_USE_BOTH - ); - } - - /** - * Returns the status of a given module. - * - * @param string $module_slug The module's slug. - * - * @return bool The enablement status of the module. - */ - public function get_module_status( $module_slug ) { - $default_module_status = in_array( $module_slug, self::ENABLED_MODULES_DEFAULT, true ); - - return apply_filters( 'jetpack_boost_module_enabled', $default_module_status, $module_slug ); - } - - /** - * Check if a module is enabled. - * - * @param boolean $is_enabled Default value. - * @param string $module_slug The module we are checking. - * - * @return mixed|null - */ - public function is_module_enabled( $is_enabled, $module_slug ) { - do_action( 'jetpack_boost_pre_is_module_enabled', $is_enabled, $module_slug ); - - return $this->config()->get_value( "$module_slug/enabled", $is_enabled ); - } - - /** - * Set status of a module. - * - * @param boolean $is_enabled Default value. - * @param string $module_slug The module we are checking. - */ - public function set_module_status( $is_enabled, $module_slug ) { - do_action( 'jetpack_boost_pre_set_module_status', $is_enabled, $module_slug ); - Analytics::record_user_event( - 'set_module_status', - array( - 'module' => $module_slug, - 'status' => $is_enabled, - ) - ); - $this->config()->set_value( "$module_slug/enabled", $is_enabled, true ); - } - - /** - * Get critical CSS viewport sizes. - * - * @param mixed $default The default value. - * - * @return mixed|null - */ - public function get_critical_css_viewport_sizes( $default ) { - return $this->config()->get_value( 'critical-css/settings/viewport_sizes', $default ); - } - - /** - * Get critical CSS default viewports. - * - * @param mixed $default The default value. - * - * @return mixed|null - */ - public function get_critical_css_default_viewports( $default ) { - return $this->config()->get_value( 'critical-css/settings/default_viewports', $default ); - } - - /** - * Get critical CSS ignore rules. - * - * @param mixed $default The default value. - * - * @return mixed|null - */ - public function get_critical_css_ignore_rules( $default ) { - return $this->config()->get_value( 'critical-css/settings/css-ignore-rules', $default ); - } - - /** - * Returns configuration array. - * - * @return Config Configuration array. - */ - public function config() { - if ( ! $this->config ) { - do_action( 'jetpack_boost_pre_get_config' ); - $this->config = Config::get( self::CURRENT_CONFIG_ID ); // under the hood, this actually fetches from an option, not the config cache. - } - - return apply_filters( 'jetpack_boost_config', $this->config ); - } - - /** - * Initialize config system. - * - * @todo This should be replaced by a proper configuration implementation eventually. - */ - public function init_config() { - add_action( 'switch_blog', array( $this, 'clear_memoized_config' ) ); - add_filter( 'jetpack_boost_module_enabled', array( $this, 'is_module_enabled' ), 0, 2 ); - add_filter( 'jetpack_boost_critical_css_viewport_sizes', array( $this, 'get_critical_css_viewport_sizes' ) ); - add_filter( 'jetpack_boost_critical_css_default_viewports', array( $this, 'get_critical_css_default_viewports' ) ); - add_filter( 'jetpack_boost_critical_css_ignore_rules', array( $this, 'get_critical_css_ignore_rules' ) ); - } - - /** - * Clear the memoized config, executed on `switch_blog` - */ - public function clear_memoized_config() { - $this->config = null; - } - - /** - * Returns a default config array. - * - * @return array Default config. - */ - public static function get_default_config_array() { - return apply_filters( - 'jetpack_boost_config_array', - array( - Render_Blocking_JS::MODULE_SLUG => array( - 'enabled' => false, - ), - Critical_CSS::MODULE_SLUG => array( - 'enabled' => false, - 'settings' => array( - 'viewport_sizes' => Viewport::DEFAULT_VIEWPORT_SIZES, - 'default_viewports' => Viewport::DEFAULT_VIEWPORTS, - 'css-ignore-rules' => array( - // TODO: Define if we need any default CSS ignore rules - // Example regex, exclude all css where there is a url inside. - 'url\(', - ), - ), - ), - Lazy_Images::MODULE_SLUG => array( - 'enabled' => false, - ), - 'show_rating_prompt' => true, - ) - ); + Admin::clear_dismissed_notices(); } /** * Initialize the admin experience. */ - public function init_admin() { - if ( ! apply_filters( 'jetpack_boost_connection_bypass', false ) ) { - $jetpack_config = new Jetpack_Config(); - $jetpack_config->ensure( - 'connection', - array( - 'slug' => 'jetpack-boost', - 'name' => 'Jetpack Boost', - 'url_info' => '', // Optional, URL of the plugin. - ) - ); - } - - /** - * The class responsible for defining all actions that occur in the admin area. - */ - require_once plugin_dir_path( __FILE__ ) . 'admin/class-admin.php'; - - new Admin( $this ); + public function init_admin( $modules ) { + REST_API::register( Optimization_Status::class ); + $this->connection->ensure_connection(); + new Admin( $modules ); } /** @@ -470,15 +139,6 @@ public function init_textdomain() { ); } - /** - * Registers the `jetpack_boost_url_ready` filter which allows modules to provide their readiness status. - */ - public function display_meta_field_module_ready() { - ?> - - version; } - /** - * Returns a list of admin notices to show. Asks each module to provide admin notices the user needs to see. - * - * @return \Automattic\Jetpack_Boost\Admin\Admin_Notice[] - */ - public function get_admin_notices() { - $all_notices = array(); - - foreach ( $this->get_active_modules() as $module ) { - $module_notices = $module->get_admin_notices(); - - if ( ! empty( $module_notices ) ) { - $all_notices = array_merge( $all_notices, $module_notices ); - } - } - - return $all_notices; - } - /** * Handle an environment change to set the correct status to the Critical CSS request. * This is done here so even if the Critical CSS module is switched off we can @@ -528,4 +169,28 @@ public function handle_theme_change() { Admin::clear_dismissed_notice( Regenerate_Admin_Notice::SLUG ); \update_option( Critical_CSS::RESET_REASON_STORAGE_KEY, Regenerate_Admin_Notice::REASON_THEME_CHANGE, false ); } + + /** + * Plugin uninstallation handler. Delete all settings and cache. + */ + public function uninstall() { + + global $wpdb; + + // When uninstalling, make sure all deactivation cleanups have run as well. + $this->deactivate(); + + // Delete all Jetpack Boost options. + $wpdb->query( + " + DELETE + FROM `$wpdb->options` + WHERE `option_name` LIKE jetpack_boost_% + " + ); + + // Delete stored Critical CSS. + ( new Critical_CSS_Storage() )->clear(); + + } } diff --git a/projects/plugins/boost/app/contracts/Feature.php b/projects/plugins/boost/app/contracts/Feature.php new file mode 100644 index 0000000000000..33edf2c86b622 --- /dev/null +++ b/projects/plugins/boost/app/contracts/Feature.php @@ -0,0 +1,11 @@ +feature = $feature; + $this->status = new Status( $feature->get_slug() ); + } +} diff --git a/projects/plugins/boost/app/features/optimizations/Optimizations.php b/projects/plugins/boost/app/features/optimizations/Optimizations.php new file mode 100644 index 0000000000000..a933dbeb54edd --- /dev/null +++ b/projects/plugins/boost/app/features/optimizations/Optimizations.php @@ -0,0 +1,127 @@ +get_slug(); + $this->features[ $slug ] = new Optimization( $feature ); + } + } + + public function available_modules() { + $forced_disabled_modules = $this->get_disabled_modules(); + + if ( empty( $forced_disabled_modules ) ) { + return $this->features; + } + + if ( array( 'all' ) === $forced_disabled_modules ) { + return array(); + } + + $available_modules = array(); + foreach ( $this->features as $slug => $feature ) { + if ( ! in_array( $slug, $forced_disabled_modules, true ) ) { + $available_modules[ $slug ] = $feature; + } + } + + return $available_modules; + } + + public function have_enabled_modules() { + return count( $this->get_status() ) > 0; + } + + public function get_status() { + $status = array(); + foreach ( $this->features as $slug => $optimization ) { + $status[ $slug ] = $optimization->status->is_enabled(); + } + return $status; + } + + public function register_endpoints( $feature ) { + if ( ! $feature instanceof Has_Endpoints ) { + return false; + } + + if ( empty( $feature->get_endpoints() ) ) { + return false; + } + + } + + /** + * @inheritDoc + */ + public function setup() { + + foreach ( $this->available_modules() as $slug => $optimization ) { + + if ( ! $optimization->status->is_enabled() ) { + continue; + } + + $optimization->feature->setup(); + $this->register_endpoints( $optimization->feature ); + + do_action( "jetpack_boost_{$slug}_initialized", $this ); + + } + } + + /** + * Get the lists of modules explicitly disabled from the 'jb-disable-modules' query string. + * The parameter is a comma separated value list of module slug. + * + * @return array + */ + + public function get_disabled_modules() { + // phpcs:disable WordPress.Security.NonceVerification.Recommended + if ( ! empty( $_GET['jb-disable-modules'] ) ) { + // phpcs:disable WordPress.Security.NonceVerification.Recommended + // phpcs:disable WordPress.Security.ValidatedSanitizedInput.MissingUnslash + // phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + return array_map( 'sanitize_key', explode( ',', $_GET['jb-disable-modules'] ) ); + } + + return array(); + } + + /** + * @inheritDoc + */ + public function setup_trigger() { + return 'plugins_loaded'; + } + +} diff --git a/projects/plugins/boost/app/modules/critical-css/class-admin-bar-css-compat.php b/projects/plugins/boost/app/features/optimizations/critical-css/Admin_Bar_Compatibilty.php similarity index 75% rename from projects/plugins/boost/app/modules/critical-css/class-admin-bar-css-compat.php rename to projects/plugins/boost/app/features/optimizations/critical-css/Admin_Bar_Compatibilty.php index 5d7924ac6bf13..a2f18f83e04c0 100644 --- a/projects/plugins/boost/app/modules/critical-css/class-admin-bar-css-compat.php +++ b/projects/plugins/boost/app/features/optimizations/critical-css/Admin_Bar_Compatibilty.php @@ -1,24 +1,11 @@ storage = new Critical_CSS_Storage(); + $this->paths = new Source_Providers(); + + } + + /** + * This is only run if Critical CSS module has been activated. + */ + public function setup() { + // Touch to setup the post type. This is a temporary hack. + // This should instantiate a new Post_Type_Storage class, + // so that Critical_CSS class is responsible + // for setting up the storage. + $recommendations = new Recommendations(); + $recommendations->attach_hooks(); + + add_action( 'wp', array( $this, 'display_critical_css' ) ); + + if ( Generator::is_generating_critical_css() ) { + add_action( 'wp_head', array( $this, 'display_generate_meta' ), 0 ); + $this->force_logged_out_render(); + } + + add_action( 'handle_theme_change', array( $this, 'clear_critical_css' ) ); + add_action( 'jetpack_boost_clear_cache', array( $this, 'clear_critical_css' ) ); + add_filter( 'jetpack_boost_js_constants', array( $this, 'add_critical_css_constants' ) ); + + REST_API::register( $this->get_endpoints() ); + return true; + } + + public function get_slug() { + return 'critical-css'; + } + + /** + * Renders a tag used to verify this is a valid page to generate Critical CSS with. + */ + public function display_generate_meta() { + ?> + + paths->get_current_request_css(); + if ( ! $critical_css ) { + return; + } + + $display = new Display_Critical_CSS( $critical_css ); + add_action( 'wp_head', array( $display, 'display_critical_css' ), 0 ); + add_filter( 'style_loader_tag', array( $display, 'asynchronize_stylesheets' ), 10, 4 ); + add_action( 'wp_footer', array( $display, 'onload_flip_stylesheets' ) ); + } + + /** + * Clear Critical CSS. + */ + public function clear_critical_css() { + // Mass invalidate all cached values. + // ^^ Not true anymore. Mass invalidate __some__ cached values. + $this->storage->clear(); + Critical_CSS_State::reset(); + } + + /** + * Force the current page to render as viewed by a logged out user. Useful when generating + * Critical CSS. + */ + private function force_logged_out_render() { + $current_user_id = get_current_user_id(); + + if ( 0 !== $current_user_id ) { + // Force current user to 0 to ensure page is rendered as a non-logged-in user. + wp_set_current_user( 0 ); + + // Turn off display of admin bar. + add_filter( 'show_admin_bar', '__return_false', PHP_INT_MAX ); + } + } + + /** + * Override; returns an admin notice to show if there was a reset reason. + * + * @TODO: + * There should be an Admin_Notice class + * To create a notice, (new Admin_Notice())->create("notice text"); + * To view notices: (new Admin_Notice())->get_all(); + * @return null|\Automattic\Jetpack_Boost\Admin\Admin_Notice[] + */ + public function get_admin_notices() { + $reason = \get_option( self::RESET_REASON_STORAGE_KEY ); + + if ( ! $reason ) { + return array(); + } + + return array( new Regenerate_Admin_Notice( $reason ) ); + } + + /** + * Clear Critical CSS reset reason option. + * + * @TODO: Admin notices need to be moved elsewhere. + * Note: Looks like we need a way to and options throughout the app. + * This is why it's currently awkwardly using a static method with a constant + * If we could trust classes to use constructors properly - without performing actions + * Then we could easily (and cheaply) instantiate all Boost objects + * and kindly ask them to delete themselves + */ + public static function clear_reset_reason() { + \delete_option( self::RESET_REASON_STORAGE_KEY ); + } + + /** + * Add Critical CSS related constants to be passed to JavaScript only if the module is enabled. + * + * @param array $constants Constants to be passed to JavaScript. + * + * @return array + */ + public function add_critical_css_constants( $constants ) { + // Information about the current status of Critical CSS / generation. + $generator = new Generator(); + $constants['criticalCssStatus'] = $generator->get_local_critical_css_generation_info(); + + return $constants; + } + + /** + * @TODO: Facepalm. PHP Typehinting is broken. + * @return Endpoint[] + * + */ + public function get_endpoints() { + return array( + Generator_Status::class, + Generator_Request::class, + Generator_Success::class, + Recommendations_Dismiss::class, + Recommendations_Reset::class, + Generator_Error::class, + ); + } + + /** + * @inheritDoc + */ + public function setup_trigger() { + return 'init'; + } +} diff --git a/projects/plugins/boost/app/modules/critical-css/class-critical-css-state.php b/projects/plugins/boost/app/features/optimizations/critical-css/Critical_CSS_State.php similarity index 97% rename from projects/plugins/boost/app/modules/critical-css/class-critical-css-state.php rename to projects/plugins/boost/app/features/optimizations/critical-css/Critical_CSS_State.php index 1768bd0227abc..e5867d9887da1 100644 --- a/projects/plugins/boost/app/modules/critical-css/class-critical-css-state.php +++ b/projects/plugins/boost/app/features/optimizations/critical-css/Critical_CSS_State.php @@ -7,10 +7,9 @@ * @package automattic/jetpack-boost */ -namespace Automattic\Jetpack_Boost\Modules\Critical_CSS; +namespace Automattic\Jetpack_Boost\Features\Optimizations\Critical_CSS; use Automattic\Jetpack_Boost\Lib\Transient; -use Automattic\Jetpack_Boost\Modules\Critical_CSS\Providers\Provider; /** * Critical CSS State @@ -203,11 +202,6 @@ public function get_core_providers_status( $keys ) { protected function get_provider_sources( $providers ) { $sources = array(); - /** - * Provider. - * - * @var $provider Provider - */ foreach ( $providers as $provider ) { $provider_name = $provider::get_provider_name(); @@ -382,7 +376,7 @@ public function get_percent_complete() { /** * Reset the Critical CSS state. */ - public function reset() { + public static function reset() { Transient::delete( self::KEY ); } diff --git a/projects/plugins/boost/app/modules/critical-css/class-critical-css-storage.php b/projects/plugins/boost/app/features/optimizations/critical-css/Critical_CSS_Storage.php similarity index 94% rename from projects/plugins/boost/app/modules/critical-css/class-critical-css-storage.php rename to projects/plugins/boost/app/features/optimizations/critical-css/Critical_CSS_Storage.php index 29f233f445fe5..820b560ac3de3 100644 --- a/projects/plugins/boost/app/modules/critical-css/class-critical-css-storage.php +++ b/projects/plugins/boost/app/features/optimizations/critical-css/Critical_CSS_Storage.php @@ -7,7 +7,7 @@ * @package automattic/jetpack-boost */ -namespace Automattic\Jetpack_Boost\Modules\Critical_CSS; +namespace Automattic\Jetpack_Boost\Features\Optimizations\Critical_CSS; use Automattic\Jetpack_Boost\Lib\Storage_Post_Type; diff --git a/projects/plugins/boost/app/features/optimizations/critical-css/Display_Critical_CSS.php b/projects/plugins/boost/app/features/optimizations/critical-css/Display_Critical_CSS.php new file mode 100644 index 0000000000000..35cf33817306c --- /dev/null +++ b/projects/plugins/boost/app/features/optimizations/critical-css/Display_Critical_CSS.php @@ -0,0 +1,149 @@ +css = $css; + } + + /** + * Converts existing screen CSS to be asynchronously loaded. + * + * @param string $html The link tag for the enqueued style. + * @param string $handle The style's registered handle. + * @param string $href The stylesheet's source URL. + * @param string $media The stylesheet's media attribute. + * + * @return string + * @see style_loader_tag + */ + public function asynchronize_stylesheets( + $html, + $handle, + $href, + $media + ) { + // If there is no critical CSS, do not alter the stylesheet loading. + if ( false === $this->css ) { + return $html; + } + + $available_methods = array( + 'async' => 'media="not all" data-media="' . $media . '" onload="this.media=this.dataset.media; delete this.dataset.media; this.removeAttribute( \'onload\' );"', + 'deferred' => 'media="not all" data-media="' . $media . '"', + ); + + /** + * Loading method for stylesheets. + * + * Filter the loading method for each stylesheet for the screen with following values: + * async - Stylesheets are loaded asynchronously. + * Styles are applied once the stylesheet is loaded completely without render blocking. + * deferred - Loading of stylesheets are deferred until the window load event. + * Styles from all the stylesheets are applied at once after the page load. + * + * Stylesheet loading behaviour is not altered for any other value such as false or 'default'. + * Stylesheet loading is instant and the process blocks the page rendering. + * Eg: add_filter( 'jetpack_boost_async_style', '__return_false' ); + * + * @param string $handle The style's registered handle. + * @param string $media The stylesheet's media attribute. + * + * @see onload_flip_stylesheets for how stylesheets loading is deferred. + * + * @todo Retrieve settings from database, either via auto-configuration or UI option. + */ + $method = apply_filters( 'jetpack_boost_async_style', 'async', $handle, $media ); + + // If the loading method is not allowed, do not alter the stylesheet loading. + if ( ! isset( $available_methods[ $method ] ) ) { + return $html; + } + + $html_no_script = ''; + + // Update the stylesheet markup for allowed methods. + $html = preg_replace( '~media=(\'[^\']+\')|("[^"]+")~', $available_methods[ $method ], $html ); + + // Append to the HTML stylesheet tag the same untouched HTML stylesheet tag within the noscript tag + // to support the rendering of the stylesheet when JavaScript is disabled. + return $html_no_script . $html; + } + + /** + * Prints the critical CSS to the page. + */ + public function display_critical_css() { + $critical_css = $this->css; + + if ( false === $critical_css ) { + return false; + } + + echo ' tag (or any HTML tags) in output. + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo wp_strip_all_tags( $critical_css ); + + echo ''; + } + + /** + * Add a small piece of JavaScript to the footer, which on load flips all + * linked stylesheets from media="not all" to "all", and switches the + * Critical CSS tag (or any HTML tags) in output. - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - echo wp_strip_all_tags( $critical_css ); - - echo ''; - } - - /** - * Check if the current URL is warmed up. For this module, "warmed up" means that - * either Critical CSS has been generated for this page, or this page is not - * eligible to have Critical CSS generated for it. - * - * @param bool $ready Injected filter value. - * - * @return bool - */ - public function is_ready_filter( $ready ) { - if ( ! $ready ) { - return $ready; - } - - // If this page has no provider keys, it is ineligible for Critical CSS. - $keys = $this->get_current_request_css_keys(); - if ( count( $keys ) === 0 ) { - return true; - } - - // Return "ready" if Critical CSS has been generated. - return ! empty( $this->get_critical_css() ); - } - - /** - * Force the current page to render as viewed by a logged out user. Useful when generating - * Critical CSS. - */ - private function force_logged_out_render() { - $current_user_id = get_current_user_id(); - - if ( 0 !== $current_user_id ) { - // Force current user to 0 to ensure page is rendered as a non-logged-in user. - wp_set_current_user( 0 ); - - // Turn off display of admin bar. - add_filter( 'show_admin_bar', '__return_false', PHP_INT_MAX ); - } - } - - /** - * AJAX handler to handle proxying of external CSS resources. - */ - public function handle_css_proxy() { - // Verify valid nonce. - if ( empty( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['nonce'] ), self::GENERATE_PROXY_NONCE ) ) { - wp_die( '', 400 ); - } - - // Make sure currently logged in as admin. - if ( ! $this->current_user_can_modify_critical_css() ) { - wp_die( '', 400 ); - } - - // Reject any request made when not generating. - if ( ! $this->state->is_pending() ) { - wp_die( '', 400 ); - } - - // Validate URL and fetch. - $proxy_url = filter_var( wp_unslash( $_POST['proxy_url'] ), FILTER_VALIDATE_URL ); - if ( ! wp_http_validate_url( $proxy_url ) ) { - die( 'Invalid URL' ); - } - - $response = wp_remote_get( $proxy_url ); - if ( is_wp_error( $response ) ) { - // TODO: Nicer error handling. - die( 'error' ); - } - - header( 'Content-type: text/css' ); - - // Outputting proxied CSS contents unescaped. - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - echo wp_strip_all_tags( $response['body'] ); - - die(); - } - - /** - * API helper for ensuring this module is enabled before allowing an API - * endpoint to continue. Will die if this module is not initialized, with - * a status message indicating so. - */ - public function ensure_module_initialized() { - if ( ! $this->is_initialized() ) { - wp_send_json( array( 'status' => 'module-unavailable' ) ); - } - } - - /** - * Add a small piece of JavaScript to the footer, which on load flips all - * linked stylesheets from media="not all" to "all", and switches the - * Critical CSS