diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index c3e90bc18ad8..44b409ea7e1f 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -1,7 +1,7 @@ name: auto-merge on: - pull_request: + pull_request_target: branches: - main @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest if: github.actor == 'dependabot[bot]' steps: - - uses: ahmadnassri/action-dependabot-auto-merge@v2.3 + - uses: ahmadnassri/action-dependabot-auto-merge@v2.4 with: github-token: ${{ secrets.AUTOMERGE_TOKEN }} command: "squash and merge" diff --git a/.github/workflows/content-origin-request.yml b/.github/workflows/content-origin-request.yml new file mode 100644 index 000000000000..d5637420608b --- /dev/null +++ b/.github/workflows/content-origin-request.yml @@ -0,0 +1,62 @@ +# This starts up a simulator that tries to do what our Lambda@Edge does. + +name: content-origin-request + +on: + pull_request: + branches: + - main + paths: + - deployer/aws-lambda/** + - libs/** + - .github/workflows/content-origin-request.yml + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Setup Node.js environment + uses: actions/setup-node@v2.1.5 + with: + node-version: "12" + + - name: Cache node_modules + uses: actions/cache@v2.1.4 + id: cached-node_modules + with: + path: | + deployer/aws-lambda/content-origin-request/node_modules + key: ${{ runner.os }}-${{ hashFiles('deployer/aws-lambda/content-origin-request/yarn.lock') }}-${{ hashFiles('libs/**/*.js') }} + + - name: Install all yarn packages + if: steps.cached-node_modules.outputs.cache-hit != 'true' + working-directory: deployer/aws-lambda/content-origin-request + run: yarn --frozen-lockfile + + - name: Run test server + working-directory: deployer/aws-lambda/content-origin-request + run: | + yarn serve > /tmp/stdout.log 2> /tmp/stderr.log & + + - name: Check that the server started + run: curl --retry-connrefused --retry 5 -I http://localhost:7000/ping + + - name: Preflight the integration tests + run: | + curl -I http://localhost:7000/docs/Web + curl -I http://localhost:7000/en-US/docs/Web/ + + - name: Unit test + working-directory: deployer/aws-lambda/content-origin-request + run: | + yarn test-server + + - name: Debug any server outputs + run: | + echo "____STDOUT____" + cat /tmp/stdout.log + echo "____STDERR____" + cat /tmp/stderr.log diff --git a/.github/workflows/dev-build.yml b/.github/workflows/dev-build.yml index e9dc381a6025..f38427d16951 100644 --- a/.github/workflows/dev-build.yml +++ b/.github/workflows/dev-build.yml @@ -21,10 +21,6 @@ on: description: "Build archived content" required: false default: "false" - translated_content: - description: "Build translated content" - required: false - default: "true" # This is very useful when combined with the "Use workflow from" # feature that is built into the "Run workflow" button on @@ -66,13 +62,12 @@ jobs: path: mdn/archived-content - uses: actions/checkout@v2 - if: "contains(github.event.inputs.translated_content, 'true')" with: - repository: mdn/translated-content-rendered + repository: mdn/translated-content path: mdn/translated-content - name: Setup Node.js environment - uses: actions/setup-node@v2.1.4 + uses: actions/setup-node@v2.1.5 with: node-version: "12" @@ -96,7 +91,7 @@ jobs: python-version: "3.8" - name: Install Python poetry - uses: snok/install-poetry@v1.1.1 + uses: snok/install-poetry@v1.1.2 - name: Install deployer run: | @@ -112,7 +107,6 @@ jobs: run: | echo "notes: ${{ github.event.inputs.notes }}" echo "archived_content: ${{ github.event.inputs.archived_content }}" - echo "translated_content: ${{ github.event.inputs.translated_content }}" echo "log_each_successful_upload: ${{ github.event.inputs.log_each_successful_upload }}" echo "deployment_prefix: ${{ github.event.inputs.deployment_prefix }}" @@ -121,6 +115,7 @@ jobs: # Remember, the mdn/content repo got cloned into `pwd` into a # sub-folder called "mdn/content" CONTENT_ROOT: ${{ github.workspace }}/mdn/content/files + CONTENT_TRANSLATED_ROOT: ${{ github.workspace }}/mdn/translated-content/files # This basically means that all live-sample iframes run on the same # host as the page that includes the iframe. Not great security but the @@ -152,12 +147,6 @@ jobs: else echo "Will NOT build mdn/archived-content too" fi - if [ ${{ github.event.inputs.translated_content }} == "true" ]; then - echo "Will build mdn/translated-content too" - export CONTENT_TRANSLATED_ROOT=${{ github.workspace }}/mdn/translated-content/files - else - echo "Will NOT build mdn/translated-content too" - fi # Info about which CONTENT_* environment variables were set and to what. echo "CONTENT_ROOT=$CONTENT_ROOT" @@ -165,6 +154,7 @@ jobs: echo "CONTENT_TRANSLATED_ROOT=$CONTENT_TRANSLATED_ROOT" yarn prepare-build + yarn tool sync-translated-content yarn build # TODO: When the deployer is available this is where we @@ -175,6 +165,7 @@ jobs: env: # Set the CONTENT_ROOT first CONTENT_ROOT: ${{ github.workspace }}/mdn/content/files + CONTENT_TRANSLATED_ROOT: ${{ github.workspace }}/mdn/translated-content/files DEPLOYER_BUCKET_NAME: mdn-content-dev DEPLOYER_BUCKET_PREFIX: ${{ github.event.inputs.deployment_prefix }} @@ -209,10 +200,11 @@ jobs: poetry run deployer whatsdeployed --output ../client/build/_whatsdeployed/code.json poetry run deployer whatsdeployed --output ../client/build/_whatsdeployed/content.json $CONTENT_ROOT + poetry run deployer whatsdeployed --output ../client/build/_whatsdeployed/translated-content.json $CONTENT_TRANSLATED_ROOT # XXX would be nice to validate here that $DEPLOYER_BUCKET_PREFIX is truthy echo "DEPLOYER_BUCKET_PREFIX=$DEPLOYER_BUCKET_PREFIX" - poetry run deployer upload ../client/build + poetry run deployer upload --prune ../client/build poetry run deployer update-lambda-functions ./aws-lambda # TODO # Execute command to tell the Dev CloudFront distribution to use the diff --git a/.github/workflows/developing.yml b/.github/workflows/developing.yml index e8a308c1eec9..d3ffdfb494e5 100644 --- a/.github/workflows/developing.yml +++ b/.github/workflows/developing.yml @@ -16,7 +16,7 @@ jobs: path: mdn/content - name: Setup Node.js environment - uses: actions/setup-node@v2.1.4 + uses: actions/setup-node@v2.1.5 with: node-version: "12" @@ -62,7 +62,7 @@ jobs: - name: Wait for servers run: | # Just a slight delay to wait until the dev server is ready. - sleep 5 + sleep 3 curl --retry-connrefused --retry 5 http://localhost:5000 > /dev/null curl --retry-connrefused --retry 5 --silent http://localhost:3000 > /dev/null @@ -76,15 +76,13 @@ jobs: # of the yarn installs above PUPPETEER_EXECUTABLE_PATH: /usr/bin/google-chrome run: | - status=0 - yarn test:testing developing || ( - status=$? - echo "Testing failed! Going to dump stdout and stderr" - echo "STDOUT..................................................." - cat /tmp/stdout.log - echo "STDERR..................................................." - cat /tmp/stderr.log - echo $status - exit $status - ) - exit $status + yarn test:testing developing + + - name: Debug server's stdout and stderr if tests failed + if: failure() + run: | + echo "STDOUT..................................................." + cat /tmp/stdout.log + echo "" + echo "STDERR..................................................." + cat /tmp/stderr.log diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index daaed940d367..68570660e866 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -21,7 +21,7 @@ jobs: fetch-depth: 10 - name: Setup Node.js environment - uses: actions/setup-node@v2.1.4 + uses: actions/setup-node@v2.1.5 with: node-version: "12" diff --git a/.github/workflows/npm-published-simulation.yml b/.github/workflows/npm-published-simulation.yml new file mode 100644 index 000000000000..ca13f0914828 --- /dev/null +++ b/.github/workflows/npm-published-simulation.yml @@ -0,0 +1,113 @@ +# Instead of waiting for Yari to be published to npmjs.com and be upgraded +# inside mdn/content by Dependabot, we do all those steps here using `npm pack`. + +name: NPM Publish simulation + +on: + pull_request: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: actions/checkout@v2 + with: + repository: mdn/content + path: mdn/content + + - name: Setup Node.js environment + uses: actions/setup-node@v2.1.5 + with: + node-version: "12" + + - name: Cache node_modules + uses: actions/cache@v2.1.4 + id: cached-node_modules + with: + path: | + node_modules + key: ${{ runner.os }}-${{ hashFiles('yarn.lock') }} + + - name: Install all yarn packages + if: steps.cached-node_modules.outputs.cache-hit != 'true' + env: + PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: 1 + run: yarn --frozen-lockfile + + - name: Setup kernel for react native, increase watchers + run: | + # When running Yari on Linux, you might get the + # "Error: ENOSPC: System limit for number of file watchers reached" error. + # This, resolves that. + # Source https://github.com/expo/expo-github-action/issues/20#issuecomment-541676895 + echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p + + - name: Prepare to build + env: + # The following env vars is what we do in npm-publish.yml + # Each variable set is documented there. + + REACT_APP_CRUD_MODE: true + REACT_APP_DISABLE_AUTH: true + CONTENT_ROOT: testing/content/files + run: | + yarn prepare-build + + - name: Build and install tarball + run: | + echo mdn/content/ >> .npmignore + npm pack + TARBALL=`ls mdn-yari-*.tgz` + echo $TARBALL + ls -lh $TARBALL + mv $TARBALL mdn/content/ + cd mdn/content + yarn add file:$TARBALL + + - name: Start Yari from mock content repo + working-directory: mdn/content + run: | + yarn start > /tmp/stdout.log 2> /tmp/stderr.log & + + - name: View some URLs on localhost:5000 + run: | + curl --retry-connrefused --retry 5 -I http://localhost:5000 + + # Basically, test if it 200 OKs. If not, this'll exit non-zero. + curl http://localhost:5000/en-US/ > /dev/null + curl http://localhost:5000/en-US/docs/MDN/Kitchensink > /dev/null + + - name: Test viewing the dev server + env: + # This will make sure the tests in `testing/tests/*.test.js` only run + # if the development server is up and ready to be tested. + TESTING_DEVELOPING: true + # Use local chrome installs since we skip downloading it as part + # of the yarn installs above + PUPPETEER_EXECUTABLE_PATH: /usr/bin/google-chrome + # When running Yari from within mdn/content it only starts 1 server; + # the one on localhost:5000. No React dev server; the one + # on localhost:3000. + # Testing that dev server is not relevant or important in this context. + DEVELOPING_SKIP_DEV_URL: true + run: | + yarn test:testing developing + + - name: Debug server's stdout and stderr if tests failed + if: failure() + run: | + echo "STDOUT..................................................." + cat /tmp/stdout.log + echo "" + echo "STDERR..................................................." + cat /tmp/stderr.log + + - name: SSR build a page + working-directory: mdn/content + run: | + yarn build files/en-us/mdn/kitchensink/index.html diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml index 4404aac99750..6614649667ea 100644 --- a/.github/workflows/performance.yml +++ b/.github/workflows/performance.yml @@ -2,6 +2,11 @@ name: Performance on: pull_request: + paths: + - client/src/** + - .github/workflows/performance.yml + - package.json + - yarn.lock jobs: lighthouse: @@ -20,7 +25,7 @@ jobs: path: mdn/content - name: Setup Node.js environment - uses: actions/setup-node@v2.1.4 + uses: actions/setup-node@v2.1.5 with: node-version: "12" diff --git a/.github/workflows/pr-deployer.yml b/.github/workflows/pr-deployer.yml index c5570af173b2..fe8543e52715 100644 --- a/.github/workflows/pr-deployer.yml +++ b/.github/workflows/pr-deployer.yml @@ -19,7 +19,7 @@ jobs: python-version: "3.8" - name: Install Python poetry - uses: snok/install-poetry@v1.1.1 + uses: snok/install-poetry@v1.1.2 with: virtualenvs-create: true virtualenvs-in-project: true diff --git a/.github/workflows/pr-docs.yml b/.github/workflows/pr-docs.yml index 5851f53a70da..2225ed617504 100644 --- a/.github/workflows/pr-docs.yml +++ b/.github/workflows/pr-docs.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v2 - name: Setup Node.js environment - uses: actions/setup-node@v2.1.4 + uses: actions/setup-node@v2.1.5 with: node-version: "12" diff --git a/.github/workflows/pr-kumascript.yml b/.github/workflows/pr-kumascript.yml index 29b0928e0333..abd5f076fc76 100644 --- a/.github/workflows/pr-kumascript.yml +++ b/.github/workflows/pr-kumascript.yml @@ -24,7 +24,7 @@ jobs: - uses: actions/checkout@v2 - name: Setup Node.js environment - uses: actions/setup-node@v2.1.4 + uses: actions/setup-node@v2.1.5 with: node-version: "12" diff --git a/.github/workflows/prod-build.yml b/.github/workflows/prod-build.yml index fd39b54d66c4..faf02fdee7b6 100644 --- a/.github/workflows/prod-build.yml +++ b/.github/workflows/prod-build.yml @@ -13,7 +13,6 @@ env: DEFAULT_DEPLOYMENT_PREFIX: "main" DEFAULT_NOTES: "" DEFAULT_ARCHIVED_CONTENT: "false" - DEFAULT_TRANSLATED_CONTENT: "true" DEFAULT_LOG_EACH_SUCCESSFUL_UPLOAD: "false" on: @@ -31,10 +30,6 @@ on: description: "Build archived content" required: false default: ${DEFAULT_ARCHIVED_CONTENT} - translated_content: - description: "Build translated content" - required: false - default: ${DEFAULT_TRANSLATED_CONTENT} # This is very useful when combined with the "Use workflow from" # feature that is built into the "Run workflow" button on @@ -78,7 +73,6 @@ jobs: # can refer to later in `if: ....` lines or in bash with the `run: ...` blocks. - name: Merge dispatch inputs with default env vars run: | - echo "BUILD_TRANSLATED_CONTENT=${{ github.event.inputs.translated_content || env.DEFAULT_TRANSLATED_CONTENT }}" >> $GITHUB_ENV echo "BUILD_ARCHIVED_CONTENT=${{ github.event.inputs.archived_content || env.DEFAULT_ARCHIVED_CONTENT }}" >> $GITHUB_ENV echo "DEPLOYER_BUCKET_PREFIX=${{ github.event.inputs.deployment_prefix || env.DEFAULT_DEPLOYMENT_PREFIX }}" >> $GITHUB_ENV echo "DEPLOYER_LOG_EACH_SUCCESSFUL_UPLOAD=${{ github.event.inputs.log_each_successful_upload || env.DEFAULT_LOG_EACH_SUCCESSFUL_UPLOAD }}" >> $GITHUB_ENV @@ -90,13 +84,12 @@ jobs: path: mdn/archived-content - uses: actions/checkout@v2 - if: "contains(env.BUILD_TRANSLATED_CONTENT, 'true')" with: - repository: mdn/translated-content-rendered + repository: mdn/translated-content path: mdn/translated-content - name: Setup Node.js environment - uses: actions/setup-node@v2.1.4 + uses: actions/setup-node@v2.1.5 with: node-version: "12" @@ -120,7 +113,7 @@ jobs: python-version: "3.8" - name: Install Python poetry - uses: snok/install-poetry@v1.1.1 + uses: snok/install-poetry@v1.1.2 - name: Install deployer run: | @@ -136,10 +129,8 @@ jobs: run: | echo "notes: ${{ github.event.inputs.notes || env.DEFAULT_NOTES }}" echo "archived_content: ${{ github.event.inputs.archived_content || env.DEFAULT_ARCHIVED_CONTENT }}" - echo "translated_content: ${{ github.event.inputs.translated_content || env.DEFAULT_TRANSLATED_CONTENT }}" echo "log_each_successful_upload: ${{ github.event.inputs.log_each_successful_upload || env.DEFAULT_LOG_EACH_SUCCESSFUL_UPLOAD }}" echo "deployment_prefix: ${{ github.event.inputs.deployment_prefix || env.DEFAULT_DEPLOYMENT_PREFIX }}" - echo "BUILD_TRANSLATED_CONTENT: ${{ env.BUILD_TRANSLATED_CONTENT }}" echo "BUILD_ARCHIVED_CONTENT: ${{ env.BUILD_ARCHIVED_CONTENT }}" - name: Build everything @@ -147,6 +138,7 @@ jobs: # Remember, the mdn/content repo got cloned into `pwd` into a # sub-folder called "mdn/content" CONTENT_ROOT: ${{ github.workspace }}/mdn/content/files + CONTENT_TRANSLATED_ROOT: ${{ github.workspace }}/mdn/translated-content/files # The default for this environment variable is geared for writers # (aka. local development). Usually defaults are supposed to be for @@ -174,12 +166,6 @@ jobs: else echo "Will NOT build mdn/archived-content too" fi - if [ ${{ env.BUILD_TRANSLATED_CONTENT }} == "true" ]; then - echo "Will build mdn/translated-content too" - export CONTENT_TRANSLATED_ROOT=${{ github.workspace }}/mdn/translated-content/files - else - echo "Will NOT build mdn/translated-content too" - fi # Info about which CONTENT_* environment variables were set and to what. echo "CONTENT_ROOT=$CONTENT_ROOT" @@ -187,6 +173,7 @@ jobs: echo "CONTENT_TRANSLATED_ROOT=$CONTENT_TRANSLATED_ROOT" yarn prepare-build + yarn tool sync-translated-content yarn build du -sh client/build @@ -199,6 +186,7 @@ jobs: # Set the CONTENT_ROOT first CONTENT_ROOT: ${{ github.workspace }}/mdn/content/files + CONTENT_TRANSLATED_ROOT: ${{ github.workspace }}/mdn/translated-content/files DEPLOYER_BUCKET_NAME: mdn-content-prod @@ -222,12 +210,6 @@ jobs: else echo "Will NOT build mdn/archived-content too" fi - if [ ${{ env.BUILD_TRANSLATED_CONTENT }} == "true" ]; then - echo "Will build mdn/translated-content too" - export CONTENT_TRANSLATED_ROOT=${{ github.workspace }}/mdn/translated-content/files - else - echo "Will NOT build mdn/translated-content too" - fi # Info about which CONTENT_* environment variables were set and to what. echo "CONTENT_ROOT=$CONTENT_ROOT" @@ -238,6 +220,7 @@ jobs: poetry run deployer whatsdeployed --output ../client/build/_whatsdeployed/code.json poetry run deployer whatsdeployed --output ../client/build/_whatsdeployed/content.json $CONTENT_ROOT + poetry run deployer whatsdeployed --output ../client/build/_whatsdeployed/translated-content.json $CONTENT_TRANSLATED_ROOT # XXX would be nice to validate here that $DEPLOYER_BUCKET_PREFIX is truthy echo "DEPLOYER_BUCKET_PREFIX=$DEPLOYER_BUCKET_PREFIX" diff --git a/.github/workflows/stage-build.yml b/.github/workflows/stage-build.yml index 6335034f50bd..527987bd1184 100644 --- a/.github/workflows/stage-build.yml +++ b/.github/workflows/stage-build.yml @@ -13,7 +13,6 @@ env: DEFAULT_DEPLOYMENT_PREFIX: "main" DEFAULT_NOTES: "" DEFAULT_ARCHIVED_CONTENT: "false" - DEFAULT_TRANSLATED_CONTENT: "true" DEFAULT_LOG_EACH_SUCCESSFUL_UPLOAD: "false" on: @@ -31,10 +30,6 @@ on: description: "Build archived content" required: false default: ${DEFAULT_ARCHIVED_CONTENT} - translated_content: - description: "Build translated content" - required: false - default: ${DEFAULT_TRANSLATED_CONTENT} # This is very useful when combined with the "Use workflow from" # feature that is built into the "Run workflow" button on @@ -78,7 +73,6 @@ jobs: # can refer to later in `if: ....` lines or in bash with the `run: ...` blocks. - name: Merge dispatch inputs with default env vars run: | - echo "BUILD_TRANSLATED_CONTENT=${{ github.event.inputs.translated_content || env.DEFAULT_TRANSLATED_CONTENT }}" >> $GITHUB_ENV echo "BUILD_ARCHIVED_CONTENT=${{ github.event.inputs.archived_content || env.DEFAULT_ARCHIVED_CONTENT }}" >> $GITHUB_ENV echo "DEPLOYER_BUCKET_PREFIX=${{ github.event.inputs.deployment_prefix || env.DEFAULT_DEPLOYMENT_PREFIX }}" >> $GITHUB_ENV echo "DEPLOYER_LOG_EACH_SUCCESSFUL_UPLOAD=${{ github.event.inputs.log_each_successful_upload || env.DEFAULT_LOG_EACH_SUCCESSFUL_UPLOAD }}" >> $GITHUB_ENV @@ -90,13 +84,12 @@ jobs: path: mdn/archived-content - uses: actions/checkout@v2 - if: "contains(env.BUILD_TRANSLATED_CONTENT, 'true')" with: - repository: mdn/translated-content-rendered + repository: mdn/translated-content path: mdn/translated-content - name: Setup Node.js environment - uses: actions/setup-node@v2.1.4 + uses: actions/setup-node@v2.1.5 with: node-version: "12" @@ -120,7 +113,7 @@ jobs: python-version: "3.8" - name: Install Python poetry - uses: snok/install-poetry@v1.1.1 + uses: snok/install-poetry@v1.1.2 - name: Install deployer run: | @@ -136,10 +129,8 @@ jobs: run: | echo "notes: ${{ github.event.inputs.notes || env.DEFAULT_NOTES }}" echo "archived_content: ${{ github.event.inputs.archived_content || env.DEFAULT_ARCHIVED_CONTENT }}" - echo "translated_content: ${{ github.event.inputs.translated_content || env.DEFAULT_TRANSLATED_CONTENT }}" echo "log_each_successful_upload: ${{ github.event.inputs.log_each_successful_upload || env.DEFAULT_LOG_EACH_SUCCESSFUL_UPLOAD }}" echo "deployment_prefix: ${{ github.event.inputs.deployment_prefix || env.DEFAULT_DEPLOYMENT_PREFIX }}" - echo "BUILD_TRANSLATED_CONTENT: ${{ env.BUILD_TRANSLATED_CONTENT }}" echo "BUILD_ARCHIVED_CONTENT: ${{ env.BUILD_ARCHIVED_CONTENT }}" - name: Build everything @@ -147,6 +138,7 @@ jobs: # Remember, the mdn/content repo got cloned into `pwd` into a # sub-folder called "mdn/content" CONTENT_ROOT: ${{ github.workspace }}/mdn/content/files + CONTENT_TRANSLATED_ROOT: ${{ github.workspace }}/mdn/translated-content/files # The default for this environment variable is geared for writers # (aka. local development). Usually defaults are supposed to be for @@ -172,6 +164,14 @@ jobs: # '' nomatter what # kind of document it is. BUILD_ALWAYS_NO_ROBOTS: true + + # (peterbe, Mar 2021) This is unique to Stage and temporary. We want to + # test the new Yari-based sign-in and sign-up. Setting this environment + # variable changes the behavior of the "Sign in" link in the top navbar. + # Once we know for sure that this new Yari sign in/up is working in Stage + # we'll make this the new default can we can remove these lines. + REACT_APP_USE_YARI_SIGNIN: true + run: | if [ ${{ env.BUILD_ARCHIVED_CONTENT }} == "true" ]; then echo "Will build mdn/archived-content too" @@ -179,12 +179,6 @@ jobs: else echo "Will NOT build mdn/archived-content too" fi - if [ ${{ env.BUILD_TRANSLATED_CONTENT }} == "true" ]; then - echo "Will build mdn/translated-content too" - export CONTENT_TRANSLATED_ROOT=${{ github.workspace }}/mdn/translated-content/files - else - echo "Will NOT build mdn/translated-content too" - fi # Info about which CONTENT_* environment variables were set and to what. echo "CONTENT_ROOT=$CONTENT_ROOT" @@ -192,6 +186,7 @@ jobs: echo "CONTENT_TRANSLATED_ROOT=$CONTENT_TRANSLATED_ROOT" yarn prepare-build + yarn tool sync-translated-content yarn build du -sh client/build @@ -204,6 +199,7 @@ jobs: # Set the CONTENT_ROOT first CONTENT_ROOT: ${{ github.workspace }}/mdn/content/files + CONTENT_TRANSLATED_ROOT: ${{ github.workspace }}/mdn/translated-content/files DEPLOYER_BUCKET_NAME: mdn-content-stage @@ -227,12 +223,6 @@ jobs: else echo "Will NOT build mdn/archived-content too" fi - if [ ${{ env.BUILD_TRANSLATED_CONTENT }} == "true" ]; then - echo "Will build mdn/translated-content too" - export CONTENT_TRANSLATED_ROOT=${{ github.workspace }}/mdn/translated-content/files - else - echo "Will NOT build mdn/translated-content too" - fi # Info about which CONTENT_* environment variables were set and to what. echo "CONTENT_ROOT=$CONTENT_ROOT" @@ -243,10 +233,11 @@ jobs: poetry run deployer whatsdeployed --output ../client/build/_whatsdeployed/code.json poetry run deployer whatsdeployed --output ../client/build/_whatsdeployed/content.json $CONTENT_ROOT + poetry run deployer whatsdeployed --output ../client/build/_whatsdeployed/translated-content.json $CONTENT_TRANSLATED_ROOT # XXX would be nice to validate here that $DEPLOYER_BUCKET_PREFIX is truthy echo "DEPLOYER_BUCKET_PREFIX=$DEPLOYER_BUCKET_PREFIX" - poetry run deployer upload ../client/build + poetry run deployer upload --prune ../client/build poetry run deployer update-lambda-functions ./aws-lambda # TODO: Depending on how long the upload takes, consider switching to diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 2fa236187c00..398c9cc70d73 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -17,7 +17,7 @@ jobs: - uses: actions/checkout@v2 - name: Setup Node.js environment - uses: actions/setup-node@v2.1.4 + uses: actions/setup-node@v2.1.5 with: node-version: "12" @@ -42,9 +42,6 @@ jobs: - name: Lint ESLint run: yarn eslint - - name: Unit testing build - run: yarn test:build - - name: Unit testing client run: yarn test:client diff --git a/.gitignore b/.gitignore index 2ddde806867d..a5b2c0f65fe2 100644 --- a/.gitignore +++ b/.gitignore @@ -72,5 +72,6 @@ mdn-yari-*.tgz function.zip testing/content/files/en-us/_githistory.json +testing/translated-content/files/**/_githistory.json # eslintcache client/.eslintcache diff --git a/README.md b/README.md index c5f06bc3c83e..fd4d001b8390 100644 --- a/README.md +++ b/README.md @@ -5,52 +5,82 @@ ## Quickstart -Before you can begin with Yari, you need [Content](https://github.com/mdn/content). -See its README which basically, says something like this: +Development on `yari` involves updating the machinery that renders MDN content +or improving the structure and styling of the MDN UI (e.g. the +styling of the header). If you are more interested in contributing to the MDN +content, you should check out the [content](https://github.com/mdn/content) repo +README instead. - git clone https://github.com/mdn/content.git mdn/content +Before you can start working with Yari, you need to: -Now, you just need to note where that folder is before you can start Yari. + + -To run Yari locally, you'll first need to install [git](https://git-scm.com/), -[Node.js](https://nodejs.org) (>= 12.0.0) and -[Yarn 1](https://classic.yarnpkg.com/en/docs/install). -After that, run these commands in your bash: +1. Install [git](https://git-scm.com/), + [Node.js](https://nodejs.org) (>= 12.0.0), and [Yarn 1](https://classic.yarnpkg.com/en/docs/install). + +1. [Fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) + the MDN [content](https://github.com/mdn/content) and [yari](https://github.com/mdn/content) + repositories using the Fork button on GitHub. + +1. Clone the forked repositories to your computer using the following commands + (replace `[your account]` with the account you forked the repositories to): + + git clone https://github.com/[your_account]/content.git + git clone https://github.com/[your_account]/yari.git + + Take a note of the file path to the location where you've cloned that + repo before moving on. + + + +To run Yari locally, you'll first need to install its dependencies and build the +app locally. Do this like so: - git clone https://github.com/mdn/yari.git cd yari - yarn + yarn install + +Now run the following command to create a `.env` file inside your `yari` repo +root and set the `CONTENT_ROOT` environment variable equal to the path to the +`content` repo. This is so the Yari app can find the content it needs to render. +You'll need to replace `/path/to/mdn/content/files` with the path to the +`/files` folder inside your clone of the `content` repo: + echo CONTENT_ROOT=/path/to/mdn/content/files >> .env + +At this point, you can get started. Run the following lines to compile required +files, start the Yari web server running, and open it in your browser: + yarn dev open http://localhost:3000 -Make sure you point to the `/files` folder inside your clone of the content -repo. +If you prefer you can use `yarn start`, which will re-use any previously +compiled files; this is "riskier" but faster. `yarn dev` always ensures that +everything is up-to-date. -If you prefer, you can fork the repo first and do the `git clone` with -_your_ fork instead of the `mdn` one. - -The `yarn dev` command will compile and prepare certain files. This always -takes a little extra time. If you prefer you can use `yarn start` which -will re-use any previously compiled files which is "riskier" but faster. -The `yarn start` command will also start a server which doesn't automatically -reload when its source code files change, so use with caution. +The `yarn start` command also starts a server with slightly different behavior — +it doesn't automatically reload when its source code files change, +so use with caution. See also our [reviewing guide](docs/REVIEWING.md) for information on how to review Yari changes. ### How to stay up-to-date -Periodically, the code and the content changes. Make sure you're staying -up-to-date with these commands: +Periodically, the code and the content changes. Make sure you stay +up-to-date with something along the following lines (replace `yari-origin` +with whatever you called [the remote location](https://git-scm.com/docs/git-remote) +of the original yari repo): - git pull origin main + git pull yari-origin main yarn yarn dev -These are also good steps to always take when you embark on making a change. -Then, the only extra command needed is `git checkout -b my-new-branch` -(or however you prefer to create new `git` branches) +When you embark on making a change, do it on a new branch, for example +`git checkout -b my-new-branch`. ## License @@ -61,9 +91,11 @@ in the [mdn/content repository](https://github.com/mdn/content). ## How it works -Yari is multiple things but at its core is the MDN content as `index.html` -files, in `git`, that contain the metadata (as front-matter) and -the bulk of the document. +Yari does a number of things, the most important of which is to render and serve +the MDN content found in the [content repo](https://github.com/mdn/content). +Each document is stored as an `index.html` file that contains metadata presented +as YAML [front-matter](https://github.com/mdn/content#fundamental-concepts) +followed by the document source. The builder converts these "source files" into "build files" using a CLI tool that iterates over the files, builds the HTML, and lastly packages it up @@ -71,12 +103,6 @@ with the front-end code, ready to be served as static files. ## Development -First of all, development on `yari` can mean the source code (e.g. the -styling of the header) or it can mean the content, since it's all one -repo. This document doesn't distinguish between the two. In the future we -might expand with more documentation specifically for contributing to the -content exclusively. - The `yarn start` command encapsulates the front-end dev server (on ) and the `server` (on ). @@ -87,14 +113,15 @@ if you want to work more rapidly. If you configure an environment variable called `EDITOR`, either on your system as a whole or in the root `.env` file, it can be used in the development -server to link to sources which, when clicked, opens in -your preferred editor/IDE. For example, in the root: +server to link to sources which, when clicked, open in your preferred +editor/IDE. For example, in the root of the repo you could run: echo 'EDITOR=code' >> .env Now clicking certain links will open files directly in the currently open -VSCode IDE. To test it, view any document on and -click the "Open in your editor" button. +VS Code IDE (replace `code` in the above command with a different text editor +name if needed, e.g. `atom` or whatever). To test it, view any document on + and click the "Open in your editor" button. ### How the server works @@ -114,29 +141,30 @@ And conveniently, if you're not even interested in what the flaws were, run: yarn prettier-format -But automatically when you ran `yarn` the first time (`yarn` is an alias for -`yarn install`) it set up a `git` pre-commit hook that uses `pretty-quick` -which is a wrapper on `prettier` that checks only the files in the git +When you ran `yarn` for the first time (`yarn` is an alias for +`yarn install`) it automatically sets up a `git` pre-commit hook that uses +`pretty-quick` — a wrapper for `prettier` that checks only the files in the git commit. -If in doubt about formatting, you can create a pull request and if you have -formatting flaws, the pull request checks should catch it. +If you have doubts about formatting, submit your pull request anyway. If you +have formatting flaws, the [pull request checks](https://github.com/features/actions) +should catch it. ### Upgrading Packages We maintain the dependencies using `Dependabot` in GitHub but if you want -to manually upgrade some you can use: +to manually upgrade them you can use: yarn upgrade-interactive --latest ### Sharing your dev environment with `ngrok` -[`ngrok`](https://ngrok.com/) is a great tool for starting a HTTP proxy -server from the Internet into your Yari server. This can be useful for testing -your current build on external tools like BrowserStack, WebPageTest, +[`ngrok`](https://ngrok.com/) allows you to start an HTTP proxy +server from the web into your Yari server. This can be useful for testing +your current build using external tools like BrowserStack, WebPageTest, or Google Translate, or to simply show a friend what you're up to. Obviously it'll never be faster than your uplink Internet connection but it should -be fairly feature complete. +be fairly feature-complete. 1. [Create in account on Ngrok.com](https://dashboard.ngrok.com/signup) 2. [Download the executable](https://ngrok.com/download) @@ -146,7 +174,7 @@ be fairly feature complete. This will display something like this: Session Status online - Account (Plan: Free) + Account (Plan: Free) Version 2.3.35 Region United States (us) Web Interface http://127.0.0.1:4040 @@ -154,17 +182,18 @@ This will display something like this: Forwarding https://920ba2108da8.ngrok.io -> http://localhost:5000 Connections ttl opn rt1 rt5 p50 p90 - 0 0 0.00 0.00 0.00 0.00 + 0 0 0.00 0.00 0.00 0.00 -Now, take that "Forwarding" URL `https://920ba2108da8.ngrok.io` (in this +Now, take that "Forwarding" URL (`https://920ba2108da8.ngrok.io` in this example) and share it. ## Building The `server` builds content automatically (on-the-fly) when you're viewing -pages. But if you want to you can pre-emptively build all the content -in advance. One potential advantage is that you can get a more complete -list of all possible "flaws" across all documents before you even visit them. +pages, but you can pre-emptively build all the content in advance if desired. +One potential advantage is that you can get a more complete list of all possible +"flaws" across all documents before you even visit them. + The most fundamental CLI command is: yarn build @@ -173,8 +202,9 @@ The most fundamental CLI command is: Every `index.html` becomes two files: -- `index.html` fully formed and complete HTML file -- `index.json` the React needed state to build the page in the client +- `index.html` — a fully formed and complete HTML file +- `index.json` — the state information React needs to build the page in the + client ### Flaw checks @@ -185,7 +215,7 @@ severe but they should never block a full build. More information about how to set flaws can be found in `docs/envvars.md`. Essentially, the default is to _warn_ about any flaw and you can see -those flaws when using . But for completed builds, +those flaws when using . For completed builds, all flaws are ignored. This makes the build faster and there's also no good place to display the flaws in a production-grade build. @@ -196,7 +226,7 @@ be on you to fix it. ## Icons and logos -The various formats and sizes of the favicon is generated +The various formats and sizes of the favicon are generated from the file `mdn-web-docs.svg` in the repository root. This file is then converted to favicons using [realfavicongenerator.net](https://realfavicongenerator.net/). To generate new favicons, edit or replace the `mdn-web-docs.svg` file diff --git a/build/check-images.js b/build/check-images.js index 11ba0727413c..129aa2f888d7 100644 --- a/build/check-images.js +++ b/build/check-images.js @@ -9,6 +9,7 @@ const sizeOf = require("image-size"); const { Document, Image } = require("../content"); const { FLAW_LEVELS } = require("./constants"); const { findMatchesInText } = require("./matches-in-text"); +const { DEFAULT_LOCALE } = require("../libs/constants"); /** * Mutate the `$` instance for image reference and if appropriate, @@ -86,7 +87,7 @@ function checkImageReferences(doc, $, options, { url, rawContent }) { // a new function dedicated to that. let finalSrc = null; - if (!src.trim()) { + if (!src.split("#")[0].trim()) { if (checkImages) { addImageFlaw(img, src, { explanation: "Empty img 'src' attribute", @@ -119,9 +120,24 @@ function checkImageReferences(doc, $, options, { url, rawContent }) { // it now, we still want the full relative URL. img.attr("src", absoluteURL.pathname); } else { + let suggestion = null; + // If this document is *not* en-US, perhaps the external image has already + // been downloaded by the en-US equivalent. If so, make that the suggestion. + if (doc.locale !== DEFAULT_LOCALE) { + const filePath = Image.findByURL( + path.join( + doc.mdn_url.replace(`/${doc.locale}/`, `/${DEFAULT_LOCALE}/`), + path.basename(src) + ) + ); + if (filePath) { + suggestion = path.basename(filePath); + } + } addImageFlaw(img, src, { explanation: "External image URL", externalImage: true, + suggestion, }); } } @@ -133,16 +149,38 @@ function checkImageReferences(doc, $, options, { url, rawContent }) { // We can use the `finalSrc` to look up and find the image independent // of the correct case because `Image.findByURL` operates case // insensitively. - const filePath = Image.findByURL(finalSrc); + let filePath = Image.findByURL(finalSrc); + let enUSFallback = false; + if ( + !filePath && + doc.locale !== DEFAULT_LOCALE && + !finalSrc.startsWith(`/${DEFAULT_LOCALE.toLowerCase()}/`) + ) { + const enUSFinalSrc = finalSrc.replace( + `/${doc.locale.toLowerCase()}/`, + `/${DEFAULT_LOCALE.toLowerCase()}/` + ); + if (Image.findByURL(enUSFinalSrc)) { + // Use the en-US src instead + finalSrc = enUSFinalSrc; + // Note that this `` value can work if you use the + // en-US equivalent URL instead. + enUSFallback = true; + } + } if (filePath) { filePaths.add(filePath); } if (checkImages) { - if (!filePath) { + if (enUSFallback) { + // If it worked by switching to the en-US src, don't do anything more. + // Do nothing! I.e. don't try to perfect the spelling. + } else if (!filePath) { // E.g. ` tag looks anything other than // `` then we can't assume the `img[src]` can // be resolved. For example, suppose the HTML contains `` // then it's a broken image and it's handled by the `checkImageReferences()` // function. Stay away from those. - if (!imgSrc.includes("://") && imgSrc.startsWith("/")) { + if (!imgSrc) { + if (options.flawLevels.get("image_widths") === FLAW_LEVELS.ERROR) { + throw new Error( + `images width flaws: ${JSON.stringify(doc.flaws.image_widths)}` + ); + } + } else if (!imgSrc.includes("://") && imgSrc.startsWith("/")) { const filePath = Image.findByURL(imgSrc); if (filePath) { const dimensions = sizeOf(filePath); diff --git a/build/cli.js b/build/cli.js index 46c1f4dd5cd9..49b462d1da3c 100644 --- a/build/cli.js +++ b/build/cli.js @@ -6,30 +6,25 @@ const cliProgress = require("cli-progress"); const program = require("@caporal/core").default; const { prompt } = require("inquirer"); -const { Document, slugToFolder } = require("../content"); +const { + Document, + slugToFolder, + translationsOf, + CONTENT_TRANSLATED_ROOT, +} = require("../content"); + // eslint-disable-next-line node/no-missing-require -const { renderDocHTML, renderHTML } = require("../ssr/dist/main"); +const { renderDocHTML } = require("../ssr/dist/main"); const options = require("./build-options"); const { buildDocument, renderContributorsTxt } = require("./index"); const SearchIndex = require("./search-index"); -const { - BUILD_OUT_ROOT, - HOMEPAGE_FEED_URL, - HOMEPAGE_FEED_DISPLAY_MAX, -} = require("./constants"); +const { BUILD_OUT_ROOT } = require("./constants"); const { makeSitemapXML, makeSitemapIndexXML } = require("./sitemaps"); -const { - CONTENT_TRANSLATED_ROOT, - CONTENT_ROOT, -} = require("../content/constants"); -const { uniqifyTranslationsOf } = require("./translationsof"); const { humanFileSize } = require("./utils"); -const { getFeedEntries } = require("./feedparser"); async function buildDocumentInteractive( documentPath, - translationsOf, interactive, invalidate = false ) { @@ -38,37 +33,15 @@ async function buildDocumentInteractive( ? Document.read(documentPath, Document.MEMOIZE_INVALIDATE) : Document.read(documentPath); - const { translation_of } = document.metadata; - - // If it's a non-en-US document, it'll most likely have a `translation_of`. - // If so, add it to the map so that when we build the en-US one, we can - // get an index of the *other* translations available. - if (translation_of) { - if (!translationsOf.has(translation_of)) { - translationsOf.set(translation_of, []); - } - const translation = { - url: document.url, - locale: document.metadata.locale, - title: document.metadata.title, - }; - if (document.metadata.translation_of_original) { - translation.original = document.metadata.translation_of_original; + if (!interactive) { + const translations = translationsOf(document.metadata); + if (translations && translations.length > 0) { + document.translations = translations; + } else { + document.translations = []; } - translationsOf.get(translation_of).push(translation); - // This is a shortcoming. If this is a translated document, we don't have a - // complete mapping of all other translations. So, the best we can do is - // at least link to the English version. - // In 2021, when we refactor localization entirely, this will need to change. - // Perhaps, then, we'll do a complete scan through all content first to build - // up the map before we process each one. - document.translations = []; - } else if (translationsOf.has(document.metadata.slug)) { - document.translations = uniqifyTranslationsOf( - translationsOf.get(document.metadata.slug), - document.url - ); } + return { document, doc: await buildDocument(document), skip: false }; } catch (e) { if (!interactive) { @@ -89,12 +62,7 @@ async function buildDocumentInteractive( }, ]); if (action === "r") { - return await buildDocumentInteractive( - documentPath, - translationsOf, - interactive, - true - ); + return await buildDocumentInteractive(documentPath, interactive, true); } if (action === "s") { return { doc: {}, skip: true }; @@ -142,9 +110,6 @@ async function buildDocuments( } } - // This builds up a mapping from en-US slugs to their translated slugs. - const translationsOf = new Map(); - if (!options.noProgressbar) { progressBar.start(documents.count); } @@ -154,11 +119,7 @@ async function buildDocuments( doc: { doc: builtDocument, liveSamples, fileAttachments, bcdData }, document, skip, - } = await buildDocumentInteractive( - documentPath, - translationsOf, - interactive - ); + } = await buildDocumentInteractive(documentPath, interactive); if (skip) { continue; } @@ -270,10 +231,8 @@ async function buildDocuments( sitemapsBuilt.push(sitemapFilePath); } - // Only if you've just built all of CONTENT_ROOT and all of CONTENT_TRANSLATED_ROOT // do we bother generating the combined sitemaps index file. // That means, that if you've done this at least once, consequent runs of - // *only* CONTENT_ROOT will just keep overwriting the sitemaps/en-us/sitemap.xml.gz. if (CONTENT_TRANSLATED_ROOT) { const sitemapIndexFilePath = path.join(BUILD_OUT_ROOT, "sitemap.xml"); fs.writeFileSync( @@ -294,85 +253,6 @@ async function buildDocuments( return { slugPerLocale: docPerLocale, peakHeapBytes, totalFlaws }; } -async function buildOtherSPAs(options) { - // The URL isn't very important as long as it triggers the right route in the - const url = "/en-US/404.html"; - const html = renderHTML(url, { pageNotFound: true }); - const outPath = path.join(BUILD_OUT_ROOT, "en-us", "_spas"); - fs.mkdirSync(outPath, { recursive: true }); - fs.writeFileSync(path.join(outPath, path.basename(url)), html); - if (!options.quiet) { - console.log("Wrote", path.join(outPath, path.basename(url))); - } - - // Basically, this builds one `search/index.html` for every locale we intend - // to build. - for (const root of [CONTENT_ROOT, CONTENT_TRANSLATED_ROOT]) { - if (!root) { - continue; - } - for (const locale of fs.readdirSync(root)) { - if (!fs.statSync(path.join(root, locale)).isDirectory()) { - continue; - } - const url = `/${locale}/search`; - const html = renderHTML(url); - const outPath = path.join(BUILD_OUT_ROOT, locale, "search"); - fs.mkdirSync(outPath, { recursive: true }); - const filePath = path.join(outPath, "index.html"); - fs.writeFileSync(filePath, html); - if (!options.quiet) { - console.log("Wrote", filePath); - } - } - } - - // Build all the home pages in all locales. - // Have the feed entries ready before building the home pages. - // XXX disk caching? - const feedEntries = (await getFeedEntries(HOMEPAGE_FEED_URL)).slice( - 0, - HOMEPAGE_FEED_DISPLAY_MAX - ); - for (const root of [CONTENT_ROOT, CONTENT_TRANSLATED_ROOT]) { - if (!root) { - continue; - } - for (const locale of fs.readdirSync(root)) { - if (!fs.statSync(path.join(root, locale)).isDirectory()) { - continue; - } - const url = `/${locale}/`; - // Each .pubDate in feedEntries is a Date object. That has to be converted - // to a string. That way the SSR rendering is - const dateFormatter = new Intl.DateTimeFormat(locale, { - dateStyle: "full", - }); - const context = { - feedEntries: feedEntries.map((entry) => { - const pubDateString = dateFormatter.format(entry.pubDate); - return Object.assign({}, entry, { pubDate: pubDateString }); - }), - }; - const html = renderHTML(url, context); - const outPath = path.join(BUILD_OUT_ROOT, locale); - fs.mkdirSync(outPath, { recursive: true }); - const filePath = path.join(outPath, "index.html"); - fs.writeFileSync(filePath, html); - if (!options.quiet) { - console.log("Wrote", filePath); - } - // Also, dump the feed entries as a JSON file so the data can be gotten - // in client-side rendering. - const filePathContext = path.join(outPath, "index.json"); - fs.writeFileSync(filePathContext, JSON.stringify(context)); - if (!options.quiet) { - console.log("Wrote", filePathContext); - } - } - } -} - function formatTotalFlaws(flawsCountMap, header = "Total_Flaws_Count") { if (!flawsCountMap.size) { return ""; @@ -392,24 +272,12 @@ function formatTotalFlaws(flawsCountMap, header = "Total_Flaws_Count") { program .name("build") - .option("--spas", "Build the SPA pages", { default: true }) // PR builds - .option("--spas-only", "Only build the SPA pages", { default: false }) .option("-i, --interactive", "Ask what to do when encountering flaws", { default: false, }) .argument("[files...]", "specific files to build") .action(async ({ args, options }) => { try { - if (options.spas) { - if (!options.quiet) { - console.log("\nBuilding SPAs..."); - } - await buildOtherSPAs(options); - } - if (options.spasOnly) { - return; - } - if (!options.quiet) { console.log("\nBuilding Documents..."); } diff --git a/build/constants.js b/build/constants.js index 6aa6e4cca10e..9a8e6d6bb941 100644 --- a/build/constants.js +++ b/build/constants.js @@ -30,6 +30,8 @@ const VALID_FLAW_CHECKS = new Set([ "image_widths", "bad_pre_tags", "sectioning", + "heading_links", + "unsafe_html", ]); // TODO (far future): Switch to "error" when number of flaws drops. diff --git a/build/feedparser.js b/build/feedparser.js index c2b22976ce3d..0e25ca7119e2 100644 --- a/build/feedparser.js +++ b/build/feedparser.js @@ -14,9 +14,10 @@ async function getFeedEntries(url) { for (const item of feed.rss.channel.item) { const description = cheerio.load(item.description); const summary = description("p").text(); + const title = cheerio.load(item.title).text(); entries.push({ url: item.link, - title: item.title, + title, pubDate: new Date(item.pubDate), creator: item["dc:creator"], summary, diff --git a/build/flaws.js b/build/flaws.js index 5eb3c27b910a..3f916527c532 100644 --- a/build/flaws.js +++ b/build/flaws.js @@ -12,28 +12,162 @@ const imageminSvgo = require("imagemin-svgo"); const sanitizeFilename = require("sanitize-filename"); const { Archive, Document, Redirect, Image } = require("../content"); -const { FLAW_LEVELS } = require("./constants"); +const { FLAW_LEVELS, VALID_FLAW_CHECKS } = require("./constants"); +const { + INTERACTIVE_EXAMPLES_BASE_URL, + LIVE_SAMPLES_BASE_URL, +} = require("../kumascript/src/constants"); const { packageBCD } = require("./resolve-bcd"); const { findMatchesInText, + getFirstMatchInText, replaceMatchesInText, } = require("./matches-in-text"); const { humanFileSize } = require("./utils"); const { VALID_MIME_TYPES } = require("../filecheck/constants"); -function injectFlaws(doc, $, options, { rawContent }) { +function injectFlaws(doc, $, options, document) { if (doc.isArchive) return; - injectBrokenLinksFlaws( - options.flawLevels.get("broken_links"), - doc, - $, - rawContent - ); + const flawChecks = [ + ["unsafe_html", injectUnsafeHTMLFlaws, false], + ["broken_links", injectBrokenLinksFlaws, true], + ["bad_bcd_queries", injectBadBCDQueriesFlaws, false], + ["bad_pre_tags", injectPreTagFlaws, false], + ["heading_links", injectHeadingLinksFlaws, false], + ]; + + // Note that some flaw checking functions need to always run. Even if we're not + // recording the flaws, the checks that it does are important for regular + // building. + + for (const [flawName, func, alwaysRun] of flawChecks) { + // Sanity check the list of flaw names that they're all recognized. + // Basically a cheap enum check. + if (!VALID_FLAW_CHECKS.has(flawName)) { + throw new Error(`'${flawName}' is not a valid flaw check name`); + } - injectBadBCDQueriesFlaws(options.flawLevels.get("bad_bcd_queries"), doc, $); + const level = options.flawLevels.get(flawName); + if (!alwaysRun && level === FLAW_LEVELS.IGNORE) { + continue; + } - injectPreTagFlaws(options.flawLevels.get("bad_pre_tags"), doc, $, rawContent); + // The flaw injection function will mutate the `doc.flaws` object. + func(doc, $, document, level); + + if ( + level === FLAW_LEVELS.ERROR && + doc.flaws[flawName] && + doc.flaws[flawName].length > 0 + ) { + // To make the stdout output a bit more user-friendly, print one warning + // for each explanation + doc.flaws[flawName].forEach((flaw, i) => { + console.warn( + i + 1, + chalk.yellow(`${chalk.bold(flawName)} flaw: ${flaw.explanation}`) + ); + }); + throw new Error(`${doc.flaws[flawName].length} ${flawName} flaws`); + } + } +} + +function injectUnsafeHTMLFlaws(doc, $, { rawContent }) { + function addFlaw(element, explanation) { + if (!("unsafe_html" in doc.flaws)) { + doc.flaws.unsafe_html = []; + } + const id = `unsafe_html${doc.flaws.unsafe_html.length + 1}`; + let html = $.html($(element)); + $(element).replaceWith($("").addClass("unsafe-html").text(html)); + // Some nasty tags are so broken they can make the HTML become more or less + // the whole page. E.g. ``. + if (html.length > 100) { + html = html.slice(0, Math.min(html.indexOf("\n"), 100)) + "…"; + } + // Perhaps in the future we can make it possibly fixable to delete it. + const fixable = false; + const suggestion = null; + + const flaw = { + explanation, + id, + fixable, + html, + suggestion, + }; + for (const { line, column } of findMatchesInText(html, rawContent)) { + // This might not find anything because the HTML might have mutated + // slightly because of how cheerio parses it. But it doesn't hurt to try. + flaw.line = line; + flaw.column = column; + } + + doc.flaws.unsafe_html.push(flaw); + } + + const safeIFrameSrcs = [ + // EmbedGHLiveSample.ejs + "https://mdn.github.io", + // EmbedYouTube.ejs + "https://www.youtube-nocookie.com", + // JSFiddleEmbed.ejs + "https://jsfiddle.net", + // EmbedTest262ReportResultsTable.ejs + "https://test262.report", + ]; + if (LIVE_SAMPLES_BASE_URL) { + safeIFrameSrcs.push(LIVE_SAMPLES_BASE_URL.toLowerCase()); + } + if (INTERACTIVE_EXAMPLES_BASE_URL) { + safeIFrameSrcs.push(INTERACTIVE_EXAMPLES_BASE_URL.toLowerCase()); + } + + $("script, embed, object, iframe").each((i, element) => { + const { tagName } = element; + if (tagName === "iframe") { + // For iframes we only check the 'src' value + const src = $(element).attr("src"); + // Local URLs are always safe. + if (!(src.startsWith("//") || src.includes("://"))) { + return; + } + if (!safeIFrameSrcs.find((s) => src.toLowerCase().startsWith(s))) { + addFlaw(element, `Unsafe `; +str = ``; %> <%- str %> diff --git a/kumascript/macros/EmbedLiveSample.ejs b/kumascript/macros/EmbedLiveSample.ejs index 7c0081a4fda6..30d5b695cc07 100644 --- a/kumascript/macros/EmbedLiveSample.ejs +++ b/kumascript/macros/EmbedLiveSample.ejs @@ -73,7 +73,7 @@ if (hasScreenshot) { %><% %><% } // end hasScreenshot -%>" @@ -29,7 +29,7 @@ describeMacro("EmbedLiveSample", function () { macro.ctx.env.url = "/en-US/docs/Web/SVG/Element/switch"; return assert.eventually.equal( macro.call("SVG_<switch>_example"), - '" @@ -39,7 +39,7 @@ describeMacro("EmbedLiveSample", function () { macro.ctx.env.url = "/en-US/docs/Web/SVG/Element/switch"; return assert.eventually.equal( macro.call("SVG_%3Cswitch%3E_example"), - '" @@ -50,7 +50,7 @@ describeMacro("EmbedLiveSample", function () { "/fr/docs/Web/CSS/Utilisation_de_d%C3%A9grad%C3%A9s_CSS"; return assert.eventually.equal( macro.call("Dégradés_linéaires_simples"), - '" @@ -60,7 +60,7 @@ describeMacro("EmbedLiveSample", function () { macro.ctx.env.url = "/en-US/docs/Web/HTML/Element/figure"; return assert.eventually.equal( macro.call('">'), - '" @@ -70,7 +70,7 @@ describeMacro("EmbedLiveSample", function () { macro.ctx.env.url = "/en-US/docs/Web/CSS/border-top-width"; return assert.eventually.equal( macro.call("Example", "100%"), - '" @@ -255,7 +255,7 @@ describeMacro("EmbedLiveSample", function () { "", '">' ), - '" @@ -266,7 +266,7 @@ describeMacro("EmbedLiveSample", function () { macro.ctx.env.url = "/en-US/docs/Web/CSS/-moz-appearance"; return assert.eventually.equal( macro.call("sampleNone", 100, 50, "", "", "nobutton"), - ' + + + +

Here's a link that contains the string :JavaScript within the href +attribute:
+ + A beginner's guide to SpiderMonkey, Mozilla's JavaScript engine +

+ +
    +
  • I'm
  • +
  • sneaky
  • +
+ + diff --git a/testing/integration/headless/map_301.py b/testing/integration/headless/map_301.py index 90b726baa162..6771a6754167 100644 --- a/testing/integration/headless/map_301.py +++ b/testing/integration/headless/map_301.py @@ -552,9 +552,11 @@ url_test("/patches", status_code=404), url_test("/patches/foo", status_code=404), url_test("/web-tech", status_code=404), - url_test("/web-tech/feed/atom/", status_code=404), - url_test("/css/wiki.css", status_code=404), - url_test("/css/base.css", status_code=404), + url_test( + "/web-tech/feed/atom/", follow_redirects=True, final_status_code=404 + ), + url_test("/css/wiki.css", follow_redirects=True, final_status_code=404), + url_test("/css/base.css", follow_redirects=True, final_status_code=404), url_test("/contests", "http://www.mozillalabs.com/", status_code=302), url_test("/contests/", "http://www.mozillalabs.com/", status_code=302), url_test( @@ -979,3 +981,81 @@ ) ) ) + +MISC_REDIRECT_URLS = [ + url_test("/en-US/DOM", "/en-US/docs/DOM"), + url_test("/en-US/DOM/", "/en-US/docs/DOM"), + url_test( + "/en-US/DOM/element.addEventListener", + "/en-US/docs/DOM/element.addEventListener", + ), + url_test("/en-US/DOM/CSSRule/cssText/", "/en-US/docs/DOM/CSSRule/cssText"), + url_test("/fr/DOM", "/fr/docs/DOM"), + url_test("/fr/DOM/", "/fr/docs/DOM"), + url_test( + "/fr/DOM/element.addEventListener", "/fr/docs/DOM/element.addEventListener" + ), + url_test("/fr/DOM/CSSRule/cssText/", "/fr/docs/DOM/CSSRule/cssText"), + url_test("/en-US/AJAX", "/en-US/docs/AJAX"), + url_test("/en-US/AJAX/", "/en-US/docs/AJAX"), + url_test("/en-US/AJAX/Getting_Started/", "/en-US/docs/AJAX/Getting_Started"), + url_test("/en-US/CSS", "/en-US/docs/CSS"), + url_test("/en-US/CSS/", "/en-US/docs/CSS"), + url_test("/en-US/CSS/time/", "/en-US/docs/CSS/time"), + url_test("/en-US/DragDrop", "/en-US/docs/DragDrop"), + url_test("/en-US/DragDrop/", "/en-US/docs/DragDrop"), + url_test("/en-US/DragDrop/Drag_and_Drop/", "/en-US/docs/DragDrop/Drag_and_Drop"), + url_test("/en-US/HTML", "/en-US/docs/HTML"), + url_test("/en-US/HTML/", "/en-US/docs/HTML"), + url_test("/en-US/HTML/Canvas/", "/en-US/docs/HTML/Canvas"), + url_test("/en-US/JavaScript", "/en-US/docs/JavaScript"), + url_test("/en-US/JavaScript/", "/en-US/docs/JavaScript"), + url_test( + "/en-US/JavaScript/Reference/About/", "/en-US/docs/JavaScript/Reference/About" + ), + url_test("/en-US/SVG", "/en-US/docs/SVG"), + url_test("/en-US/SVG/", "/en-US/docs/SVG"), + url_test("/en-US/SVG/Element/font/", "/en-US/docs/SVG/Element/font"), + url_test("/en-US/Tools", "/en-US/docs/Tools"), + url_test("/en-US/Tools/", "/en-US/docs/Tools"), + url_test( + "/en-US/Tools/Memory/Treemap_view/", "/en-US/docs/Tools/Memory/Treemap_view" + ), + url_test( + "/en-US/Using_files_from_web_applications", + "/en-US/docs/Using_files_from_web_applications", + ), + url_test( + "/en-US/Using_files_from_web_applications/", + "/en-US/docs/Using_files_from_web_applications", + ), + url_test("/en-US/Web", "/en-US/docs/Web"), + url_test("/en-US/Web/", "/en-US/docs/Web"), + url_test("/en-US/Web/API/ArrayBuffer/", "/en-US/docs/Web/API/ArrayBuffer"), + url_test("/en-US/XMLHttpRequest", "/en-US/docs/XMLHttpRequest"), + url_test("/en-US/XMLHttpRequest/", "/en-US/docs/XMLHttpRequest"), + url_test("/en-US/XMLHttpRequest/FormData/", "/en-US/docs/XMLHttpRequest/FormData"), + url_test("/en-US/Security", "/en-US/docs/Security"), + url_test("/en-US/Security/", "/en-US/docs/Security"), + url_test("/en-US/Security/CSP/", "/en-US/docs/Security/CSP"), + # Add trailing slash for the home page. + url_test("/en-US", "/en-US/"), + # Some special cases for "/docs". + url_test("/docs", "/docs/Web"), + url_test("/docs/", "/docs/Web"), + url_test("/en-us/docs", "/en-us/docs/Web"), + url_test("/en-us/docs/", "/en-us/docs/Web"), + # Locale and trailing-slash correction redirect tests. + url_test("/EN-us", "/en-US/", status_code=302), + url_test("/EN-us?next=FOO", "/en-US/?next=FOO", status_code=302), + url_test("/EN-US/", "/en-US/", status_code=302), + url_test("/EN-US/?next=FOO", "/en-US/?next=FOO", status_code=302), + url_test("/eN-us/docs/Web", "/en-US/docs/Web", status_code=302), + url_test("/eN-us/docs/Web/", "/en-US/docs/Web", status_code=302), + url_test("/eN-us/docs/Web?next=FOO", "/en-US/docs/Web?next=FOO", status_code=302), + url_test("/eN-us/docs/Web/?next=FOO", "/en-US/docs/Web?next=FOO", status_code=302), + url_test("/en-uS/search", "/en-US/search", status_code=302), + url_test("/en-uS/search/", "/en-US/search", status_code=302), + url_test("/en-Us/search?q=video", "/en-US/search?q=video", status_code=302), + url_test("/en-Us/search/?q=video", "/en-US/search?q=video", status_code=302), +] diff --git a/testing/integration/headless/test_cdn.py b/testing/integration/headless/test_cdn.py index 1286b464defe..06bbbe764ff4 100644 --- a/testing/integration/headless/test_cdn.py +++ b/testing/integration/headless/test_cdn.py @@ -140,7 +140,6 @@ def assert_cached( ("/readiness", 204, None), ("/api/v1/whoami", 200, None), ("/api/v1/search/en-US?q=css", 200, None), - ("/en-US/search?q=css", 200, None), ("/csp-violation-capture", 405, None), ("/en-US/profile", 302, "/en-US/users/signin?next=/en-US/profile"), ("/en-US/profile/edit", 302, "/en-US/users/signin?next=/en-US/profile/edit"), @@ -206,7 +205,8 @@ def test_not_cached(base_url, is_behind_cdn, slug, status, expected_location): ("/presentations/microsummaries/index.html", 200, None), ("/en-US/account/", 200, None), ("/en-US/search/xml", 200, None), - ("/en-US/search.json?q=yada", 301, "/api/v1/search/en-US?q=yada"), + ("/en-US/search.json?q=yada", 301, "/api/v1/search?q=yada"), + ("/en-US/search?q=css", 200, None), ("/en-US/search/?q=css", 301, "/en-US/search?q=css"), ("/en-US/search/?q=html", 301, "/en-US/search?q=html"), ("/en-US/Firefox", 302, "/en-US/docs/Mozilla/Firefox"), diff --git a/testing/integration/headless/test_endpoints.py b/testing/integration/headless/test_endpoints.py index 4ab7b23656a0..8f2269f557c6 100644 --- a/testing/integration/headless/test_endpoints.py +++ b/testing/integration/headless/test_endpoints.py @@ -71,7 +71,7 @@ def test_hreflang_basic(base_url): resp = request("get", url) assert resp.status_code == 200 html = PyQuery(resp.text) - assert html.attr("lang") == "en" + assert html.attr("lang") == "en-US" assert html.find( 'head > link[hreflang="en"][href="https://developer.mozilla.org/en-US/docs/Web/HTTP"]' ) @@ -107,12 +107,12 @@ def test_api_basic(base_url, uri, expected_keys): "en-US-2": ("en-US", None, "en-US"), "en-US-3": ("en-US", "en-US", None), "en-US-4": ("en-US", "en-US", "fr"), - "es-1": ("es", "es", None), - "es-2": ("es", "es", "en-US"), - "es-3": ("es", None, "es"), - "de-1": ("de", "de", None), - "de-2": ("de", "de", "en-US"), - "de-3": ("de", None, "de"), + "fr-1": ("fr", "fr", None), + "fr-2": ("fr", "fr", "en-US"), + "fr-3": ("fr", None, "fr"), + "ja-1": ("ja", "ja", None), + "ja-2": ("ja", "ja", "en-US"), + "ja-3": ("ja", None, "ja"), } @@ -124,17 +124,20 @@ def test_api_basic(base_url, uri, expected_keys): @pytest.mark.parametrize( "slug", [ + "", "/", "/docs/Web", + "/docs/Web/", "/search", + "/search/", + "/search?q=video", + "/search/?q=video", "/events", "/profile", "/profiles/sheppy", "/users/signin", "/promote", "/account", - "/docs/Web/HTML", - "/docs/Learn/CSS/Styling_text/Fundamentals#Color", ], ) def test_locale_selection(base_url, slug, expected, cookie, accept): @@ -151,4 +154,7 @@ def test_locale_selection(base_url, slug, expected, cookie, accept): request_kwargs["cookies"] = {"preferredlocale": cookie} response = request("get", url, **request_kwargs) assert response.status_code == 302 - assert response.headers["location"].startswith(f"/{expected}/") + extra = "?".join(p.strip("/") for p in slug.split("?")) + assert response.headers["location"].startswith( + f"/{expected}/{extra}" + ), f"{response.headers['location']} does not start with {f'/{expected}/{extra}'}" diff --git a/testing/integration/headless/test_redirects.py b/testing/integration/headless/test_redirects.py index 90a4db4712bc..70b43145b996 100644 --- a/testing/integration/headless/test_redirects.py +++ b/testing/integration/headless/test_redirects.py @@ -9,6 +9,7 @@ GITHUB_IO_URLS, LEGACY_URLS, MARIONETTE_URLS, + MISC_REDIRECT_URLS, MOZILLADEMOS_URLS, REDIRECT_URLS, SCL3_REDIRECT_URLS, @@ -105,3 +106,13 @@ def test_firefox_accounts_redirects(url, base_url): def test_firefox_source_docs_redirects(url, base_url): url["base_url"] = base_url assert_valid_url(**url) + + +@pytest.mark.parametrize( + "url", + MISC_REDIRECT_URLS, + ids=[item["url"] for item in MISC_REDIRECT_URLS], +) +def test_misc_redirects(url, base_url): + url["base_url"] = base_url + assert_valid_url(**url) diff --git a/testing/integration/utils/urls.py b/testing/integration/utils/urls.py index ae7d048ee209..6bed2b7b4053 100644 --- a/testing/integration/utils/urls.py +++ b/testing/integration/utils/urls.py @@ -123,9 +123,13 @@ def assert_valid_url( # so that the value will appear in locals in test output resp_location = resp.headers.get("location") if follow_redirects: - assert resp.status_code == final_status_code + assert ( + resp.status_code == final_status_code + ), f"got {resp.status_code}, expected {final_status_code}" else: - assert resp.status_code == status_code + assert ( + resp.status_code == status_code + ), f"got {resp.status_code}, expected {status_code}" if location and not follow_redirects: if query: # all query values must be lists @@ -139,7 +143,9 @@ def assert_valid_url( # strip off query for further comparison resp_location = resp_location.split("?")[0] - assert location == unquote(resp_location) + assert location == unquote( + resp_location + ), f"got {unquote(resp_location)}, expected {location}" if resp_headers and not follow_redirects: diff --git a/testing/scripts/functional-test.sh b/testing/scripts/functional-test.sh index a2fe15f632cf..3dbb373d5dd7 100755 --- a/testing/scripts/functional-test.sh +++ b/testing/scripts/functional-test.sh @@ -6,6 +6,9 @@ export ENV_FILE=testing/.env # Temporary whilst only the functional tests use the autocomplete search widget. export REACT_APP_AUTOCOMPLETE_SEARCH_WIDGET=true +# Temporary until we're still using the old Kuma for signin in. +export REACT_APP_USE_YARI_SIGNIN=true + yarn prepare-build yarn build diff --git a/testing/tests/developing.test.js b/testing/tests/developing.test.js index 65877e6a3a04..26935174ef98 100644 --- a/testing/tests/developing.test.js +++ b/testing/tests/developing.test.js @@ -6,25 +6,38 @@ const { setDefaultOptions } = require("expect-puppeteer"); // and then the server building of the page can be pretty heavy. setDefaultOptions({ timeout: 5000 }); +const DEV_BASE_URL = + process.env.DEVELOPING_DEV_BASE_URL || "http://localhost:3000"; + function devURL(pathname = "/") { - return `http://localhost:3000${pathname}`; + return `${DEV_BASE_URL}${pathname}`; } +const SERVER_BASE_URL = + process.env.DEVELOPING_SERVER_BASE_URL || "http://localhost:5000"; function serverURL(pathname = "/") { - return `http://localhost:5000${pathname}`; + return `${SERVER_BASE_URL}${pathname}`; } +const SKIP_DEV_URL = JSON.parse(process.env.DEVELOPING_SKIP_DEV_URL || "false"); + // This "trick" is to force every test to be skipped if the environment // variable hasn't been set. This way, when you run `jest ...`, and it finds // all `**/*.test.js` it doesn't actually run these tests unless explicitly // prepared to do so. // The source of this idea comes from https://github.com/facebook/jest/issues/7245 -const withDeveloping = JSON.parse(process.env.TESTING_DEVELOPING || "false") - ? it - : it.skip; +const isTesting = JSON.parse(process.env.TESTING_DEVELOPING || "false"); +const withDeveloping = isTesting ? it : it.skip; +// If the test suite runs in a way that there's no separate dev server, +// don't bother using the `DEV_BASE_URL`. +// For example, when it tests the `npm pack` tarball, it's starting only +// the one server (on `localhost:5000`) that suite will set the `DEV_BASE_URL` +// to be the same as `SAME_BASE_URL`. +// In conclusion, if there's only 1 base URL to test again; don't test both. +const withCrud = isTesting && !SKIP_DEV_URL ? it : it.skip; describe("Testing the kitchensink page", () => { - withDeveloping("open the page", async () => { + withCrud("open the page", async () => { await page.goto(devURL("/en-US/docs/MDN/Kitchensink")); await expect(page).toMatch("The MDN Content Kitchensink"); await expect(page).toMatch("No known flaws at the moment"); @@ -161,3 +174,17 @@ describe("Testing the Express server", () => { expect(response.headers.location).toBe("/sv-SE/"); }); }); + +describe("Testing the CRUD apps", () => { + withCrud("open the writer's home page", async () => { + await page.goto(devURL("/")); + await expect(page).toMatch("Writer's home page"); + await expect(page).toMatchElement("a", { text: "Flaws Dashboard" }); + }); + + withCrud("open the Flaws Dashboard", async () => { + await page.goto(devURL("/")); + await expect(page).toClick("a", { text: "Flaws Dashboard" }); + await expect(page).toMatch("Documents with flaws found (0)"); + }); +}); diff --git a/testing/tests/headless.test.js b/testing/tests/headless.test.js index e578ba79dd50..f48e1f3c9fcd 100644 --- a/testing/tests/headless.test.js +++ b/testing/tests/headless.test.js @@ -29,8 +29,9 @@ describe("Basic viewing of functional pages", () => { await expect(page).toMatchElement("h1", { text: ": Une page de test", }); - await expect(page).toSelect('select[name="language"]', "English (US)"); - await expect(page).toClick("button", { text: "Change language" }); + await expect(page).toClick("a.view-in-english", { + text: "View in English", + }); await expect(page).toMatchElement("h1", { text: ": A test tag" }); // Should have been redirected too... // Note! It's important that this happens *after* the `.toMatchElement` @@ -64,22 +65,22 @@ describe("Basic viewing of functional pages", () => { text: "Flexbox", }); await expect(page).toMatchElement( - `iframe.live-sample-frame.sample-code-frame[src$="${flexSample1Uri}"]` + `iframe.sample-code-frame[src$="${flexSample1Uri}"]` ); await expect(page).toMatchElement( - `iframe.live-sample-frame.sample-code-frame[src$="${flexSample2Uri}"]` + `iframe.sample-code-frame[src$="${flexSample2Uri}"]` ); await expect(page).toMatchElement("#grid_layout", { text: "Grid Layout", }); await expect(page).toMatchElement( - `iframe.live-sample-frame.sample-code-frame[src$="${gridSample1Uri}"]` + `iframe.sample-code-frame[src$="${gridSample1Uri}"]` ); await expect(page).toMatchElement("#Grid_2 > pre.css.notranslate", { text: /\.wrapper\s*\{\s*display:\s*grid;/, }); await expect(page).toMatchElement( - `iframe.live-sample-frame.sample-code-frame[src$="${gridSample2Uri}"]` + `iframe.sample-code-frame[src$="${gridSample2Uri}"]` ); // Ensure that the live-sample pages were built. for (const sampleUri of [ @@ -117,13 +118,13 @@ describe("Basic viewing of functional pages", () => { text: /\.wrapper\s*\{\s*display:\s*flex;\s*\}/, }); await expect(page).toMatchElement( - `iframe.live-sample-frame.sample-code-frame[src$="${flexSample1Uri}"]` + `iframe.sample-code-frame[src$="${flexSample1Uri}"]` ); await expect(page).toMatchElement("#Flex_2 > pre.css.notranslate", { text: /\.wrapper\s*\{\s*display:\s*flex;\s*\}.+flex:\s*1;/, }); await expect(page).toMatchElement( - `iframe.live-sample-frame.sample-code-frame[src$="${flexSample2Uri}"]` + `iframe.sample-code-frame[src$="${flexSample2Uri}"]` ); }); @@ -143,13 +144,13 @@ describe("Basic viewing of functional pages", () => { text: /\.wrapper\s*\{\s*display:\s*grid;/, }); await expect(page).toMatchElement( - `iframe.live-sample-frame.sample-code-frame[src$="${gridSample1Uri}"]` + `iframe.sample-code-frame[src$="${gridSample1Uri}"]` ); await expect(page).toMatchElement("#Grid_2 > pre.css.notranslate", { text: /\.wrapper\s*\{\s*display:\s*grid;.+\.box1\s*\{/, }); await expect(page).toMatchElement( - `iframe.live-sample-frame.sample-code-frame[src$="${gridSample2Uri}"]` + `iframe.sample-code-frame[src$="${gridSample2Uri}"]` ); // Ensure that the live-sample page "gridSample2Uri" was built. await page.goto(testURL(gridSample2Uri)); @@ -184,7 +185,7 @@ describe("Basic viewing of functional pages", () => { // For more information, see // https://github.com/puppeteer/puppeteer/issues/2977#issuecomment-412807613 await page.evaluate(() => { - document.querySelector(".breadcrumbs a").click(); + document.querySelector(".breadcrumbs-container a").click(); }); await expect(page).toMatchElement("h1", { text: "Web technology for developers", @@ -238,4 +239,54 @@ describe("Basic viewing of functional pages", () => { await page.goto(testURL("/fr/")); await expect(page).toMatch("Resources for developers, by developers."); }); + + it("should be able to switch from French to English, set a cookie, and back again", async () => { + await page.goto(testURL("/fr/docs/Web/Foo")); + await expect(page).toMatch(": Une page de test"); + await expect(page).toSelect('select[name="language"]', "English (US)"); + await expect(page).toClick("button", { text: "Change language" }); + await expect(page).toMatch(": A test tag"); + expect(page.url()).toBe(testURL("/en-US/docs/Web/Foo")); + + // And change back to French + await expect(page).toSelect('select[name="language"]', "Français"); + await expect(page).toClick("button", { text: "Change language" }); + await expect(page).toMatch(": Une page de test"); + expect(page.url()).toBe(testURL("/fr/docs/Web/Foo")); + }); + + it("clicking 'Sign in' should offer links to all identity providers", async () => { + await page.goto(testURL("/en-US/docs/Web/Foo")); + await expect(page).toClick("a", { text: "Sign in" }); + await expect(page).toMatchElement("h1", { text: "Sign in" }); + expect(page.url()).toContain( + testURL("/en-US/signin?next=/en-US/docs/Web/Foo") + ); + await expect(page).toMatchElement("a", { text: "Google" }); + await expect(page).toMatchElement("a", { text: "GitHub" }); + }); + + it("going to 'Sign up' page without query string", async () => { + await page.goto(testURL("/en-US/signup")); + await expect(page).toMatchElement("h1", { text: "Sign up" }); + await expect(page).toMatch("Invalid Sign up URL"); + await expect(page).toMatchElement("a", { + text: "Try starting over the sign-in process", + }); + }); + + it("going to 'Sign up' page with realistic (fake) query string", async () => { + await page.goto( + testURL("/en-US/signup?csrfmiddlewaretoken=abc&provider=github") + ); + await expect(page).toMatchElement("h1", { text: "Sign up" }); + await expect(page).not.toMatch("Invalid Sign up URL"); + await expect(page).toMatch( + "You are signing in to MDN Web Docs with GitHub." + ); + await expect(page).toMatch( + "I agree to Mozilla's Terms and Privacy Notice." + ); + await expect(page).toMatchElement("button", { text: "Create account" }); + }); }); diff --git a/testing/tests/index.test.js b/testing/tests/index.test.js index 20da5a26a770..9ee58b5ebc2e 100644 --- a/testing/tests/index.test.js +++ b/testing/tests/index.test.js @@ -142,9 +142,7 @@ test("content built foo page", () => { // The HTML should contain the Google Analytics snippet. // The ID should match what's set in `testing/.env`. - expect( - $('script[src="https://www.google-analytics.com/analytics.js"]').length - ).toBe(1); + expect($('script[src="/static/js/ga.js"]').length).toBe(1); // The HTML should contain the Speedcurve LUX snippet. // The ID should match what's set in `testing/.env`. @@ -806,7 +804,9 @@ test("image flaws kitchen sink", () => { expect(flaw.column).toBe(13); flaw = map.get("idontexist.png"); - expect(flaw.explanation).toBe("File not present on disk"); + expect(flaw.explanation).toBe( + "File not present on disk, an empty file, or not an image" + ); expect(flaw.suggestion).toBeNull(); expect(flaw.line).toBe(34); expect(flaw.column).toBe(13); @@ -846,7 +846,9 @@ test("image flaws kitchen sink", () => { expect(flaw.column).toBe(13); flaw = map.get("../Foo/nonexistent.png"); - expect(flaw.explanation).toBe("File not present on disk"); + expect(flaw.explanation).toBe( + "File not present on disk, an empty file, or not an image" + ); expect(flaw.suggestion).toBeNull(); expect(flaw.line).toBe(64); expect(flaw.column).toBe(13); @@ -866,6 +868,30 @@ test("image flaws kitchen sink", () => { }); }); +test("image flaws with bad images", () => { + const builtFolder = path.join( + buildRoot, + "en-us", + "docs", + "web", + "images", + "bad_src" + ); + const jsonFile = path.join(builtFolder, "index.json"); + const { doc } = JSON.parse(fs.readFileSync(jsonFile)); + const { flaws } = doc; + // You have to be intimately familiar with the fixture to understand + // why these flaws come out as they do. + expect(flaws.images.length).toBe(4); + expect( + flaws.images.filter( + (flaw) => + flaw.explanation === + "File not present on disk, an empty file, or not an image" + ).length + ).toBe(4); +}); + test("image flaws with repeated external images", () => { // This test exists because of https://github.com/mdn/yari/issues/2247 // which showed that if a document has an external URL repeated more than @@ -925,6 +951,26 @@ test("404 page", () => { expect($('meta[name="robots"]').attr("content")).toBe("noindex, nofollow"); }); +test("sign in page", () => { + const builtFolder = path.join(buildRoot, "en-us", "signin"); + expect(fs.existsSync(builtFolder)).toBeTruthy(); + const htmlFile = path.join(builtFolder, "index.html"); + const html = fs.readFileSync(htmlFile, "utf-8"); + const $ = cheerio.load(html); + expect($("h1").text()).toContain("Sign in"); + expect($("title").text()).toContain("Sign in"); +}); + +test("sign up page", () => { + const builtFolder = path.join(buildRoot, "en-us", "signup"); + expect(fs.existsSync(builtFolder)).toBeTruthy(); + const htmlFile = path.join(builtFolder, "index.html"); + const html = fs.readFileSync(htmlFile, "utf-8"); + const $ = cheerio.load(html); + expect($("h1").text()).toContain("Sign up"); + expect($("title").text()).toContain("Sign up"); +}); + test("bcd table extraction followed by h3", () => { const builtFolder = path.join( buildRoot, @@ -972,12 +1018,17 @@ test("img tags with an empty 'src' should be a flaw", () => { expect(fs.existsSync(builtFolder)).toBeTruthy(); const jsonFile = path.join(builtFolder, "index.json"); const { doc } = JSON.parse(fs.readFileSync(jsonFile)); - expect(doc.flaws.images.length).toBe(1); + expect(doc.flaws.images.length).toBe(2); expect(doc.flaws.images[0].explanation).toBe("Empty img 'src' attribute"); expect(doc.flaws.images[0].fixable).toBeFalsy(); expect(doc.flaws.images[0].externalImage).toBeFalsy(); expect(doc.flaws.images[0].line).toBe(8); expect(doc.flaws.images[0].column).toBe(13); + expect(doc.flaws.images[1].explanation).toBe("Empty img 'src' attribute"); + expect(doc.flaws.images[1].fixable).toBeFalsy(); + expect(doc.flaws.images[1].externalImage).toBeFalsy(); + expect(doc.flaws.images[1].line).toBe(17); + expect(doc.flaws.images[1].column).toBe(11); }); test("img with the image_widths flaw", () => { @@ -1048,6 +1099,20 @@ test("img tags should always have their 'width' and 'height' set", () => { }); }); +test("img tags without 'src' should not crash", () => { + const builtFolder = path.join( + buildRoot, + "en-us", + "docs", + "web", + "images", + "srcless" + ); + const jsonFile = path.join(builtFolder, "index.json"); + const { doc } = JSON.parse(fs.readFileSync(jsonFile)); + expect(Object.keys(doc.flaws).length).toBe(0); +}); + test("/Web/Embeddable should have 3 valid live samples", () => { const builtFolder = path.join( buildRoot, @@ -1160,3 +1225,77 @@ test("home page should have a /index.json file with feedEntries", () => { const { feedEntries } = JSON.parse(fs.readFileSync(jsonFile)); expect(feedEntries.length).toBeGreaterThan(0); }); + +test("headings with links in them are flaws", () => { + const builtFolder = path.join( + buildRoot, + "en-us", + "docs", + "web", + "heading_links" + ); + + const jsonFile = path.join(builtFolder, "index.json"); + const { doc } = JSON.parse(fs.readFileSync(jsonFile)); + expect(doc.flaws.heading_links.length).toBe(2); + const map = new Map(doc.flaws.heading_links.map((x) => [x.id, x])); + expect(map.get("heading_links1").explanation).toBe( + "h2 heading contains an tag" + ); + expect(map.get("heading_links1").suggestion).toBe("One"); + expect(map.get("heading_links1").line).toBe(9); + expect(map.get("heading_links1").column).toBe(19); + expect(map.get("heading_links1").fixable).toBe(false); + expect(map.get("heading_links1").before).toBe('One'); + expect(map.get("heading_links1").html).toBe( + '

One

' + ); + expect(map.get("heading_links2").explanation).toBe( + "h3 heading contains an tag" + ); + expect(map.get("heading_links2").suggestion.trim()).toBe("Two"); + expect(map.get("heading_links2").line).toBe(11); + expect(map.get("heading_links2").column).toBe(19); + expect(map.get("heading_links2").fixable).toBe(false); + expect(map.get("heading_links2").before.trim()).toBe( + 'Two' + ); + expect(map.get("heading_links2").html).toBe( + '

\n Two\n

' + ); +}); + +test("'lang' attribute should match the article", () => { + let builtFolder = path.join(buildRoot, "fr", "docs", "web", "foo"); + let htmlFile = path.join(builtFolder, "index.html"); + let html = fs.readFileSync(htmlFile, "utf-8"); + let $ = cheerio.load(html); + expect($("html").attr("lang")).toBe("en-US"); + expect($("article").attr("lang")).toBe("fr"); + + builtFolder = path.join(buildRoot, "en-us", "docs", "web", "foo"); + htmlFile = path.join(builtFolder, "index.html"); + html = fs.readFileSync(htmlFile, "utf-8"); + $ = cheerio.load(html); + expect($("html").attr("lang")).toBe("en-US"); + expect($("article").attr("lang")).toBe("en-US"); +}); + +test("unsafe HTML gets flagged as flaws and replace with its raw HTML", () => { + const builtFolder = path.join( + buildRoot, + "en-us", + "docs", + "web", + "unsafe_html" + ); + + const jsonFile = path.join(builtFolder, "index.json"); + const { doc } = JSON.parse(fs.readFileSync(jsonFile)); + expect(doc.flaws.unsafe_html.length).toBe(6); + + const htmlFile = path.join(builtFolder, "index.html"); + const html = fs.readFileSync(htmlFile, "utf-8"); + const $ = cheerio.load(html); + expect($("code.unsafe-html").length).toBe(6); +}); diff --git a/testing/tests/redirects.test.js b/testing/tests/redirects.test.js index 5ef708996d80..19f618cd35d5 100644 --- a/testing/tests/redirects.test.js +++ b/testing/tests/redirects.test.js @@ -1002,6 +1002,70 @@ const LOCALE_ALIAS_URLS = [].concat( url_test("/zh", "/zh-CN/") ); +const MISC_REDIRECT_URLS = [].concat( + url_test("/en-US/DOM", "/en-US/docs/DOM"), + url_test("/en-US/DOM/", "/en-US/docs/DOM"), + url_test( + "/en-US/DOM/element.addEventListener", + "/en-US/docs/DOM/element.addEventListener" + ), + url_test("/en-US/DOM/CSSRule/cssText/", "/en-US/docs/DOM/CSSRule/cssText"), + url_test("/fr/DOM", "/fr/docs/DOM"), + url_test("/fr/DOM/", "/fr/docs/DOM"), + url_test( + "/fr/DOM/element.addEventListener", + "/fr/docs/DOM/element.addEventListener" + ), + url_test("/fr/DOM/CSSRule/cssText/", "/fr/docs/DOM/CSSRule/cssText"), + url_test("/en-US/AJAX", "/en-US/docs/AJAX"), + url_test("/en-US/AJAX/", "/en-US/docs/AJAX"), + url_test("/en-US/AJAX/Getting_Started/", "/en-US/docs/AJAX/Getting_Started"), + url_test("/en-US/CSS", "/en-US/docs/CSS"), + url_test("/en-US/CSS/", "/en-US/docs/CSS"), + url_test("/en-US/CSS/time/", "/en-US/docs/CSS/time"), + url_test("/en-US/DragDrop", "/en-US/docs/DragDrop"), + url_test("/en-US/DragDrop/", "/en-US/docs/DragDrop"), + url_test( + "/en-US/DragDrop/Drag_and_Drop/", + "/en-US/docs/DragDrop/Drag_and_Drop" + ), + url_test("/en-US/HTML", "/en-US/docs/HTML"), + url_test("/en-US/HTML/", "/en-US/docs/HTML"), + url_test("/en-US/HTML/Canvas/", "/en-US/docs/HTML/Canvas"), + url_test("/en-US/JavaScript", "/en-US/docs/JavaScript"), + url_test("/en-US/JavaScript/", "/en-US/docs/JavaScript"), + url_test( + "/en-US/JavaScript/Reference/About/", + "/en-US/docs/JavaScript/Reference/About" + ), + url_test("/en-US/SVG", "/en-US/docs/SVG"), + url_test("/en-US/SVG/", "/en-US/docs/SVG"), + url_test("/en-US/SVG/Element/font/", "/en-US/docs/SVG/Element/font"), + url_test("/en-US/Tools", "/en-US/docs/Tools"), + url_test("/en-US/Tools/", "/en-US/docs/Tools"), + url_test( + "/en-US/Tools/Memory/Treemap_view/", + "/en-US/docs/Tools/Memory/Treemap_view" + ), + url_test( + "/en-US/Using_files_from_web_applications", + "/en-US/docs/Using_files_from_web_applications" + ), + url_test( + "/en-US/Using_files_from_web_applications/", + "/en-US/docs/Using_files_from_web_applications" + ), + url_test("/en-US/Web", "/en-US/docs/Web"), + url_test("/en-US/Web/", "/en-US/docs/Web"), + url_test("/en-US/Web/API/ArrayBuffer/", "/en-US/docs/Web/API/ArrayBuffer"), + url_test("/en-US/XMLHttpRequest", "/en-US/docs/XMLHttpRequest"), + url_test("/en-US/XMLHttpRequest/", "/en-US/docs/XMLHttpRequest"), + url_test( + "/en-US/XMLHttpRequest/FormData/", + "/en-US/docs/XMLHttpRequest/FormData" + ) +); + describe("scl3 redirects", () => { for (const [url, t] of SCL3_REDIRECT_URLS) { it(url, t); @@ -1094,3 +1158,9 @@ describe("Core_JavaScript_1.5 redirects", () => { it(url, t); } }); + +describe("misc redirects", () => { + for (const [url, t] of MISC_REDIRECT_URLS) { + it(url, t); + } +}); diff --git a/testing/tests/sitesearch.test.js b/testing/tests/sitesearch.test.js index 93d26440afa7..eef148e61007 100644 --- a/testing/tests/sitesearch.test.js +++ b/testing/tests/sitesearch.test.js @@ -22,7 +22,7 @@ describe("Site search", () => { await page.$eval('form[role="search"]', (form) => form.submit()); // Force a wait for the lazy-loading await page.waitForNavigation({ waitUntil: "networkidle2" }); - await expect(page).toMatch("Results: FOO"); + await expect(page).toMatch("Search results for: FOO"); await expect(page).toMatch("Found 1 match"); }); @@ -33,7 +33,7 @@ describe("Site search", () => { await expect(page).toFill(SEARCH_SELECTOR, "NOTHING"); await page.$eval('form[role="search"]', (form) => form.submit()); await page.waitForNavigation({ waitUntil: "networkidle2" }); - await expect(page).toMatch("Results: NOTHING"); + await expect(page).toMatch("Search results for: NOTHING"); await expect(page).toMatch("Found 0 matches"); }); @@ -43,7 +43,7 @@ describe("Site search", () => { await expect(page).toFill(SEARCH_SELECTOR, "SERIAL(20)"); await page.$eval('form[role="search"]', (form) => form.submit()); await page.waitForNavigation({ waitUntil: "networkidle2" }); - await expect(page).toMatch("Results: SERIAL(20)"); + await expect(page).toMatch("Search results for: SERIAL(20)"); expect(page.url()).toBe(testURL("/en-US/search/?q=SERIAL%2820%29")); await expect(page).toMatch("Found 20 matches in 0.1 milliseconds"); await expect(page).toMatch("Serial 0"); @@ -51,7 +51,7 @@ describe("Site search", () => { await expect(page).toMatchElement("a", { text: "Next" }); await expect(page).not.toMatchElement("a", { text: "Previous" }); await expect(page).toClick(".pagination a"); - await expect(page).toMatch("Page 2"); + await expect(page).toMatch("(page 2)"); await expect(page).toMatch("Serial 10"); await expect(page).toMatch("Serial 19"); await expect(page).toMatchElement("a", { text: "Previous" }); diff --git a/testing/translated-content/files/fr/web/foo/index.html b/testing/translated-content/files/fr/web/foo/index.html index 3a8de6521860..2940c8b5458e 100644 --- a/testing/translated-content/files/fr/web/foo/index.html +++ b/testing/translated-content/files/fr/web/foo/index.html @@ -5,3 +5,8 @@ ---

Foë

+ +
+ Capture d'écran des couleurs +
Une image parfaitement normale
+
diff --git a/tool/cli.js b/tool/cli.js index 566472f93fad..580001d9f596 100644 --- a/tool/cli.js +++ b/tool/cli.js @@ -1,12 +1,16 @@ const fs = require("fs"); const path = require("path"); -const os = require("os"); const program = require("@caporal/core").default; const chalk = require("chalk"); const { prompt } = require("inquirer"); const openEditor = require("open-editor"); const open = require("open"); +const { + syncAllTranslatedContent, +} = require("../build/sync-translated-content"); +const log = require("loglevel"); +const cheerio = require("cheerio"); const { DEFAULT_LOCALE, VALID_LOCALES } = require("../libs/constants"); const { @@ -16,9 +20,16 @@ const { Redirect, Document, buildURL, + getRoot, } = require("../content"); -const { buildDocument, gatherGitHistory } = require("../build"); +const { buildDocument, gatherGitHistory, buildSPAs } = require("../build"); +const { + BUILD_OUT_ROOT, + GOOGLE_ANALYTICS_ACCOUNT, + GOOGLE_ANALYTICS_DEBUG, +} = require("../build/constants"); const { runMakePopularitiesFile } = require("./popularities"); +const kumascript = require("../kumascript"); const PORT = parseInt(process.env.SERVER_PORT || "5000"); @@ -46,11 +57,43 @@ program .name("tool") .version("0.0.0") .disableGlobalOption("--silent") - .command("validate-redirects", "Check the _redirects.txt file(s)") + .cast(false) + .command("validate-redirects", "Try loading the _redirects.txt file(s)") + .argument("[locales...]", "Locale", { + default: [...VALID_LOCALES.keys()], + validator: [...VALID_LOCALES.keys()], + }) + .option("--strict", "Strict validation") .action( - tryOrExit(({ logger }) => { - Redirect.load(null, true); - logger.info(chalk.green("🍾 All is well in the world of redirects 🥂")); + tryOrExit(({ args, options, logger }) => { + const { locales } = args; + const { strict } = options; + let fine = true; + if (strict) { + for (const locale of locales) { + try { + Redirect.validateLocale(locale, strict); + logger.info(chalk.green(`✓ redirects for ${locale} looking good!`)); + } catch (e) { + logger.info( + chalk.red(`_redirects.txt for ${locale} is causing issues: ${e}`) + ); + fine = false; + } + } + } else { + try { + Redirect.load(locales, true); + } catch (e) { + logger.info(chalk.red(`Unable to load redirects: ${e}`)); + fine = false; + } + } + if (fine) { + logger.info(chalk.green("🍾 All is well in the world of redirects 🥂")); + } else { + throw new Error("🔥 Errors loading redirects 🔥"); + } }) ) @@ -70,18 +113,8 @@ program ) .command("add-redirect", "Add a new redirect") - .argument("", "From-URL", { - validator: (value) => { - Redirect.validateFromURL(value); - return value; - }, - }) - .argument("", "To-URL", { - validator: (value) => { - Redirect.validateToURL(value); - return value; - }, - }) + .argument("", "From-URL") + .argument("", "To-URL") .action( tryOrExit(({ args, logger }) => { const { from, to } = args; @@ -92,16 +125,16 @@ program ) .command("fix-redirects", "Consolidate/fix redirects") - .argument("", "Locale", { + .argument("", "Locale", { default: [DEFAULT_LOCALE], validator: [...VALID_LOCALES.values(), ...VALID_LOCALES.keys()], }) .action( tryOrExit(({ args, logger }) => { - const { locale } = args; - for (const l of locale) { - Redirect.add(l.toLowerCase(), [], { fix: true }); - logger.info(chalk.green(`Fixed ${l}`)); + const { locales } = args; + for (const locale of locales) { + Redirect.add(locale.toLowerCase(), [], { fix: true, strict: true }); + logger.info(chalk.green(`Fixed ${locale}`)); } }) ) @@ -283,13 +316,50 @@ program const { hostname, port } = options; let url; // Perhaps they typed in a path relative to the content root - if (slug.startsWith("files") && slug.endsWith("index.html")) { + if ( + (slug.startsWith("files") || fs.existsSync(slug)) && + (slug.endsWith("index.html") || slug.endsWith("index.md")) + ) { + if ( + fs.existsSync(slug) && + slug.includes("translated-content") && + !CONTENT_TRANSLATED_ROOT + ) { + // Such an easy mistake to make that you pass it a file path + // that comes from the translated-content repo but forgot to + // set the environment variable first. + console.warn( + chalk.yellow( + `Did you forget to set the environment variable ${chalk.bold( + "CONTENT_TRANSLATED_ROOT" + )}?` + ) + ); + } + const slugSplit = slug + .replace(CONTENT_ROOT, "") + .replace(CONTENT_TRANSLATED_ROOT ? CONTENT_TRANSLATED_ROOT : "", "") + .split(path.sep); const document = Document.read( - slug.split(path.sep).slice(1, -1).join(path.sep) + // Remove that leading 'files' and the trailing 'index.(html|md)' + slugSplit.slice(1, -1).join(path.sep) ); if (document) { url = document.url; } + } else if ( + slug.includes(BUILD_OUT_ROOT) && + fs.existsSync(slug) && + fs.existsSync(path.join(slug, "index.json")) + ) { + // Someone probably yarn `yarn build` and copy-n-pasted one of the lines + // it spits out from its CLI. + const { doc } = JSON.parse( + fs.readFileSync(path.join(slug, "index.json")) + ); + if (doc) { + url = doc.mdn_url; + } } else { try { const parsed = new URL(slug); @@ -314,30 +384,25 @@ program "gather-git-history", "Extract all last-modified dates from the git logs" ) - .option("--root ", "Which content root", { - default: CONTENT_ROOT, - }) - .option("--save-history ", `File to save all previous history`, { - default: path.join(os.tmpdir(), "yari-git-history.json"), - }) - .option( - "--load-history ", - `Optional file to load all previous history`, - { - default: path.join(os.tmpdir(), "yari-git-history.json"), - } - ) + .option("--save-history ", "File to save all previous history") + .option("--load-history ", "Optional file to load all previous history") .action( tryOrExit(async ({ options }) => { - const { root, saveHistory, loadHistory } = options; - if (fs.existsSync(loadHistory)) { - console.log( - chalk.yellow(`Reusing existing history from ${loadHistory}`) - ); + const { saveHistory, loadHistory, verbose } = options; + if (loadHistory) { + if (fs.existsSync(loadHistory)) { + console.log( + chalk.yellow(`Reusing existing history from ${loadHistory}`) + ); + } + } + const roots = [CONTENT_ROOT]; + if (CONTENT_TRANSLATED_ROOT) { + roots.push(CONTENT_TRANSLATED_ROOT); } const map = gatherGitHistory( - root, - fs.existsSync(loadHistory) ? loadHistory : null + roots, + loadHistory && fs.existsSync(loadHistory) ? loadHistory : null ); const historyPerLocale = {}; @@ -345,35 +410,78 @@ program const allHistory = {}; for (const [relPath, value] of map) { allHistory[relPath] = value; - const locale = relPath.split("/")[0]; + const locale = relPath.split(path.sep)[0]; if (!historyPerLocale[locale]) { historyPerLocale[locale] = {}; } historyPerLocale[locale][relPath] = value; } + let filesWritten = 0; for (const [locale, history] of Object.entries(historyPerLocale)) { + const root = getRoot(locale); const outputFile = path.join(root, locale, "_githistory.json"); fs.writeFileSync(outputFile, JSON.stringify(history, null, 2), "utf-8"); + filesWritten += 1; + if (verbose) { + console.log( + chalk.green( + `Wrote '${locale}' ${Object.keys( + history + ).length.toLocaleString()} paths into ${outputFile}` + ) + ); + } + } + console.log(chalk.green(`Wrote ${filesWritten} _githistory.json files`)); + if (saveHistory) { + fs.writeFileSync( + saveHistory, + JSON.stringify(allHistory, null, 2), + "utf-8" + ); console.log( chalk.green( - `Wrote '${locale}' ${Object.keys( - history - ).length.toLocaleString()} paths into ${outputFile}` + `Saved ${Object.keys( + allHistory + ).length.toLocaleString()} paths into ${saveHistory}` ) ); } - fs.writeFileSync( - saveHistory, - JSON.stringify(allHistory, null, 2), - "utf-8" - ); - console.log( - chalk.green( - `Saved ${Object.keys( - allHistory - ).length.toLocaleString()} paths into ${saveHistory}` - ) - ); + }) + ) + + .command( + "sync-translated-content", + "Sync translated content (sync with en-US slugs) for a locale" + ) + .argument("", "Locale", { + default: [...VALID_LOCALES.keys()].filter((l) => l !== "en-us"), + validator: [...VALID_LOCALES.keys()].filter((l) => l !== "en-us"), + }) + .action( + tryOrExit(async ({ args, options }) => { + const { locale } = args; + const { verbose } = options; + if (verbose) { + log.setDefaultLevel(log.levels.DEBUG); + } + for (const l of locale) { + const { + movedDocs, + conflictingDocs, + orphanedDocs, + redirectedDocs, + totalDocs, + } = syncAllTranslatedContent(l); + console.log(chalk.green(`Syncing ${l}:`)); + console.log(chalk.green(`Total of ${totalDocs} documents`)); + console.log(chalk.green(`Moved ${movedDocs} documents`)); + console.log(chalk.green(`Conflicting ${conflictingDocs} documents.`)); + console.log(chalk.green(`Orphaned ${orphanedDocs} documents.`)); + console.log( + chalk.green(`Fixed ${redirectedDocs} redirected documents.`) + ); + } }) ) @@ -579,6 +687,214 @@ program ) ); }) + ) + + .command( + "google-analytics-code", + "Generate a .js file that can be used in SSR rendering" + ) + .option("--outfile ", "name of the generated script file", { + default: path.join(BUILD_OUT_ROOT, "static", "js", "ga.js"), + }) + .option( + "--debug", + "whether to use the Google Analytics debug file (defaults to value of $GOOGLE_ANALYTICS_DEBUG)", + { + default: GOOGLE_ANALYTICS_DEBUG, + } + ) + .option( + "--account ", + "Google Analytics account ID (defaults to value of $GOOGLE_ANALYTICS_ACCOUNT)", + { + default: GOOGLE_ANALYTICS_ACCOUNT, + } + ) + .action( + tryOrExit(async ({ options, logger }) => { + const { outfile, debug, account } = options; + if (account) { + const dntHelperCode = fs + .readFileSync( + path.join(__dirname, "mozilla.dnthelper.min.js"), + "utf-8" + ) + .trim(); + + const gaScriptURL = `https://www.google-analytics.com/${ + debug ? "analytics_debug" : "analytics" + }.js`; + + const code = ` +// Mozilla DNT Helper +${dntHelperCode} +// only load GA if DNT is not enabled +if (Mozilla && !Mozilla.dntEnabled()) { + window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date; + ga('create', '${account}', 'mozilla.org'); + ga('set', 'anonymizeIp', true); + ga('send', 'pageview'); + + var gaScript = document.createElement('script'); + gaScript.async = 1; gaScript.src = '${gaScriptURL}'; + document.head.appendChild(gaScript); +}`.trim(); + fs.writeFileSync(outfile, `${code}\n`, "utf-8"); + logger.info( + chalk.green( + `Generated ${outfile} for SSR rendering using ${account}${ + debug ? " (debug mode)" : "" + }.` + ) + ); + } else { + logger.info(chalk.yellow("No Google Analytics code file generated")); + } + }) + ) + + .command("spas", "Build (SSR) all the skeleton apps for single page apps") + .action( + tryOrExit(async ({ options }) => { + await buildSPAs(options); + }) + ) + + .command( + "macros", + "Render and/or remove one or more macros from one or more documents" + ) + .option("-f, --force", "Render even if there are non-fixable flaws", { + default: false, + }) + .argument("", 'must be either "render" or "remove"') + .argument("", "folder of documents to target") + .argument("", "one or more macro names") + .action( + tryOrExit(async ({ args, options }) => { + if (!CONTENT_ROOT) { + throw new Error("CONTENT_ROOT not set"); + } + if (!CONTENT_TRANSLATED_ROOT) { + throw new Error("CONTENT_TRANSLATED_ROOT not set"); + } + const { force } = options; + const { cmd, foldersearch, macros } = args; + const cmdLC = cmd.toLowerCase(); + if (!["render", "remove"].includes(cmdLC)) { + throw new Error(`invalid macros command "${cmd}"`); + } + console.log( + `${cmdLC} the macro(s) ${macros + .map((m) => `"${m}"`) + .join(", ")} within content folder(s) matching "${foldersearch}"` + ); + const documents = Document.findAll({ + folderSearch: foldersearch, + quiet: true, + }); + if (!documents.count) { + throw new Error("no documents found"); + } + + async function renderOrRemoveMacros(document) { + try { + return await kumascript.render(document.url, { + invalidateCache: true, + selective_mode: [cmdLC, macros], + }); + } catch (error) { + if (error.name === "MacroInvocationError") { + error.updateFileInfo(document.fileInfo); + throw new Error( + `error trying to parse ${error.filepath}, line ${error.line} column ${error.column} (${error.error.message})` + ); + } + // Any other unexpected error re-thrown. + throw error; + } + } + + let countTotal = 0; + let countSkipped = 0; + let countModified = 0; + let countNoChange = 0; + for (const document of documents.iter()) { + countTotal++; + console.group(`${document.fileInfo.path}:`); + const originalRawHTML = document.rawHTML; + let [renderedHTML, flaws] = await renderOrRemoveMacros(document); + if (flaws.length) { + const fixableFlaws = flaws.filter((f) => f.redirectInfo); + const nonFixableFlaws = flaws.filter((f) => !f.redirectInfo); + const nonFixableFlawNames = [ + ...new Set(nonFixableFlaws.map((f) => f.name)).values(), + ].join(", "); + if (force || nonFixableFlaws.length === 0) { + // They're all fixable or we don't care if some or all are + // not, but let's at least fix any that we can. + if (nonFixableFlaws.length > 0) { + console.log( + `ignoring ${nonFixableFlaws.length} non-fixable flaw(s) (${nonFixableFlawNames})` + ); + } + if (fixableFlaws.length) { + console.group( + `fixing ${fixableFlaws.length} fixable flaw(s) before proceeding:` + ); + // Let's start fresh so we don't keep the "data-flaw-src" + // attributes that may have been injected during the rendering. + document.rawHTML = originalRawHTML; + for (const flaw of fixableFlaws) { + const suggestion = flaw.macroSource.replace( + flaw.redirectInfo.current, + flaw.redirectInfo.suggested + ); + document.rawHTML = document.rawHTML.replace( + flaw.macroSource, + suggestion + ); + console.log(`${flaw.macroSource} --> ${suggestion}`); + } + console.groupEnd(); + Document.update( + document.url, + document.rawHTML, + document.metadata + ); + // Ok, we've fixed the fixable flaws, now let's render again. + [renderedHTML, flaws] = await renderOrRemoveMacros(document); + } + } else { + // There are one or more flaws that we can't fix, and we're not + // going to ignore them, so let's skip this document. + console.log( + `skipping, has ${nonFixableFlaws.length} non-fixable flaw(s) (${nonFixableFlawNames})` + ); + console.groupEnd(); + countSkipped++; + continue; + } + } + // The Kumascript rendering wraps the result with a "body" tag + // (and more), so let's extract the HTML content of the "body" + // to get what we'll store in the document. + const $ = cheerio.load(renderedHTML); + const newRawHTML = $("body").html(); + if (newRawHTML !== originalRawHTML) { + Document.update(document.url, newRawHTML, document.metadata); + console.log(`modified`); + countModified++; + } else { + console.log(`no change`); + countNoChange++; + } + console.groupEnd(); + } + console.log( + `modified: ${countModified} | no-change: ${countNoChange} | skipped: ${countSkipped} | total: ${countTotal}` + ); + }) ); program.run(); diff --git a/tool/mozilla.dnthelper.min.js b/tool/mozilla.dnthelper.min.js new file mode 100644 index 000000000000..c75dc9ab3afd --- /dev/null +++ b/tool/mozilla.dnthelper.min.js @@ -0,0 +1,33 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +if (typeof Mozilla === "undefined") { + var Mozilla = {}; +} +Mozilla.dntEnabled = function (dnt, ua) { + "use strict"; + var dntStatus = + dnt || navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack; + var userAgent = ua || navigator.userAgent; + var anomalousWinVersions = [ + "Windows NT 6.1", + "Windows NT 6.2", + "Windows NT 6.3", + ]; + var fxMatch = userAgent.match(/Firefox\/(\d+)/); + var ieRegEx = /MSIE|Trident/i; + var isIE = ieRegEx.test(userAgent); + var platform = userAgent.match(/Windows.+?(?=;)/g); + if (isIE && typeof Array.prototype.indexOf !== "function") { + return false; + } else if (fxMatch && parseInt(fxMatch[1], 10) < 32) { + dntStatus = "Unspecified"; + } else if ( + isIE && + platform && + anomalousWinVersions.indexOf(platform.toString()) !== -1 + ) { + dntStatus = "Unspecified"; + } else { + dntStatus = { 0: "Disabled", 1: "Enabled" }[dntStatus] || "Unspecified"; + } + return dntStatus === "Enabled" ? true : false; +}; diff --git a/yarn.lock b/yarn.lock index 0dddb01108a0..e8f356732376 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,13 +9,6 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" - integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== - dependencies: - "@babel/highlight" "^7.8.3" - "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.5.5": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" @@ -23,11 +16,16 @@ dependencies: "@babel/highlight" "^7.12.13" -"@babel/compat-data@^7.12.1", "@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7": +"@babel/compat-data@^7.12.1", "@babel/compat-data@^7.12.7": version "7.12.7" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41" integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw== +"@babel/compat-data@^7.13.8": + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.13.8.tgz#5b783b9808f15cef71547f1b691f34f8ff6003a6" + integrity sha512-EaI33z19T4qN3xLXsGf48M2cDqa6ei9tPZlfLdb2HC+e/cFtREiRd8hdSqDbwdLB0/+gLwqJmCYASH0z2bUdog== + "@babel/core@7.11.6": version "7.11.6" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.6.tgz#3a9455dc7387ff1bac45770650bc13ba04a15651" @@ -72,33 +70,34 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@>=7.9.0", "@babel/core@^7.1.0", "@babel/core@^7.12.1", "@babel/core@^7.12.16", "@babel/core@^7.12.3", "@babel/core@^7.7.5", "@babel/core@^7.8.4": - version "7.12.16" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.16.tgz#8c6ba456b23b680a6493ddcfcd9d3c3ad51cab7c" - integrity sha512-t/hHIB504wWceOeaOoONOhu+gX+hpjfeN6YRBT209X/4sibZQfSF1I0HFRRlBe97UZZosGx5XwUg1ZgNbelmNw== +"@babel/core@>=7.9.0", "@babel/core@^7.1.0", "@babel/core@^7.12.1", "@babel/core@^7.12.3", "@babel/core@^7.13.10", "@babel/core@^7.7.5", "@babel/core@^7.8.4": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.13.10.tgz#07de050bbd8193fcd8a3c27918c0890613a94559" + integrity sha512-bfIYcT0BdKeAZrovpMqX2Mx5NrgAckGbwT982AkdS5GNfn3KMGiprlBAtmBcFZRUmpaufS6WZFP8trvx8ptFDw== dependencies: "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.12.15" - "@babel/helper-module-transforms" "^7.12.13" - "@babel/helpers" "^7.12.13" - "@babel/parser" "^7.12.16" + "@babel/generator" "^7.13.9" + "@babel/helper-compilation-targets" "^7.13.10" + "@babel/helper-module-transforms" "^7.13.0" + "@babel/helpers" "^7.13.10" + "@babel/parser" "^7.13.10" "@babel/template" "^7.12.13" - "@babel/traverse" "^7.12.13" - "@babel/types" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" convert-source-map "^1.7.0" debug "^4.1.0" - gensync "^1.0.0-beta.1" + gensync "^1.0.0-beta.2" json5 "^2.1.2" lodash "^4.17.19" - semver "^5.4.1" + semver "^6.3.0" source-map "^0.5.0" -"@babel/generator@^7.11.6", "@babel/generator@^7.12.1", "@babel/generator@^7.12.13", "@babel/generator@^7.12.15": - version "7.12.15" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.15.tgz#4617b5d0b25cc572474cc1aafee1edeaf9b5368f" - integrity sha512-6F2xHxBiFXWNSGb7vyCUTBF8RCLY66rS0zEPcP8t/nQyXjha5EuK4z7H5o7fWG8B4M7y6mqVWq1J+1PuwRhecQ== +"@babel/generator@^7.11.6", "@babel/generator@^7.12.1", "@babel/generator@^7.13.0", "@babel/generator@^7.13.9": + version "7.13.9" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.13.9.tgz#3a7aa96f9efb8e2be42d38d80e2ceb4c64d8de39" + integrity sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw== dependencies: - "@babel/types" "^7.12.13" + "@babel/types" "^7.13.0" jsesc "^2.5.1" source-map "^0.5.0" @@ -141,15 +140,15 @@ "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-compilation-targets@^7.12.1", "@babel/helper-compilation-targets@^7.12.5": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" - integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw== +"@babel/helper-compilation-targets@^7.12.1", "@babel/helper-compilation-targets@^7.12.5", "@babel/helper-compilation-targets@^7.13.10": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.10.tgz#1310a1678cb8427c07a753750da4f8ce442bdd0c" + integrity sha512-/Xju7Qg1GQO4mHZ/Kcs6Au7gfafgZnwm+a7sy/ow/tV1sHeraRUHbjdat8/UvDor4Tez+siGKDk6zIKtCPKVJA== dependencies: - "@babel/compat-data" "^7.12.5" - "@babel/helper-validator-option" "^7.12.1" + "@babel/compat-data" "^7.13.8" + "@babel/helper-validator-option" "^7.12.17" browserslist "^4.14.5" - semver "^5.5.0" + semver "^6.3.0" "@babel/helper-create-class-features-plugin@^7.12.1": version "7.12.1" @@ -242,12 +241,12 @@ dependencies: "@babel/types" "^7.12.1" -"@babel/helper-member-expression-to-functions@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.13.tgz#c5715695b4f8bab32660dbdcdc2341dec7e3df40" - integrity sha512-B+7nN0gIL8FZ8SvMcF+EPyB21KnCcZHQZFczCxbiNGV/O0rsrSBlWGLzmtBJ3GMjSVMIm4lpFhR+VdVBuIsUcQ== +"@babel/helper-member-expression-to-functions@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.0.tgz#6aa4bb678e0f8c22f58cdb79451d30494461b091" + integrity sha512-yvRf8Ivk62JwisqV1rFRMxiSMDGnN6KH1/mDMmIrij4jztpQNRoHqqMG3U6apYbGRPJpgPalhva9Yd06HlUxJQ== dependencies: - "@babel/types" "^7.12.13" + "@babel/types" "^7.13.0" "@babel/helper-module-imports@^7.0.0": version "7.10.4" @@ -277,19 +276,19 @@ dependencies: "@babel/types" "^7.12.5" -"@babel/helper-module-transforms@^7.11.0", "@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.13.tgz#01afb052dcad2044289b7b20beb3fa8bd0265bea" - integrity sha512-acKF7EjqOR67ASIlDTupwkKM1eUisNAjaSduo5Cz+793ikfnpe7p4Q7B7EWU2PCoSTPWsQkR7hRUWEIZPiVLGA== +"@babel/helper-module-transforms@^7.11.0", "@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.13.0.tgz#42eb4bd8eea68bab46751212c357bfed8b40f6f1" + integrity sha512-Ls8/VBwH577+pw7Ku1QkUWIyRRNHpYlts7+qSqBBFCW3I8QteB9DxfcZ5YJpOwH6Ihe/wn8ch7fMGOP1OhEIvw== dependencies: "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-replace-supers" "^7.12.13" + "@babel/helper-replace-supers" "^7.13.0" "@babel/helper-simple-access" "^7.12.13" "@babel/helper-split-export-declaration" "^7.12.13" "@babel/helper-validator-identifier" "^7.12.11" "@babel/template" "^7.12.13" - "@babel/traverse" "^7.12.13" - "@babel/types" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" lodash "^4.17.19" "@babel/helper-optimise-call-expression@^7.10.4": @@ -342,15 +341,15 @@ "@babel/traverse" "^7.12.1" "@babel/types" "^7.12.1" -"@babel/helper-replace-supers@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.13.tgz#00ec4fb6862546bd3d0aff9aac56074277173121" - integrity sha512-pctAOIAMVStI2TMLhozPKbf5yTEXc0OJa0eENheb4w09SrgOWEs+P4nTOZYJQCqs8JlErGLDPDJTiGIp3ygbLg== +"@babel/helper-replace-supers@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.13.0.tgz#6034b7b51943094cb41627848cb219cb02be1d24" + integrity sha512-Segd5me1+Pz+rmN/NFBOplMbZG3SqRJOBlY+mA0SxAv6rjj7zJqr1AVr3SfzUVTLCv7ZLU5FycOM/SBGuLPbZw== dependencies: - "@babel/helper-member-expression-to-functions" "^7.12.13" + "@babel/helper-member-expression-to-functions" "^7.13.0" "@babel/helper-optimise-call-expression" "^7.12.13" - "@babel/traverse" "^7.12.13" - "@babel/types" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" "@babel/helper-simple-access@^7.12.1": version "7.12.1" @@ -402,6 +401,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz#175567380c3e77d60ff98a54bb015fe78f2178d9" integrity sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A== +"@babel/helper-validator-option@^7.12.17": + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz#d1fbf012e1a79b7eebbfdc6d270baaf8d9eb9831" + integrity sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw== + "@babel/helper-wrap-function@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" @@ -412,16 +416,16 @@ "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helpers@^7.10.4", "@babel/helpers@^7.12.1", "@babel/helpers@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.13.tgz#3c75e993632e4dadc0274eae219c73eb7645ba47" - integrity sha512-oohVzLRZ3GQEk4Cjhfs9YkJA4TdIDTObdBEZGrd6F/T0GPSnuV6l22eMcxlvcvzVIPH3VTtxbseudM1zIE+rPQ== +"@babel/helpers@^7.10.4", "@babel/helpers@^7.12.1", "@babel/helpers@^7.13.10": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.13.10.tgz#fd8e2ba7488533cdeac45cc158e9ebca5e3c7df8" + integrity sha512-4VO883+MWPDUVRF3PhiLBUFHoX/bsLTGFpFK/HqvvfBZz2D57u9XzPVNFVBTc0PW/CWR9BXTOKt8NF4DInUHcQ== dependencies: "@babel/template" "^7.12.13" - "@babel/traverse" "^7.12.13" - "@babel/types" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" -"@babel/highlight@^7.10.4", "@babel/highlight@^7.8.3": +"@babel/highlight@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== @@ -439,10 +443,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.11.5", "@babel/parser@^7.12.13", "@babel/parser@^7.12.16", "@babel/parser@^7.12.3", "@babel/parser@^7.7.0": - version "7.12.16" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.16.tgz#cc31257419d2c3189d394081635703f549fc1ed4" - integrity sha512-c/+u9cqV6F0+4Hpq01jnJO+GLp2DdT63ppz9Xa+6cHaajM9VFzK/iDXiKK65YtpeVwu+ctfS6iqlMqRgQRzeCw== +"@babel/parser@^7.1.0", "@babel/parser@^7.11.5", "@babel/parser@^7.12.13", "@babel/parser@^7.12.3", "@babel/parser@^7.13.0", "@babel/parser@^7.13.10", "@babel/parser@^7.7.0": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.10.tgz#8f8f9bf7b3afa3eabd061f7a5bcdf4fec3c48409" + integrity sha512-0s7Mlrw9uTWkYua7xWr99Wpk2bnGa0ANleKfksYAES8LpWH4gW1OUr42vqKNf0us5UQNfru2wPqMqRITzq/SIQ== "@babel/plugin-proposal-async-generator-functions@^7.12.1": version "7.12.1" @@ -1374,25 +1378,25 @@ "@babel/parser" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.11.5", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.13", "@babel/traverse@^7.7.0": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.13.tgz#689f0e4b4c08587ad26622832632735fb8c4e0c0" - integrity sha512-3Zb4w7eE/OslI0fTp8c7b286/cQps3+vdLW3UcwC8VSJC6GbKn55aeVVu2QJNuCDoeKyptLOFrPq8WqZZBodyA== +"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.11.5", "@babel/traverse@^7.12.1", "@babel/traverse@^7.13.0", "@babel/traverse@^7.7.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.13.0.tgz#6d95752475f86ee7ded06536de309a65fc8966cc" + integrity sha512-xys5xi5JEhzC3RzEmSGrs/b3pJW/o87SypZ+G/PhaE7uqVQNv/jlmVIBXuoh5atqQ434LfXV+sf23Oxj0bchJQ== dependencies: "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.12.13" + "@babel/generator" "^7.13.0" "@babel/helper-function-name" "^7.12.13" "@babel/helper-split-export-declaration" "^7.12.13" - "@babel/parser" "^7.12.13" - "@babel/types" "^7.12.13" + "@babel/parser" "^7.13.0" + "@babel/types" "^7.13.0" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.19" -"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.5", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.12.5", "@babel/types@^7.12.6", "@babel/types@^7.12.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.13.tgz#8be1aa8f2c876da11a9cf650c0ecf656913ad611" - integrity sha512-oKrdZTld2im1z8bDwTOQvUbxKwE+854zc16qWZQlcTqMN00pWxHQ4ZeOq0yDMnisOpRykH2/5Qqcrk/OlbAjiQ== +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.5", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.12.5", "@babel/types@^7.12.6", "@babel/types@^7.12.7", "@babel/types@^7.13.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.13.0.tgz#74424d2816f0171b4100f0ab34e9a374efdf7f80" + integrity sha512-hE+HE8rnG1Z6Wzo+MhaKE5lM5eMx71T4EHJgku2E3xIfaULhDcxiiRxUYgwX8qwP1BBSlag+TdGOt6JAidIZTA== dependencies: "@babel/helper-validator-identifier" "^7.12.11" lodash "^4.17.19" @@ -1878,10 +1882,10 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@mdn/browser-compat-data@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@mdn/browser-compat-data/-/browser-compat-data-3.1.0.tgz#a14a3e6a63b4abd6ad7cc27dd1927a1e2f61c6ac" - integrity sha512-r+0+pyMryDT4tLbKbiRgFOGGKlCG3wv0jQa7zkLOvJNBWjPYaMzJ/OMmEXcZk1lR5cnsBvEf1fbNT1Uf6Olv+w== +"@mdn/browser-compat-data@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@mdn/browser-compat-data/-/browser-compat-data-3.2.0.tgz#42b8f6c2866a77873a67d962428e417fd73201c2" + integrity sha512-pb3IvMWuDxNwWw8MfD7juJO8i5D0mo02LWNjV6T/LYzUeHSu/LL5e5ufUAyrDjsBw3T1+gqqmUBvj5WtuuPGgQ== dependencies: extend "3.0.2" @@ -1890,10 +1894,10 @@ resolved "https://registry.yarnpkg.com/@mdn/dinocons/-/dinocons-0.3.0.tgz#2162eb6c12b36dd9bfc69f344d9150b4b5a3c9ad" integrity sha512-++oqKEzbWtc4DHELnS9R6HoGt+7AGRe2zlxTyk5YCSwouIIiI4DEGuoMCdtBCrZOoHtp2WHZ1mZ6BqEmQh8hLA== -"@mdn/minimalist@^0.7.2": - version "0.7.2" - resolved "https://registry.yarnpkg.com/@mdn/minimalist/-/minimalist-0.7.2.tgz#fe453fc14d8fcf0411f0836e017475b9baa7c405" - integrity sha512-Vf4oV/AsSkk6qiTmQIYW6N5ozxLbt6z82/fbf2Xdlkvw/fUIashiIUlcI09l2BbsBST1lpsWzbLDQO9yqdg/bQ== +"@mdn/minimalist@^0.7.3": + version "0.7.3" + resolved "https://registry.yarnpkg.com/@mdn/minimalist/-/minimalist-0.7.3.tgz#e3f0773f94d1ea0578a4b16c19e604ebb4ef294b" + integrity sha512-4cYfO5SrRSyRY4RUusUK4alMsFZlUD0801Z3t2hQqdXE28QDFLRUNKa/B0Fk6hBs0Y3b3z4rhql+dYmyOE1dBA== "@mdx-js/loader@^1.6.19": version "1.6.21" @@ -2075,19 +2079,19 @@ dependencies: "@sinonjs/commons" "^1.7.0" -"@storybook/addon-a11y@^6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/addon-a11y/-/addon-a11y-6.1.18.tgz#b6e7c9302f556368ce9d7fb36532fe0868319f3a" - integrity sha512-zaIHwGU5vluDWYmthoF0TQYpoLdL1gX1kT/3kCmo2lFNwGyr0HewX3aar7HAImsUn/s3ksweZrW5iv394bDK8w== - dependencies: - "@storybook/addons" "6.1.18" - "@storybook/api" "6.1.18" - "@storybook/channels" "6.1.18" - "@storybook/client-api" "6.1.18" - "@storybook/client-logger" "6.1.18" - "@storybook/components" "6.1.18" - "@storybook/core-events" "6.1.18" - "@storybook/theming" "6.1.18" +"@storybook/addon-a11y@^6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/addon-a11y/-/addon-a11y-6.1.21.tgz#28e44c9f3b7b9e8a319f59b112092fb9aa15fb96" + integrity sha512-FTHQ0QdPhL+0D/E/og/xkT6tIEEOSCgCV+eX9UcDn3shnxVAHEHbqJ7Yf1fF5B/nRx+ptY57c9O64vIFd7UMHg== + dependencies: + "@storybook/addons" "6.1.21" + "@storybook/api" "6.1.21" + "@storybook/channels" "6.1.21" + "@storybook/client-api" "6.1.21" + "@storybook/client-logger" "6.1.21" + "@storybook/components" "6.1.21" + "@storybook/core-events" "6.1.21" + "@storybook/theming" "6.1.21" axe-core "^4.0.1" core-js "^3.0.1" global "^4.3.2" @@ -2097,17 +2101,17 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/addon-actions@6.1.18", "@storybook/addon-actions@^6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-6.1.18.tgz#9dad0f2be52db778ec4519f130d9e0c46188b504" - integrity sha512-05p52RWst3jS5txwqplLZFWuZ89PMtsHojxs4rWRQ6mrgPwiTE0MUl+S1wMihabLm9CYUUJ0/41QNb2Uv0+hhw== - dependencies: - "@storybook/addons" "6.1.18" - "@storybook/api" "6.1.18" - "@storybook/client-api" "6.1.18" - "@storybook/components" "6.1.18" - "@storybook/core-events" "6.1.18" - "@storybook/theming" "6.1.18" +"@storybook/addon-actions@6.1.21", "@storybook/addon-actions@^6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-6.1.21.tgz#881dceb0ed650fe28086d9993703f8081b29f4ce" + integrity sha512-H+nhSgK3X5L+JfArsC9ufvgJzQwPN9UXBxhMl74faEDCo9RGmq9ywNcjn9XlZGGnJ3jCaYrI/T1u0J7F6PBrTA== + dependencies: + "@storybook/addons" "6.1.21" + "@storybook/api" "6.1.21" + "@storybook/client-api" "6.1.21" + "@storybook/components" "6.1.21" + "@storybook/core-events" "6.1.21" + "@storybook/theming" "6.1.21" core-js "^3.0.1" fast-deep-equal "^3.1.1" global "^4.3.2" @@ -2120,17 +2124,17 @@ util-deprecate "^1.0.2" uuid "^8.0.0" -"@storybook/addon-backgrounds@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/addon-backgrounds/-/addon-backgrounds-6.1.18.tgz#1f1b232a76e6c97a5c9e86fc0f51b3fe999f04a8" - integrity sha512-8qgA1oKyplJQNtdTsf88zxa/q+YN25C0VCRe8HoL1r5gE7n7qf0bQofq+aMv11upbVNxdFXcoABEyiq/CfTX0g== - dependencies: - "@storybook/addons" "6.1.18" - "@storybook/api" "6.1.18" - "@storybook/client-logger" "6.1.18" - "@storybook/components" "6.1.18" - "@storybook/core-events" "6.1.18" - "@storybook/theming" "6.1.18" +"@storybook/addon-backgrounds@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/addon-backgrounds/-/addon-backgrounds-6.1.21.tgz#ada6c0a8a375855f99da0a7de770dd2c245d536d" + integrity sha512-4kJB6UcrqOo8fjm1BnfEOvw8ysPSfzIn2j5Q7h3WzoQF0VbU62+EQLTznluFfMjJ1I2FMCTz8YcwDOZn1FNlig== + dependencies: + "@storybook/addons" "6.1.21" + "@storybook/api" "6.1.21" + "@storybook/client-logger" "6.1.21" + "@storybook/components" "6.1.21" + "@storybook/core-events" "6.1.21" + "@storybook/theming" "6.1.21" core-js "^3.0.1" global "^4.3.2" memoizerific "^1.11.3" @@ -2138,24 +2142,24 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/addon-controls@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/addon-controls/-/addon-controls-6.1.18.tgz#aa85d6003854820bc5d4cf87148a7e4cc2ece207" - integrity sha512-I3dI6L5up03Uiw1RMVN0HVUgHlfN4CTgI8tex6L49dERUlcDSrfq417DXGvq8ipxHUnb/+0CVYkJ7p6TWzc3yQ== - dependencies: - "@storybook/addons" "6.1.18" - "@storybook/api" "6.1.18" - "@storybook/client-api" "6.1.18" - "@storybook/components" "6.1.18" - "@storybook/node-logger" "6.1.18" - "@storybook/theming" "6.1.18" +"@storybook/addon-controls@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/addon-controls/-/addon-controls-6.1.21.tgz#14e3473cfa6dcdb88e57a74e1a42b57bd87c69ee" + integrity sha512-IJgZWD2E9eLKj8DJLA9lT63N4jPfVneFJ05gnPco01ZJCEiDAo7babP5Ns2UTJDUaQEtX0m04UoIkidcteWKsA== + dependencies: + "@storybook/addons" "6.1.21" + "@storybook/api" "6.1.21" + "@storybook/client-api" "6.1.21" + "@storybook/components" "6.1.21" + "@storybook/node-logger" "6.1.21" + "@storybook/theming" "6.1.21" core-js "^3.0.1" ts-dedent "^2.0.0" -"@storybook/addon-docs@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/addon-docs/-/addon-docs-6.1.18.tgz#bda4cbeba5318c8c4651e1b9cc1ff7d0bb770209" - integrity sha512-7aTKD5+WULiMQ9zBqQ81sHSNBcayhFZWfH19P/ikR3UqBj1gsWjNH8l8vGVbaJiV+z53pmnnGfCYGq1HkL9oCA== +"@storybook/addon-docs@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/addon-docs/-/addon-docs-6.1.21.tgz#2ab12698200e7353c4789d705b0a1972f6d268d8" + integrity sha512-MvTmxrOSo+zZ5MaMx9LVWM8DlvVHeryCJKPJx8BYCEN38r8mIK7uCFYok8oMPmACrVe0MfXOdJCm1HKkBKjsMg== dependencies: "@babel/core" "^7.12.1" "@babel/generator" "^7.12.1" @@ -2166,18 +2170,18 @@ "@mdx-js/loader" "^1.6.19" "@mdx-js/mdx" "^1.6.19" "@mdx-js/react" "^1.6.19" - "@storybook/addons" "6.1.18" - "@storybook/api" "6.1.18" - "@storybook/client-api" "6.1.18" - "@storybook/client-logger" "6.1.18" - "@storybook/components" "6.1.18" - "@storybook/core" "6.1.18" - "@storybook/core-events" "6.1.18" + "@storybook/addons" "6.1.21" + "@storybook/api" "6.1.21" + "@storybook/client-api" "6.1.21" + "@storybook/client-logger" "6.1.21" + "@storybook/components" "6.1.21" + "@storybook/core" "6.1.21" + "@storybook/core-events" "6.1.21" "@storybook/csf" "0.0.1" - "@storybook/node-logger" "6.1.18" - "@storybook/postinstall" "6.1.18" - "@storybook/source-loader" "6.1.18" - "@storybook/theming" "6.1.18" + "@storybook/node-logger" "6.1.21" + "@storybook/postinstall" "6.1.21" + "@storybook/source-loader" "6.1.21" + "@storybook/theming" "6.1.21" acorn "^7.1.0" acorn-jsx "^5.1.0" acorn-walk "^7.0.0" @@ -2198,34 +2202,34 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/addon-essentials@^6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/addon-essentials/-/addon-essentials-6.1.18.tgz#2c545b79393013d50b2fab0d4396b6c32257ea8c" - integrity sha512-c+/wM8ZHm2bv1penZJpbpDmdm7HQUxXadLKI/jtyW/87pc3yhFLZZDwPeoMtJDI1pVfWOO2IOP4LiX9cRf53uQ== - dependencies: - "@storybook/addon-actions" "6.1.18" - "@storybook/addon-backgrounds" "6.1.18" - "@storybook/addon-controls" "6.1.18" - "@storybook/addon-docs" "6.1.18" - "@storybook/addon-toolbars" "6.1.18" - "@storybook/addon-viewport" "6.1.18" - "@storybook/addons" "6.1.18" - "@storybook/api" "6.1.18" - "@storybook/node-logger" "6.1.18" +"@storybook/addon-essentials@^6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/addon-essentials/-/addon-essentials-6.1.21.tgz#ed528fbdebbc841459a8264f74e517c04b0e1a27" + integrity sha512-kdQ/hnfwwodWVFvMdvSbhOyLv/cUJyhgVRyIamrURP9I0OlWhpOAHhwMjAT2KKceutN3UjNpSCqFNSL4dMu25g== + dependencies: + "@storybook/addon-actions" "6.1.21" + "@storybook/addon-backgrounds" "6.1.21" + "@storybook/addon-controls" "6.1.21" + "@storybook/addon-docs" "6.1.21" + "@storybook/addon-toolbars" "6.1.21" + "@storybook/addon-viewport" "6.1.21" + "@storybook/addons" "6.1.21" + "@storybook/api" "6.1.21" + "@storybook/node-logger" "6.1.21" core-js "^3.0.1" regenerator-runtime "^0.13.7" ts-dedent "^2.0.0" -"@storybook/addon-links@^6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/addon-links/-/addon-links-6.1.18.tgz#e94aae6b4eb20f7068efc008fe9a3f658d1cf8cf" - integrity sha512-FgDxmkpHT+3dq/XT2zU77mdSCxTqQVR0ivdFZNXQ8bATbQg7byp7YOGwy3fqMBYYdQDp9K/VStc3YLpbo+R49g== +"@storybook/addon-links@^6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/addon-links/-/addon-links-6.1.21.tgz#59b04c4a0bd1c8dc86fecea64a2531154df382e6" + integrity sha512-DFPK6aYs9VIs1tO0PJ+mBwg64ZLv6NcVwFJ083ghCj/hR+0+3NRox+oRHXCWq7RHtnJeU4VKEiRx2EpE9L9Bkg== dependencies: - "@storybook/addons" "6.1.18" - "@storybook/client-logger" "6.1.18" - "@storybook/core-events" "6.1.18" + "@storybook/addons" "6.1.21" + "@storybook/client-logger" "6.1.21" + "@storybook/core-events" "6.1.21" "@storybook/csf" "0.0.1" - "@storybook/router" "6.1.18" + "@storybook/router" "6.1.21" "@types/qs" "^6.9.0" core-js "^3.0.1" global "^4.3.2" @@ -2234,62 +2238,62 @@ regenerator-runtime "^0.13.7" ts-dedent "^2.0.0" -"@storybook/addon-toolbars@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/addon-toolbars/-/addon-toolbars-6.1.18.tgz#484c26d668b63f481e5c8439c4b7eb800824491d" - integrity sha512-+a/H80OJ+2eCymGLlvMUmGh3AVpy5bGsw5b4AROvz1iYyYoMEJz0/Bi+VwU6bjHXn8I4Aqj727Al4XNYZtFU+A== +"@storybook/addon-toolbars@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/addon-toolbars/-/addon-toolbars-6.1.21.tgz#7e03ef74fe448c5b4e378cb08e1d79b9d8496d9f" + integrity sha512-89NtiqLT3ltb7Jb7rAug7jnWIDh6SxXa9i3mOoKEIcvuRJEmxGLF1Z79A+zXOJOKBUEEUgfJCtVS2lixakgwKA== dependencies: - "@storybook/addons" "6.1.18" - "@storybook/api" "6.1.18" - "@storybook/client-api" "6.1.18" - "@storybook/components" "6.1.18" + "@storybook/addons" "6.1.21" + "@storybook/api" "6.1.21" + "@storybook/client-api" "6.1.21" + "@storybook/components" "6.1.21" core-js "^3.0.1" -"@storybook/addon-viewport@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/addon-viewport/-/addon-viewport-6.1.18.tgz#10fdbb0b3ff5ead84f2d4c10f91a80db1cb8de6e" - integrity sha512-Sf3RhdAekmfkrcU8gFbgJFCEuo4uJmGIPaHIBuBUYxc/IT1Iz7b4k6WwPh+Dd0K6hro/2ZeWSiFTM4af17uNZw== - dependencies: - "@storybook/addons" "6.1.18" - "@storybook/api" "6.1.18" - "@storybook/client-logger" "6.1.18" - "@storybook/components" "6.1.18" - "@storybook/core-events" "6.1.18" - "@storybook/theming" "6.1.18" +"@storybook/addon-viewport@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/addon-viewport/-/addon-viewport-6.1.21.tgz#893090cca12f55abb4d8acade5f04e58e6317b1f" + integrity sha512-FrQk0BXCI4HdbBn9+8b+Cp2HvsweZkgW/joKfcF2vVLoasUBB4bl+9uU3HV/3a08glgjPl24caDMPgoRKS90WQ== + dependencies: + "@storybook/addons" "6.1.21" + "@storybook/api" "6.1.21" + "@storybook/client-logger" "6.1.21" + "@storybook/components" "6.1.21" + "@storybook/core-events" "6.1.21" + "@storybook/theming" "6.1.21" core-js "^3.0.1" global "^4.3.2" memoizerific "^1.11.3" prop-types "^15.7.2" regenerator-runtime "^0.13.7" -"@storybook/addons@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.1.18.tgz#b953f355350376808914f015b689dbda4e20b864" - integrity sha512-sI/ifk3RLswItRUejt4tCi3IMS9oBUd2NK4Kns1PF+x4NIry/yuOeE/de3Dz5tPjJhg9jJuBDLhxEaqRFq3Uzg== - dependencies: - "@storybook/api" "6.1.18" - "@storybook/channels" "6.1.18" - "@storybook/client-logger" "6.1.18" - "@storybook/core-events" "6.1.18" - "@storybook/router" "6.1.18" - "@storybook/theming" "6.1.18" +"@storybook/addons@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.1.21.tgz#94bb66fc51d1dfee80d0fe84f5b83c10045651b5" + integrity sha512-xo5TGu9EZVCqgh3D1veVnfuGzyKDWWsvOMo18phVqRxj21G3/+hScVyfIYwNTv7Ys5/Ahp9JxJUMXL3V3ny+tw== + dependencies: + "@storybook/api" "6.1.21" + "@storybook/channels" "6.1.21" + "@storybook/client-logger" "6.1.21" + "@storybook/core-events" "6.1.21" + "@storybook/router" "6.1.21" + "@storybook/theming" "6.1.21" core-js "^3.0.1" global "^4.3.2" regenerator-runtime "^0.13.7" -"@storybook/api@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.1.18.tgz#289d9907ed36a0c2af933c871a36a72acd911c43" - integrity sha512-VfntmrMEijkbdNDncpr9bv2RXVn12hCui1YcK3S6bCXnMi/OFp6aO5+jrb/GZqqZzLeVK005N1HTE2Ivq1IBJg== +"@storybook/api@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.1.21.tgz#be753ca8d3602efe4a11783c81c689463bee0825" + integrity sha512-QjZk70VSXMw/wPPoWdMp5Bl9VmkfmGhIz8PALrFLLEZHjzptpfZE2qkGEEJHG0NAksFUv6NxGki2/632dzR7Ug== dependencies: "@reach/router" "^1.3.3" - "@storybook/channels" "6.1.18" - "@storybook/client-logger" "6.1.18" - "@storybook/core-events" "6.1.18" + "@storybook/channels" "6.1.21" + "@storybook/client-logger" "6.1.21" + "@storybook/core-events" "6.1.21" "@storybook/csf" "0.0.1" - "@storybook/router" "6.1.18" + "@storybook/router" "6.1.21" "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.1.18" + "@storybook/theming" "6.1.21" "@types/reach__router" "^1.3.7" core-js "^3.0.1" fast-deep-equal "^3.1.1" @@ -2302,38 +2306,38 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/channel-postmessage@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.1.18.tgz#9f4aa17612cc3c52a040c99c64d80838f835c410" - integrity sha512-49Tae2wwY+b2BL6b+Z+tqM/k8pX5ox/SE23ahtWtovrp/OHOYoXrMXTYuU8MA58xqjR4QhB4KjVB5e0V/iQxYQ== +"@storybook/channel-postmessage@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.1.21.tgz#acce71833499dba4c4e686de09f5b281a3239842" + integrity sha512-SuI/ffqcPT02VNda32k8V0D4XpLm5bIy8CLIs0OAnQg+zt5KjGBpQBngk3q4EaAiOoAhbMWAQiUzRUXfrgkgXg== dependencies: - "@storybook/channels" "6.1.18" - "@storybook/client-logger" "6.1.18" - "@storybook/core-events" "6.1.18" + "@storybook/channels" "6.1.21" + "@storybook/client-logger" "6.1.21" + "@storybook/core-events" "6.1.21" core-js "^3.0.1" global "^4.3.2" qs "^6.6.0" telejson "^5.0.2" -"@storybook/channels@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.1.18.tgz#834cafb45e91d39c99160dbaa2ac74720bbaef5a" - integrity sha512-XMuHD15B7SWpUJgaTP/6Axa66bykObN1YBcyZ2mOqBVQK4DVf51yI/zp/4ZndgE/MxG5uqVWuOEDOJvSAENREw== +"@storybook/channels@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.1.21.tgz#adbfae5f4767234c5b17d9578be983584dddead4" + integrity sha512-7WoizMjyHqCyvcWncLexSg9FLPIErWAZL4NvluEthwsHSO2sDybn9mh1pzsFHdYMuTP6ml06Zt9ayWMtIveHDg== dependencies: core-js "^3.0.1" ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/client-api@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.1.18.tgz#7569830375d6618e8b0f3b48c5789798e7474751" - integrity sha512-iwHLrirUFM4zQuzrKD+mN14F8/IdpMz4aYRBRDHf/FbG9F0dM27RF8S9a3y7thhAVPiNNT8HJ4YO0ZMTdZ5idg== +"@storybook/client-api@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.1.21.tgz#c9f72bbc9bf9d12cc931eb824f6912173c73b0b3" + integrity sha512-uLFXQ5z1LLWYnw1w+YUJPzIPRVlwCCvM2Si37aHDZn1F3fnbMg+huEhEqIQ1TTTw3wiJoTeGuShYvqyaiNwq/w== dependencies: - "@storybook/addons" "6.1.18" - "@storybook/channel-postmessage" "6.1.18" - "@storybook/channels" "6.1.18" - "@storybook/client-logger" "6.1.18" - "@storybook/core-events" "6.1.18" + "@storybook/addons" "6.1.21" + "@storybook/channel-postmessage" "6.1.21" + "@storybook/channels" "6.1.21" + "@storybook/client-logger" "6.1.21" + "@storybook/core-events" "6.1.21" "@storybook/csf" "0.0.1" "@types/qs" "^6.9.0" "@types/webpack-env" "^1.15.3" @@ -2348,23 +2352,23 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/client-logger@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.1.18.tgz#36c7e33090e70bc274e1a39ef5ebbfe31c886f6a" - integrity sha512-o+lXoi61SLgNbDGrfDJsUdkbc2eDzNL1DMkSenksis7kiblOsBzO+7S0UiguyQ/gku2wYyksGx71A/TzE5JsgQ== +"@storybook/client-logger@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.1.21.tgz#fe7d9e645ddb4eb9dc18fdacea24b4baf11bc6c9" + integrity sha512-QJV+gnVM2fQ4M7lSkRLCXkOw/RU+aEtUefo9TAnXxPHK3UGG+DyvLmha6fHGaz9GAcFxyWtgqCyVOhMe03Q35g== dependencies: core-js "^3.0.1" global "^4.3.2" -"@storybook/components@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.1.18.tgz#23ab5a7d735bd8e09cad2e487f8636aa099998a9" - integrity sha512-YUF/JpkZ6ghcxm26V6zOXl4iS2OOhNhfCp1CxVBu+71k78nziOQdxBmT0aG0LXzZ+WSF8pMiXzvBTrei+YTxyg== +"@storybook/components@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.1.21.tgz#7b9bfd51e73c179654a114275e5073f494d2a005" + integrity sha512-2NjkyS1yeYXlRY7azt88woqd6eqJA00oloIxgMAFLVpRmvFxoHalY61wNrvxl2QSu9cNofp984AbGc8gPbizBA== dependencies: "@popperjs/core" "^2.5.4" - "@storybook/client-logger" "6.1.18" + "@storybook/client-logger" "6.1.21" "@storybook/csf" "0.0.1" - "@storybook/theming" "6.1.18" + "@storybook/theming" "6.1.21" "@types/overlayscrollbars" "^1.9.0" "@types/react-color" "^3.0.1" "@types/react-syntax-highlighter" "11.0.4" @@ -2380,19 +2384,20 @@ react-popper-tooltip "^3.1.1" react-syntax-highlighter "^13.5.0" react-textarea-autosize "^8.1.1" + regenerator-runtime "^0.13.7" ts-dedent "^2.0.0" -"@storybook/core-events@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.1.18.tgz#6417eb25d36d7e26b990552dc1d3c4db1679e0d4" - integrity sha512-FdhDTsL8u9759jJ4nDthen5x8+mpmdMXIXat1HYL1RNgjXZFRUiwcWha8ELQFVTgpjJ9U5ZTF8C5B0B1W47Etw== +"@storybook/core-events@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.1.21.tgz#11f537f78f8c73ba5e627b57b282a279793a3511" + integrity sha512-KWqnh1C7M1pT//WfQb3AD60yTR8jL48AfaeLGto2gO9VK7VVgj/EGsrXZP/GTL90ygyExbbBI5gkr7EBTu/HYw== dependencies: core-js "^3.0.1" -"@storybook/core@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/core/-/core-6.1.18.tgz#0186007c97a3e64f936eac784590d45eee6473d7" - integrity sha512-FJAJX39HvyL85riUBjRaiyKmbyppNmzZ4dU/hZpinmXHJDk9d857lmkjSz96N24vwRc5uinsodaPs+ccIUONNg== +"@storybook/core@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/core/-/core-6.1.21.tgz#e4c9f5ab361e0c4690f2827a71308757f9d46395" + integrity sha512-ITqSid3VVL5/fkx7Wwu7QfD2Y5xjl3V6p7yUpLSzP8GpBnCHKDvJ4pFJUdJlGQ0mnGz6ACa0qVnSc+V0hiy1sA== dependencies: "@babel/core" "^7.12.3" "@babel/plugin-proposal-class-properties" "^7.12.1" @@ -2416,20 +2421,20 @@ "@babel/preset-react" "^7.12.1" "@babel/preset-typescript" "^7.12.1" "@babel/register" "^7.12.1" - "@storybook/addons" "6.1.18" - "@storybook/api" "6.1.18" - "@storybook/channel-postmessage" "6.1.18" - "@storybook/channels" "6.1.18" - "@storybook/client-api" "6.1.18" - "@storybook/client-logger" "6.1.18" - "@storybook/components" "6.1.18" - "@storybook/core-events" "6.1.18" + "@storybook/addons" "6.1.21" + "@storybook/api" "6.1.21" + "@storybook/channel-postmessage" "6.1.21" + "@storybook/channels" "6.1.21" + "@storybook/client-api" "6.1.21" + "@storybook/client-logger" "6.1.21" + "@storybook/components" "6.1.21" + "@storybook/core-events" "6.1.21" "@storybook/csf" "0.0.1" - "@storybook/node-logger" "6.1.18" - "@storybook/router" "6.1.18" + "@storybook/node-logger" "6.1.21" + "@storybook/router" "6.1.21" "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.1.18" - "@storybook/ui" "6.1.18" + "@storybook/theming" "6.1.21" + "@storybook/ui" "6.1.21" "@types/glob-base" "^0.3.0" "@types/micromatch" "^4.0.1" "@types/node-fetch" "^2.5.4" @@ -2477,7 +2482,7 @@ pretty-hrtime "^1.0.3" qs "^6.6.0" raw-loader "^4.0.1" - react-dev-utils "^10.0.0" + react-dev-utils "^11.0.3" regenerator-runtime "^0.13.7" resolve-from "^5.0.0" serve-favicon "^2.5.0" @@ -2503,10 +2508,10 @@ dependencies: lodash "^4.17.15" -"@storybook/node-logger@6.1.18", "@storybook/node-logger@^6.1.16": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-6.1.18.tgz#cf45d30f3456b7eeb664233df05f654e5773cb18" - integrity sha512-gsiHQVratKBSoP11IqU2Td5W+KUc0qg+czqhzzp1JNMJ25/xBtCJ8MAIOX5JFhovzvB7H0j8y8VNF1YgmcmOQg== +"@storybook/node-logger@6.1.21", "@storybook/node-logger@^6.1.19": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-6.1.21.tgz#bcf882209697acfe4fc60bc224676400bce260ed" + integrity sha512-wQZZw4n1PG3kGOsczWCBC6+8RagYkrGYDqsVOpUcs5shGbPg5beCXDuzP4nxz2IlsoP9ZtTSaX741H791OIOjA== dependencies: "@types/npmlog" "^4.1.2" chalk "^4.0.0" @@ -2514,10 +2519,10 @@ npmlog "^4.1.2" pretty-hrtime "^1.0.3" -"@storybook/postinstall@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/postinstall/-/postinstall-6.1.18.tgz#f98fc0c3b2b7dcbfb7725133179612f12ca9b673" - integrity sha512-QVj3VbgdCPHO+nrB1zOyEwdr5pLpMyf257Sqk+wR3pcEdewEYoVMP9sxUULBlQqPYSzPVzlZzgyAzGWZlCE/jA== +"@storybook/postinstall@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/postinstall/-/postinstall-6.1.21.tgz#a7598b53291e3ab74400feb492359cc0d725d9a3" + integrity sha512-mg3fNqdQYiz6ivQIU1WMKqtqrFt5GySmsPCar3Y+xOdMClmpx6pZYcpiN782h8CIFA1XnldGR3TKVtWP848qOg== dependencies: core-js "^3.0.1" @@ -2533,17 +2538,17 @@ react-docgen-typescript-plugin "^0.6.2" semver "^7.3.2" -"@storybook/react@^6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/react/-/react-6.1.18.tgz#895cdc252299a181442131f0b3b2506f273888c0" - integrity sha512-wAkUn3LPzoo10LgIZ28beJT9hrWAKR5rEl6g3Y4yTqmvfWdaXZOtHomEchq7Cru7C+1jQ60mDMtwu+D2FZP4bQ== +"@storybook/react@^6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/react/-/react-6.1.21.tgz#1c4d01dba8d8f130f9b7da4038a380eeb9c61f38" + integrity sha512-j3gq/ssWxRCCH5iCHbP3ihXSGS7lVWh1HpmBmGbbhHGHgdmSPsRjwDXiQGE81EmE7bzbC8NECBhU3zHJ6h1TvA== dependencies: "@babel/preset-flow" "^7.12.1" "@babel/preset-react" "^7.12.1" "@pmmmwh/react-refresh-webpack-plugin" "^0.4.2" - "@storybook/addons" "6.1.18" - "@storybook/core" "6.1.18" - "@storybook/node-logger" "6.1.18" + "@storybook/addons" "6.1.21" + "@storybook/core" "6.1.21" + "@storybook/node-logger" "6.1.21" "@storybook/semver" "^7.3.2" "@types/webpack-env" "^1.15.3" babel-plugin-add-react-displayname "^0.0.5" @@ -2553,17 +2558,17 @@ global "^4.3.2" lodash "^4.17.15" prop-types "^15.7.2" - react-dev-utils "^10.0.0" + react-dev-utils "^11.0.3" react-docgen-typescript-plugin "^0.6.2" react-refresh "^0.8.3" regenerator-runtime "^0.13.7" ts-dedent "^2.0.0" webpack "^4.44.2" -"@storybook/router@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.1.18.tgz#e9ed563bd06f4a2a746709415f0c20d116b4cac5" - integrity sha512-eY8snYjAESgDdC4sZFJIZ6FTJU4hY1oRqk24nTxhUiEV7U7JAqcXPpz+kaoiAoXnB+H9vXh5MADs9pXS654pBw== +"@storybook/router@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.1.21.tgz#0a822fa9cc67589a082f7a10fff15c8413f17706" + integrity sha512-m75WvUhoCBWDVekICAdbkidji/w5hCjHo+M8L13UghpwXWEnyr4/QqvkOb/PcSC8aZzxeMqSCpRQ1o6LWULneg== dependencies: "@reach/router" "^1.3.3" "@types/reach__router" "^1.3.7" @@ -2580,13 +2585,13 @@ core-js "^3.6.5" find-up "^4.1.0" -"@storybook/source-loader@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/source-loader/-/source-loader-6.1.18.tgz#5221b9408f30454ae514f5d19fafdd81650647bf" - integrity sha512-Fca8gGqQ5rosXLZpBdqpwItbl7iQ4QZZ5MqJkt7FyEqVX7n4O8WjIiAqNbeCGJnc1keohoGIPWOMt1gXvwZQkA== +"@storybook/source-loader@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/source-loader/-/source-loader-6.1.21.tgz#23cda170dd77d188df52cb3f2ab8ef191e04b8a0" + integrity sha512-eMbmQG3a/7SFxVN+KGJKfk4uxLqQz2Nk95zvHyRvoX15LRyMnFvmdvmULe5vwRev8Npd4AS0EZ37m3jAEcD0ig== dependencies: - "@storybook/addons" "6.1.18" - "@storybook/client-logger" "6.1.18" + "@storybook/addons" "6.1.21" + "@storybook/client-logger" "6.1.21" "@storybook/csf" "0.0.1" core-js "^3.0.1" estraverse "^4.2.0" @@ -2597,15 +2602,15 @@ regenerator-runtime "^0.13.7" source-map "^0.7.3" -"@storybook/theming@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.1.18.tgz#a2aa08a52d589ce9662b9e789506ffa42d97da24" - integrity sha512-q97mKSLLnB2LmjzKiNpip7jvvrVPDi+bnYoUCWCt04zuXiaIVU8Bu4i0Y/w3Y3bHqfRbae3gZErFr89Z+f77vA== +"@storybook/theming@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.1.21.tgz#b8e612e5a39b77f7e63a5f9ea322ed62adb0d5b0" + integrity sha512-yq7+/mpdljRdSRJYw/In/9tnDGXIUDe//mhyMftFfrB2mq6zi1yAZpowCerWhiDE2ipGkrfzIYx/Sn7bcaXgqg== dependencies: "@emotion/core" "^10.1.1" "@emotion/is-prop-valid" "^0.8.6" "@emotion/styled" "^10.0.23" - "@storybook/client-logger" "6.1.18" + "@storybook/client-logger" "6.1.21" core-js "^3.0.1" deep-object-diff "^1.1.0" emotion-theming "^10.0.19" @@ -2615,21 +2620,21 @@ resolve-from "^5.0.0" ts-dedent "^2.0.0" -"@storybook/ui@6.1.18": - version "6.1.18" - resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-6.1.18.tgz#e88ad5ba0e041127c8624f15b3071e796348b817" - integrity sha512-EKOja3ji0gHxnKWFBt+nK7xuBOzKTEKJ3+PiW0+QS0jZ18EkR7U7h0U052jNXdiI1c6Sck5n9+gI5EylzN18+Q== +"@storybook/ui@6.1.21": + version "6.1.21" + resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-6.1.21.tgz#bf7cac3ba9a6250f573fa1ba12d4592891d5ece2" + integrity sha512-2nRb5egnSBKbosuR7g5PsuM4XnRLXZUf7TBjwT6eRlomnE2wrWM5DtTLpFeUpDob0SI5hPlOV1xCpPz3XmeyyA== dependencies: "@emotion/core" "^10.1.1" - "@storybook/addons" "6.1.18" - "@storybook/api" "6.1.18" - "@storybook/channels" "6.1.18" - "@storybook/client-logger" "6.1.18" - "@storybook/components" "6.1.18" - "@storybook/core-events" "6.1.18" - "@storybook/router" "6.1.18" + "@storybook/addons" "6.1.21" + "@storybook/api" "6.1.21" + "@storybook/channels" "6.1.21" + "@storybook/client-logger" "6.1.21" + "@storybook/components" "6.1.21" + "@storybook/core-events" "6.1.21" + "@storybook/router" "6.1.21" "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.1.18" + "@storybook/theming" "6.1.21" "@types/markdown-to-jsx" "^6.11.0" copy-to-clipboard "^3.0.8" core-js "^3.0.1" @@ -2818,6 +2823,11 @@ resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.1.1.tgz#f0d92c12f87079ddfd1b29f614758b9696bc29e3" integrity sha512-XO6INPbZCxdprl+9qa/AAbFFOMzzwqYxpjPgLICrMD6C2FCw6qfJOPcBk6JqqPLSaZ/Qx87qn4rpPmPMwaAK6w== +"@trysound/sax@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.1.1.tgz#3348564048e7a2d7398c935d466c0414ebb6a669" + integrity sha512-Z6DoceYb/1xSg5+e+ZlPZ9v0N16ZvZ+wYMraFue4HYrE4ttONKtsvruIRf6t9TBR0YvSOfi1hUU0fJfBLCDYow== + "@types/anymatch@*": version "1.3.1" resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a" @@ -2893,10 +2903,10 @@ resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.5.tgz#b14efa8852b7768d898906613c23f688713e02cd" integrity sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ== -"@types/eslint@^7.2.4": - version "7.2.5" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.5.tgz#92172ecf490c2fce4b076739693d75f30376d610" - integrity sha512-Dc6ar9x16BdaR3NSxSF7T4IjL9gxxViJq8RmFd+2UAyA+K6ck2W+gUwfgpG/y9TPyUuBL35109bbULpEynvltA== +"@types/eslint@^7.2.6": + version "7.2.6" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.6.tgz#5e9aff555a975596c03a98b59ecd103decc70c3c" + integrity sha512-I+1sYH+NPQ3/tVqCeUSBwTE/0heyvtXqpIopUUArlBm0Kpocb8FbMa3AZ/ASKIFpN3rnEx932TTXDbt9OXsNDw== dependencies: "@types/estree" "*" "@types/json-schema" "*" @@ -3141,10 +3151,10 @@ "@types/react" "*" "@types/reactcss" "*" -"@types/react-dom@^17.0.1": - version "17.0.1" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.1.tgz#d92d77d020bfb083e07cc8e0ac9f933599a4d56a" - integrity sha512-yIVyopxQb8IDZ7SOHeTovurFq+fXiPICa+GV3gp0Xedsl+MwQlMLKmvrnEjFbQxjliH5YVAEWFh975eVNmKj7Q== +"@types/react-dom@^17.0.2": + version "17.0.2" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.2.tgz#35654cf6c49ae162d5bc90843d5437dc38008d43" + integrity sha512-Icd9KEgdnFfJs39KyRyr0jQ7EKhq8U6CcHRMGAS45fp5qgUvxL3ujUCfWFttUK2UErqZNj97t9gsVPNAqcwoCg== dependencies: "@types/react" "*" @@ -3155,12 +3165,13 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^17.0.2": - version "17.0.2" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.2.tgz#3de24c4efef902dd9795a49c75f760cbe4f7a5a8" - integrity sha512-Xt40xQsrkdvjn1EyWe1Bc0dJLcil/9x2vAuW7ya+PuQip4UYUaXyhzWmAbwRsdMgwOFHpfp7/FFZebDU6Y8VHA== +"@types/react@*", "@types/react@^17.0.3": + version "17.0.3" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.3.tgz#ba6e215368501ac3826951eef2904574c262cc79" + integrity sha512-wYOUxIgs2HZZ0ACNiIayItyluADNbONl7kt8lkLjVK8IitMH5QMyAh75Fwhmo37r1m7L2JaFj03sIfxBVDvRAg== dependencies: "@types/prop-types" "*" + "@types/scheduler" "*" csstype "^3.0.2" "@types/reactcss@*": @@ -3192,6 +3203,11 @@ dependencies: "@types/node" "*" +"@types/scheduler@*": + version "0.16.1" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.1.tgz#18845205e86ff0038517aab7a18a62a6b9f71275" + integrity sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA== + "@types/source-list-map@*": version "0.1.2" resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" @@ -3338,45 +3354,36 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727" integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ== +"@typescript-eslint/types@4.15.2": + version "4.15.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.15.2.tgz#04acf3a2dc8001a88985291744241e732ef22c60" + integrity sha512-r7lW7HFkAarfUylJ2tKndyO9njwSyoy6cpfDKWPX6/ctZA+QyaYscAHXVAfJqtnY6aaTwDYrOhp+ginlbc7HfQ== + "@typescript-eslint/types@4.8.2": version "4.8.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.8.2.tgz#c862dd0e569d9478eb82d6aee662ea53f5661a36" integrity sha512-z1/AVcVF8ju5ObaHe2fOpZYEQrwHyZ7PTOlmjd3EoFeX9sv7UekQhfrCmgUO7PruLNfSHrJGQvrW3Q7xQ8EoAw== -"@typescript-eslint/typescript-estree@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853" - integrity sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w== - dependencies: - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/visitor-keys" "3.10.1" - debug "^4.1.1" - glob "^7.1.6" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" - -"@typescript-eslint/typescript-estree@4.8.2": - version "4.8.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.8.2.tgz#eeec34707d8577600fb21661b5287226cc8b3bed" - integrity sha512-HToGNwI6fekH0dOw3XEVESUm71Onfam0AKin6f26S2FtUmO7o3cLlWgrIaT1q3vjB3wCTdww3Dx2iGq5wtUOCg== +"@typescript-eslint/typescript-estree@3.10.1", "@typescript-eslint/typescript-estree@4.8.2", "@typescript-eslint/typescript-estree@>=4.15.2": + version "4.15.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.2.tgz#c2f7a1e94f3428d229d5ecff3ead6581ee9b62fa" + integrity sha512-cGR8C2g5SPtHTQvAymEODeqx90pJHadWsgTtx6GbnTWKqsg7yp6Eaya9nFzUd4KrKhxdYTTFBiYeTPQaz/l8bw== dependencies: - "@typescript-eslint/types" "4.8.2" - "@typescript-eslint/visitor-keys" "4.8.2" + "@typescript-eslint/types" "4.15.2" + "@typescript-eslint/visitor-keys" "4.15.2" debug "^4.1.1" globby "^11.0.1" is-glob "^4.0.1" - lodash "^4.17.15" semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/visitor-keys@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931" - integrity sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ== +"@typescript-eslint/visitor-keys@4.15.2": + version "4.15.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.2.tgz#3d1c7979ce75bf6acf9691109bd0d6b5706192b9" + integrity sha512-TME1VgSb7wTwgENN5KVj4Nqg25hP8DisXxNBojM4Nn31rYaNDIocNm5cmjOFfh42n7NVERxWrDFoETO/76ePyg== dependencies: - eslint-visitor-keys "^1.1.0" + "@typescript-eslint/types" "4.15.2" + eslint-visitor-keys "^2.0.0" "@typescript-eslint/visitor-keys@4.8.2": version "4.8.2" @@ -3570,10 +3577,10 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -abab@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.4.tgz#6dfa57b417ca06d21b2478f0e638302f99c2405c" - integrity sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ== +abab@^2.0.3, abab@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" + integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== abbrev@1: version "1.1.1" @@ -3626,16 +3633,16 @@ acorn@^6.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== -acorn@^7.1.0, acorn@^7.1.1: - version "7.4.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c" - integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w== - -acorn@^7.4.0: +acorn@^7.1.0, acorn@^7.1.1, acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== +acorn@^8.0.5: + version "8.0.5" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.0.5.tgz#a3bfb872a74a6a7f661bc81b9849d9cac12601b7" + integrity sha512-v+DieK/HJkJOpFBETDJioequtc3PfxsWMaxIdIwujtF7FEV/MAyDQLlm6/zPvr7Mix07mLh6ccVwIsloceodlg== + address@1.1.2, address@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" @@ -4142,15 +4149,6 @@ axobject-query@^2.2.0: resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== -babel-code-frame@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - babel-eslint@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" @@ -4868,16 +4866,6 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@4.10.0: - version "4.10.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.10.0.tgz#f179737913eaf0d2b98e4926ac1ca6a15cbcc6a9" - integrity sha512-TpfK0TDgv71dzuTsEAlQiHeWQ/tiPqgNZVdv046fvNtBZrjbv2O3TsWCDU0AWGJJKCF/KsjNdLzR9hXOsh/CfA== - dependencies: - caniuse-lite "^1.0.30001035" - electron-to-chromium "^1.3.378" - node-releases "^1.1.52" - pkg-up "^3.1.0" - browserslist@4.14.2: version "4.14.2" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.2.tgz#1b3cec458a1ba87588cc5e9be62f19b6d48813ce" @@ -5186,7 +5174,7 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001093, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001157: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001093, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001157: version "1.0.30001180" resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001180.tgz" integrity sha512-n8JVqXuZMVSPKiPiypjFtDTXc4jWIdjxull0f92WLo7e1MSi3uJ3NvveakSh/aCl1QKFAvIz3vIj0v+0K+FrXw== @@ -5248,7 +5236,7 @@ chalk@4.1.0, chalk@^4.0.0, chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^1.0.0, chalk@^1.1.3: +chalk@^1.0.0: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= @@ -5313,7 +5301,7 @@ cheerio@1.0.0-rc.5: parse5 "^6.0.0" parse5-htmlparser2-tree-adapter "^6.0.0" -"chokidar@>=2.0.0 <4.0.0", chokidar@^3.2.2, chokidar@^3.3.0, chokidar@^3.4.1: +"chokidar@>=2.0.0 <4.0.0", chokidar@^3.2.2, chokidar@^3.4.1: version "3.5.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== @@ -5667,6 +5655,11 @@ commander@^7.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.0.0.tgz#3e2bbfd8bb6724760980988fb5b22b7ee6b71ab2" integrity sha512-ovx/7NkTrnPuIV8sqk/GjUIIM1+iUQeqA3ye2VNpq9sVoiZsooObWlQy+OPWGI17GDaEoybuAGJm6U8yC077BA== +commander@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.1.0.tgz#f2eaecf131f10e36e07d894698226e36ae0eb5ff" + integrity sha512-pRxBna3MJe6HKnBGsDyMv8ETbptw3axEdYHoqNh7gu5oDcew8fs0xnivZGm06Ogk8zGAJ9VX+OPEr2GXEQK4dg== + common-tags@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" @@ -5999,15 +5992,6 @@ cross-env@^7.0.3: dependencies: cross-spawn "^7.0.1" -cross-spawn@7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.1.tgz#0ab56286e0f7c24e153d04cc2aa027e43a9a5d14" - integrity sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - cross-spawn@7.0.3, cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -6188,6 +6172,14 @@ css-tree@1.0.0-alpha.39: mdn-data "2.0.6" source-map "^0.6.1" +css-tree@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.2.tgz#9ae393b5dafd7dae8a622475caec78d3d8fbd7b5" + integrity sha512-wCoWush5Aeo48GLhfHPbmvZs59Z+M7k5+B1xDnXbdWNcEF423DoFdqSWE0PM5aNk5nI5cp1q7ms36zGApY/sKQ== + dependencies: + mdn-data "2.0.14" + source-map "^0.6.1" + css-what@2.1: version "2.1.3" resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" @@ -6303,6 +6295,13 @@ csso@^4.0.2: dependencies: css-tree "1.0.0-alpha.39" +csso@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" + integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== + dependencies: + css-tree "^1.1.2" + cssom@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" @@ -6313,7 +6312,7 @@ cssom@~0.3.6: resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== -cssstyle@^2.2.0: +cssstyle@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== @@ -6393,7 +6392,7 @@ debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: dependencies: ms "2.1.2" -debug@^3.0.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: +debug@^3.0.0, debug@^3.1.1, debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -6413,10 +6412,10 @@ decamelize@^1.1.0, decamelize@^1.1.2, decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= -decimal.js@^10.2.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.0.tgz#39466113a9e036111d02f82489b5fd6b0b5ed231" - integrity sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw== +decimal.js@^10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.1.tgz#238ae7b0f0c793d3e3cea410108b35a2c01426a3" + integrity sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw== decode-uri-component@^0.2.0: version "0.2.0" @@ -6726,14 +6725,6 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" -dir-glob@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034" - integrity sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag== - dependencies: - arrify "^1.0.1" - path-type "^3.0.0" - dir-glob@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" @@ -7024,7 +7015,7 @@ ejs@^2.6.1: resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== -electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.488: +electron-to-chromium@^1.3.488: version "1.3.523" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.523.tgz#494080b318ba929614eebd04405b94c359ea9333" integrity sha512-D4/3l5DpciddD92IDRtpLearQSGzly8FwBJv+nITvLH8YJrFabpDFe4yuiOJh2MS4/EsXqyQTXyw1toeYPtshQ== @@ -7335,7 +7326,7 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escodegen@^1.12.0, escodegen@^1.14.1: +escodegen@^1.12.0: version "1.14.3" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== @@ -7347,6 +7338,18 @@ escodegen@^1.12.0, escodegen@^1.14.1: optionalDependencies: source-map "~0.6.1" +escodegen@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" + integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + eslint-config-react-app@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-6.0.0.tgz#ccff9fc8e36b322902844cbd79197982be355a0e" @@ -7414,10 +7417,10 @@ eslint-plugin-import@^2.22.1: resolve "^1.17.0" tsconfig-paths "^3.9.0" -eslint-plugin-jest@24.1.3, eslint-plugin-jest@^24.1.0: - version "24.1.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.1.3.tgz#fa3db864f06c5623ff43485ca6c0e8fc5fe8ba0c" - integrity sha512-dNGGjzuEzCE3d5EPZQ/QGtmlMotqnYWD/QpCZ1UuZlrMAdhG5rldh0N0haCvhGnUkSeuORS5VNROwF9Hrgn3Lg== +eslint-plugin-jest@24.2.1, eslint-plugin-jest@^24.1.0: + version "24.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.2.1.tgz#7e84f16a3ca6589b86be9732a93d71367a4ed627" + integrity sha512-s24ve8WUu3DLVidvlSzaqlOpTZre9lTkZTAO+a7X0WMtj8HraWTiTEkW3pbDT1xVxqEHMWSv+Kx7MyqR50nhBw== dependencies: "@typescript-eslint/experimental-utils" "^4.0.1" @@ -7520,12 +7523,12 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== -eslint-webpack-plugin@^2.1.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/eslint-webpack-plugin/-/eslint-webpack-plugin-2.4.0.tgz#dcfd2653d0e15e52251f34dd3690ce60718d5589" - integrity sha512-j0lAJj3RnStAFdIH2P0+nsEImiBijwogZhL1go4bI6DE+9OhQuOmJ/xtmxkLtNr1w0cf5SRNkDlmIe8t/pHgww== +eslint-webpack-plugin@^2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/eslint-webpack-plugin/-/eslint-webpack-plugin-2.5.2.tgz#4ee17577d6392bf72048080a1678d6237183db81" + integrity sha512-ndD9chZ/kaGnjjx7taRg7c6FK/YKb29SSYzaLtPBIYLYJQmZtuKqtQbAvTS2ymiMQT6X0VW9vZIHK0KLstv93Q== dependencies: - "@types/eslint" "^7.2.4" + "@types/eslint" "^7.2.6" arrify "^2.0.1" jest-worker "^26.6.2" micromatch "^4.0.2" @@ -7912,7 +7915,7 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== -fast-glob@^2.0.2, fast-glob@^2.2.6: +fast-glob@^2.2.6: version "2.2.7" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== @@ -7980,14 +7983,7 @@ fault@^1.0.0: dependencies: format "^0.2.0" -faye-websocket@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" - integrity sha1-TkkvjQTftviQA1B/btvy1QHnxvQ= - dependencies: - websocket-driver ">=0.5.1" - -faye-websocket@~0.11.1: +faye-websocket@^0.11.3: version "0.11.3" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e" integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA== @@ -8040,10 +8036,10 @@ figures@^3.0.0: dependencies: escape-string-regexp "^1.0.5" -file-entry-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a" - integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA== +file-entry-cache@^6.0.0, file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== dependencies: flat-cache "^3.0.4" @@ -8064,10 +8060,10 @@ file-system-cache@^1.0.5: fs-extra "^0.30.0" ramda "^0.21.0" -file-type@16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-16.2.0.tgz#d4f1da71ddda758db7f15f93adfaed09ce9e2715" - integrity sha512-1Wwww3mmZCMmLjBfslCluwt2mxH80GsAXYrvPnfQ42G1EGWag336kB1iyCgyn7UXiKY3cJrNykXPrCwA7xb5Ag== +file-type@16.3.0: + version "16.3.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-16.3.0.tgz#f03af91db30f92cc9a0b335c0644c46101522f6d" + integrity sha512-ZA0hV64611vJT42ltw0T9IDwHApQuxRdrmQZWTeDmeAUtZBBVSQW3nSQqhhW1cAgpXgqcJvm410BYHXJQ9AymA== dependencies: readable-web-to-node-stream "^3.0.0" strtok3 "^6.0.3" @@ -8079,7 +8075,7 @@ file-type@5.2.0, file-type@^5.2.0: resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" integrity sha1-LdvqfHP/42No365J3DOMBYwritY= -file-type@^10.4.0: +file-type@^10.10.0, file-type@^10.4.0: version "10.11.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-10.11.0.tgz#2961d09e4675b9fb9a3ee6b69e9cd23f43fd1890" integrity sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw== @@ -8135,11 +8131,6 @@ filenamify@^2.0.0: strip-outer "^1.0.0" trim-repeated "^1.0.0" -filesize@6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-6.0.1.tgz#f850b509909c7c86f7e450ea19006c31c2ed3d2f" - integrity sha512-u4AYWPgbI5GBhs6id1KdImZWn5yfyFrrQ8OWZdN7ZMfA8Bf4HcO0BGo9bmUIEV8yrp8I1xVfJ/dn90GtFNNJcg== - filesize@6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/filesize/-/filesize-6.1.0.tgz#e81bdaa780e2451d714d71c0d7a4f3238d37ad00" @@ -8347,20 +8338,6 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= -fork-ts-checker-webpack-plugin@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-3.1.1.tgz#a1642c0d3e65f50c2cc1742e9c0a80f441f86b19" - integrity sha512-DuVkPNrM12jR41KM2e+N+styka0EgLkTnXmNcXdgOM37vtGeY+oCBK/Jx0hzSeEU6memFCtWb4htrHPMDfwwUQ== - dependencies: - babel-code-frame "^6.22.0" - chalk "^2.4.1" - chokidar "^3.3.0" - micromatch "^3.1.10" - minimatch "^3.0.4" - semver "^5.6.0" - tapable "^1.0.0" - worker-rpc "^0.1.0" - fork-ts-checker-webpack-plugin@4.1.6, fork-ts-checker-webpack-plugin@^4.1.4: version "4.1.6" resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-4.1.6.tgz#5055c703febcf37fa06405d400c122b905167fc5" @@ -8576,10 +8553,10 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" -gensync@^1.0.0-beta.1: - version "1.0.0-beta.1" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" - integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== +gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-caller-file@^2.0.1: version "2.0.5" @@ -8836,19 +8813,6 @@ globby@11.0.1: merge2 "^1.3.0" slash "^3.0.0" -globby@8.0.2: - version "8.0.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.2.tgz#5697619ccd95c5275dbb2d6faa42087c1a941d8d" - integrity sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w== - dependencies: - array-union "^1.0.1" - dir-glob "2.0.0" - fast-glob "^2.0.2" - glob "^7.1.2" - ignore "^3.3.5" - pify "^3.0.0" - slash "^1.0.0" - globby@^10.0.0: version "10.0.2" resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" @@ -8919,10 +8883,10 @@ good-listener@^1.2.2: dependencies: delegate "^3.1.2" -got@11.8.1: - version "11.8.1" - resolved "https://registry.yarnpkg.com/got/-/got-11.8.1.tgz#df04adfaf2e782babb3daabc79139feec2f7e85d" - integrity sha512-9aYdZL+6nHmvJwHALLwKSUZ0hMwGaJGYv3hoPLPgnT8BoBXm1SjnZeky+91tfwJaDzun2s4RsBRy48IEYv2q2Q== +got@11.8.2: + version "11.8.2" + resolved "https://registry.yarnpkg.com/got/-/got-11.8.2.tgz#7abb3959ea28c31f3576f1576c1effce23f33599" + integrity sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ== dependencies: "@sindresorhus/is" "^4.0.0" "@szmarczak/http-timer" "^4.0.5" @@ -9368,10 +9332,10 @@ html-tags@^3.1.0: resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== -html-validate@4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/html-validate/-/html-validate-4.6.0.tgz#bb0377a55affde8b7fbbdaf95895339dfb97c4c4" - integrity sha512-yL19NuUeGDr6eXzdnFo0pxU0g9WB+Bziw/bTAlE49Pnc60C9ApHyoQiNqyUUmgRvxhdMoXSIQRYuDhw3UbDcag== +html-validate@4.6.1: + version "4.6.1" + resolved "https://registry.yarnpkg.com/html-validate/-/html-validate-4.6.1.tgz#9fc01072d36e518f75b8dc51157fc2e1d45ccb9f" + integrity sha512-vFmvy70+UUySVbekufawocXyfIUDRex6cwX5JMPpHZ3FzTmWnarUTGttXHk1l6/v67c/DDnsdZiJHaLMZWcOUg== dependencies: "@babel/code-frame" "^7.10.4" "@html-validate/stylish" "1.0.0" @@ -9607,11 +9571,6 @@ ignore-loader@^0.1.2: resolved "https://registry.yarnpkg.com/ignore-loader/-/ignore-loader-0.1.2.tgz#d81f240376d0ba4f0d778972c3ad25874117a463" integrity sha1-2B8kA3bQuk8Nd4lyw60lh0EXpGM= -ignore@^3.3.5: - version "3.3.10" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" - integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== - ignore@^4.0.3, ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" @@ -9622,13 +9581,20 @@ ignore@^5.1.1, ignore@^5.1.4, ignore@^5.1.8: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== -image-size@0.9.3: - version "0.9.3" - resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.9.3.tgz#f7efce6b0a1649b44b9bc43b9d9a5acf272264b6" - integrity sha512-5SakFa79uhUVSjKeQE30GVzzLJ0QNzB53+I+/VD1vIesD6GP6uatWIlgU0uisFNLt1u0d6kBydp7yfk+lLJhLQ== +image-size@0.9.5: + version "0.9.5" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.9.5.tgz#03a4224c5b643d2a0a7d21ee561cf7edf8985421" + integrity sha512-HvnQBt6+u5PjmZvaFpJOB1VfrDdwxu8p456HAfYXPzEKl6GJKrNJZKDaN0A/0b1kJ7JpDUU6eBT7hmiREwzqWA== dependencies: queue "6.0.1" +image-type@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/image-type/-/image-type-4.1.0.tgz#72a88d64ff5021371ed67b9a466442100be57cd1" + integrity sha512-CFJMJ8QK8lJvRlTCEgarL4ro6hfDQKif2HjSvYCdQZESaIPV4v9imrf7BQHK+sQeTeNeMpWciR9hyC/g8ybXEg== + dependencies: + file-type "^10.10.0" + imagemin-gifsicle@7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/imagemin-gifsicle/-/imagemin-gifsicle-7.0.0.tgz#1a7ab136a144c4678657ba3b6c412f80805d26b0" @@ -9647,10 +9613,10 @@ imagemin-mozjpeg@9.0.0: is-jpg "^2.0.0" mozjpeg "^7.0.0" -imagemin-pngquant@9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/imagemin-pngquant/-/imagemin-pngquant-9.0.1.tgz#ecf22f522bdb734a503ecc21bdd7bc3d0230edcc" - integrity sha512-PYyo9G/xwddf+Qqlqe3onz5ZH7p6vHYVVkiuuczUjxZmfekyY77RXaOA/AR6FnVoeQxGa/pDtEK5xUKOcVo+sA== +imagemin-pngquant@9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/imagemin-pngquant/-/imagemin-pngquant-9.0.2.tgz#38155702b0cc4f60f671ba7c2b086ea3805d9567" + integrity sha512-cj//bKo8+Frd/DM8l6Pg9pws1pnDUjgb7ae++sUX1kUVdv2nrngPykhiUOgFeE0LGY/LmUbCf4egCHC4YUcZSg== dependencies: execa "^4.0.0" is-png "^2.0.0" @@ -9658,13 +9624,13 @@ imagemin-pngquant@9.0.1: ow "^0.17.0" pngquant-bin "^6.0.0" -imagemin-svgo@8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/imagemin-svgo/-/imagemin-svgo-8.0.0.tgz#34658069f9e4a537e455467b433830fffaeb3c6e" - integrity sha512-++fDnnxsLT+4rpt8babwiIbzapgBzeS2Kgcy+CwgBvgSRFltBFhX2WnpCziMtxhRCzqJcCE9EcHWZP/sj+G3rQ== +imagemin-svgo@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/imagemin-svgo/-/imagemin-svgo-9.0.0.tgz#749370804608917a67d4ff590f07a87756aec006" + integrity sha512-uNgXpKHd99C0WODkrJ8OO/3zW3qjgS4pW7hcuII0RcHN3tnKxDjJWcitdVC/TZyfIqSricU8WfrHn26bdSW62g== dependencies: is-svg "^4.2.1" - svgo "^1.3.2" + svgo "^2.1.0" imagemin@7.0.1: version "7.0.1" @@ -9679,15 +9645,10 @@ imagemin@7.0.1: p-pipe "^3.0.0" replace-ext "^1.0.0" -immer@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d" - integrity sha512-O3sR1/opvCDGLEVcvrGTMtLac8GJ5IwZC4puPrLuRj3l7ICKvkmA0vGuU9OW8mV9WIBRnaxp5GJh9IEAaNOoYg== - -immer@7.0.9: - version "7.0.9" - resolved "https://registry.yarnpkg.com/immer/-/immer-7.0.9.tgz#28e7552c21d39dd76feccd2b800b7bc86ee4a62e" - integrity sha512-Vs/gxoM4DqNAYR7pugIxi0Xc8XAun/uy7AQu4fLLqaTBHxjOP9pJ266Q9MWA/ly4z6rAFZbvViOtihxUZ7O28A== +immer@8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/immer/-/immer-8.0.1.tgz#9c73db683e2b3975c424fb0572af5889877ae656" + integrity sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA== import-cwd@^2.0.0: version "2.1.0" @@ -9810,25 +9771,6 @@ inline-style-parser@0.1.1: resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== -inquirer@7.0.4: - version "7.0.4" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.4.tgz#99af5bde47153abca23f5c7fc30db247f39da703" - integrity sha512-Bu5Td5+j11sCkqfqmUTiwv+tWisMtP0L7Q8WrqA2C/BbBhy1YTdFrvjjlrKq8oagA/tLQBski2Gcx/Sqyi2qSQ== - dependencies: - ansi-escapes "^4.2.1" - chalk "^2.4.2" - cli-cursor "^3.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.15" - mute-stream "0.0.8" - run-async "^2.2.0" - rxjs "^6.5.3" - string-width "^4.1.0" - strip-ansi "^5.1.0" - through "^2.3.6" - inquirer@^6.0.0: version "6.5.2" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" @@ -9867,10 +9809,10 @@ inquirer@^7.0.0: strip-ansi "^6.0.0" through "^2.3.6" -inquirer@^7.3.3: - version "7.3.3" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" - integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== +inquirer@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.0.0.tgz#957a46db1abcf0fdd2ab82deb7470e90afc7d0ac" + integrity sha512-ON8pEJPPCdyjxj+cxsYRe6XfCJepTxANdNnTebsTuQgXpRyZRRT9t4dJwjRubgmvn20CLSEnozRUayXyM9VTXA== dependencies: ansi-escapes "^4.2.1" chalk "^4.1.0" @@ -9878,10 +9820,10 @@ inquirer@^7.3.3: cli-width "^3.0.0" external-editor "^3.0.3" figures "^3.0.0" - lodash "^4.17.19" + lodash "^4.17.21" mute-stream "0.0.8" run-async "^2.4.0" - rxjs "^6.6.0" + rxjs "^6.6.6" string-width "^4.1.0" strip-ansi "^6.0.0" through "^2.3.6" @@ -10347,11 +10289,6 @@ is-potential-custom-element-name@^1.0.0: resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397" integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c= -is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= - is-regex@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" @@ -10418,10 +10355,10 @@ is-string@^1.0.4, is-string@^1.0.5: resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== -is-svg@4.2.1, is-svg@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-4.2.1.tgz#095b496e345fec9211c2a7d5d021003e040d6f81" - integrity sha512-PHx3ANecKsKNl5y5+Jvt53Y4J7MfMpbNZkv384QNiswMKAWIbvcqbPz+sYbFKJI8Xv3be01GSFniPmoaP+Ai5A== +is-svg@4.2.2, is-svg@^4.2.1: + version "4.2.2" + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-4.2.2.tgz#a4ea0f3f78dada7085db88f1e85b6f845626cfae" + integrity sha512-JlA7Mc7mfWjdxxTkJ094oUK9amGD7gQaj5xA/NCY0vlVvZ1stmj4VX+bRuwOMN93IHRZ2ctpPH/0FO6DqvQ5Rw== dependencies: html-comment-regex "^1.1.2" @@ -11196,11 +11133,6 @@ js-string-escape@^1.0.1: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= - js-yaml@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.0.0.tgz#f426bc0ff4b4051926cd588c71113183409a121f" @@ -11221,36 +11153,36 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= -jsdom@^16.2.1, jsdom@^16.4.0: - version "16.4.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.4.0.tgz#36005bde2d136f73eee1a830c6d45e55408edddb" - integrity sha512-lYMm3wYdgPhrl7pDcRmvzPhhrGVBeVhPIqeHjzeiHN3DFmD1RBpbExbi8vU7BJdH8VAZYovR8DMt0PNNDM7k8w== +jsdom@^16.2.1, jsdom@^16.4.0, jsdom@^16.5.0: + version "16.5.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.5.0.tgz#9e453505600cc5a70b385750d35256f380730cc4" + integrity sha512-QxZH0nmDTnTTVI0YDm4RUlaUPl5dcyn62G5TMDNfMmTW+J1u1v9gCR8WR+WZ6UghAa7nKJjDOFaI00eMMWvJFQ== dependencies: - abab "^2.0.3" - acorn "^7.1.1" + abab "^2.0.5" + acorn "^8.0.5" acorn-globals "^6.0.0" cssom "^0.4.4" - cssstyle "^2.2.0" + cssstyle "^2.3.0" data-urls "^2.0.0" - decimal.js "^10.2.0" + decimal.js "^10.2.1" domexception "^2.0.1" - escodegen "^1.14.1" + escodegen "^2.0.0" html-encoding-sniffer "^2.0.1" is-potential-custom-element-name "^1.0.0" nwsapi "^2.2.0" - parse5 "5.1.1" + parse5 "6.0.1" request "^2.88.2" - request-promise-native "^1.0.8" - saxes "^5.0.0" + request-promise-native "^1.0.9" + saxes "^5.0.1" symbol-tree "^3.2.4" - tough-cookie "^3.0.1" + tough-cookie "^4.0.0" w3c-hr-time "^1.0.2" w3c-xmlserializer "^2.0.0" webidl-conversions "^6.1.0" whatwg-encoding "^1.0.5" whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" - ws "^7.2.3" + ws "^7.4.4" xml-name-validator "^3.0.0" jsesc@^2.5.1: @@ -11323,7 +11255,7 @@ json-to-ast@^2.0.3: code-error-fragment "0.0.230" grapheme-splitter "^1.0.4" -json3@^3.3.2: +json3@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== @@ -11703,7 +11635,7 @@ lodash.uniq@4.5.0, lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@4.17.15, "lodash@>=3.5 <5", lodash@>=4.17.15, lodash@^4.0.1, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.16, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.5: +lodash@4.17.15, "lodash@>=3.5 <5", lodash@>=4.17.15, lodash@^4.0.1, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.16, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.5: version "4.17.19" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== @@ -11746,6 +11678,11 @@ loglevel@^1.6.8: resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.8.tgz#8a25fb75d092230ecd4457270d80b54e28011171" integrity sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA== +loglevel@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197" + integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw== + loglevelnext@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/loglevelnext/-/loglevelnext-1.0.5.tgz#36fc4f5996d6640f539ff203ba819641680d75a2" @@ -12010,10 +11947,15 @@ mdast-util-to-string@^1.0.0: resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz#27055500103f51637bd07d01da01eb1967a43527" integrity sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A== -mdn-data@2.0.16: - version "2.0.16" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.16.tgz#b4f8cf050e4d679cbd185d1daf6370c3f434d731" - integrity sha512-z5eL/oKlBXGWk8MRrzk8Ll+owSRCXppDPJ5zBtoHhk4MUEVG5MEkHy5gdzvqpB53LUc+4F9CSVDcdgwKSY1Crg== +mdn-data@2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" + integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== + +mdn-data@2.0.17: + version "2.0.17" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.17.tgz#8618b37fd552270a5c917ab79cf962adea4eb3b6" + integrity sha512-3hZJh85oEm88+uWhoutFhoHA/Rjq/Tf8fsPxpYYLYOJei5uofjR23EOVJwA4qYCF2L21PXLN/o67KVAS7LGxLg== mdn-data@2.0.4: version "2.0.4" @@ -12505,10 +12447,10 @@ node-fetch@^2.6.0: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== -node-forge@0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579" - integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ== +node-forge@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" + integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== node-int64@^0.4.0: version "0.4.0" @@ -12561,7 +12503,7 @@ node-notifier@^8.0.0: uuid "^8.3.0" which "^2.0.2" -node-releases@^1.1.52, node-releases@^1.1.58: +node-releases@^1.1.58: version "1.1.60" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.60.tgz#6948bdfce8286f0b5d0e5a88e8384e954dfe7084" integrity sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA== @@ -13195,7 +13137,7 @@ p-try@^1.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= -p-try@^2.0.0: +p-try@^2.0.0, p-try@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== @@ -13300,12 +13242,7 @@ parse5-htmlparser2-tree-adapter@^6.0.0: dependencies: parse5 "^6.0.1" -parse5@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" - integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== - -parse5@^6.0.0, parse5@^6.0.1: +parse5@6.0.1, parse5@^6.0.0, parse5@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== @@ -13511,7 +13448,7 @@ pkg-dir@^5.0.0: dependencies: find-up "^5.0.0" -pkg-up@3.1.0, pkg-up@^3.1.0: +pkg-up@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== @@ -14321,12 +14258,12 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier-plugin-packagejson@^2.2.9: - version "2.2.9" - resolved "https://registry.yarnpkg.com/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.2.9.tgz#279b45013af22d12a0d3f58d5e4c4f17a36e131c" - integrity sha512-znjjFUNZSzwfa4s9aBfgdy/5EqwvG+BFAcKQ95RpMhVkFRHL+wsuPk0nsuShLhsMWRH01XPzixWKEd9Oz6TLyg== +prettier-plugin-packagejson@^2.2.10: + version "2.2.10" + resolved "https://registry.yarnpkg.com/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.2.10.tgz#143524f65c01cd5112375af5be98e56727b6de8a" + integrity sha512-/meFZrpGSg/F3jXspBJikHBLf/m1ol6XJjYslM++AQno7B/SPNrGICMMck0qHBU+f7vVfqbZmdC/OO5opU3HPw== dependencies: - sort-package-json "1.48.1" + sort-package-json "1.49.0" prettier@2.2.1: version "2.2.1" @@ -14491,7 +14428,7 @@ pseudomap@^1.0.2: resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= -psl@^1.1.28: +psl@^1.1.28, psl@^1.1.33: version "1.8.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== @@ -14729,40 +14666,10 @@ react-color@^2.17.0: reactcss "^1.2.0" tinycolor2 "^1.4.1" -react-dev-utils@^10.0.0: - version "10.2.1" - resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-10.2.1.tgz#f6de325ae25fa4d546d09df4bb1befdc6dd19c19" - integrity sha512-XxTbgJnYZmxuPtY3y/UV0D8/65NKkmaia4rXzViknVnZeVlklSh8u6TnaEYPfAi/Gh1TP4mEOXHI6jQOPbeakQ== - dependencies: - "@babel/code-frame" "7.8.3" - address "1.1.2" - browserslist "4.10.0" - chalk "2.4.2" - cross-spawn "7.0.1" - detect-port-alt "1.1.6" - escape-string-regexp "2.0.0" - filesize "6.0.1" - find-up "4.1.0" - fork-ts-checker-webpack-plugin "3.1.1" - global-modules "2.0.0" - globby "8.0.2" - gzip-size "5.1.1" - immer "1.10.0" - inquirer "7.0.4" - is-root "2.1.0" - loader-utils "1.2.3" - open "^7.0.2" - pkg-up "3.1.0" - react-error-overlay "^6.0.7" - recursive-readdir "2.2.2" - shell-quote "1.7.2" - strip-ansi "6.0.0" - text-table "0.2.0" - -react-dev-utils@^11.0.2: - version "11.0.2" - resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-11.0.2.tgz#98aed16ef50f808ee17b32def75eb15f89655802" - integrity sha512-xG7GlMoYkrgc2M1kDCHKRywXMDbFnjOB+/VzpytQyYBusEzR8NlGTMmUbvN86k94yyKu5XReHB8eZC2JZrNchQ== +react-dev-utils@^11.0.3: + version "11.0.3" + resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-11.0.3.tgz#b61ed499c7d74f447d4faddcc547e5e671e97c08" + integrity sha512-4lEA5gF4OHrcJLMUV1t+4XbNDiJbsAWCH5Z2uqlTqW6dD7Cf5nEASkeXrCI/Mz83sI2o527oBIFKVMXtRf1Vtg== dependencies: "@babel/code-frame" "7.10.4" address "1.1.2" @@ -14777,7 +14684,7 @@ react-dev-utils@^11.0.2: global-modules "2.0.0" globby "11.0.1" gzip-size "5.1.1" - immer "7.0.9" + immer "8.0.1" is-root "2.1.0" loader-utils "2.0.0" open "^7.0.2" @@ -14854,11 +14761,6 @@ react-element-to-jsx-string@^14.3.1: "@base2/pretty-print-object" "1.0.0" is-plain-object "3.0.0" -react-error-overlay@^6.0.7: - version "6.0.7" - resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.7.tgz#1dcfb459ab671d53f660a991513cb2f0a0553108" - integrity sha512-TAv1KJFh3RhqxNvhzxj6LeT5NWklP6rDr2a0jaTfsZ5wSZWHOGeqQyejUp3xxLfPt2UpyJEcVQB/zyPcmonNFA== - react-error-overlay@^6.0.9: version "6.0.9" resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a" @@ -14948,10 +14850,10 @@ react-router@6.0.0-beta.0: dependencies: prop-types "^15.7.2" -react-scripts@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-4.0.2.tgz#530fd934dfdf31c355e366df40bf488347c28de7" - integrity sha512-okaWNaGDGtnXyM2CLMUl8gYZnAubgxEulC40FYjsxn5bbj+G/mDINdy24wHz4Vypb/LWtIe8rdBU78k/74v8Mw== +react-scripts@4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-4.0.3.tgz#b1cafed7c3fa603e7628ba0f187787964cb5d345" + integrity sha512-S5eO4vjUzUisvkIPB7jVsKtuH2HhWcASREYWHAQ1FP5HyCv3xgn+wpILAEWkmy+A+tTNbSZClhxjT3qz6g4L1A== dependencies: "@babel/core" "7.12.3" "@pmmmwh/react-refresh-webpack-plugin" "0.4.3" @@ -14978,7 +14880,7 @@ react-scripts@4.0.2: eslint-plugin-react "^7.21.5" eslint-plugin-react-hooks "^4.2.0" eslint-plugin-testing-library "^3.9.2" - eslint-webpack-plugin "^2.1.0" + eslint-webpack-plugin "^2.5.2" file-loader "6.1.1" fs-extra "^9.0.1" html-webpack-plugin "4.5.0" @@ -14997,7 +14899,7 @@ react-scripts@4.0.2: postcss-safe-parser "5.0.2" prompts "2.4.0" react-app-polyfill "^2.0.0" - react-dev-utils "^11.0.2" + react-dev-utils "^11.0.3" react-refresh "^0.8.3" resolve "1.18.1" resolve-url-loader "^3.1.2" @@ -15008,7 +14910,7 @@ react-scripts@4.0.2: ts-pnp "1.2.0" url-loader "4.1.1" webpack "4.44.2" - webpack-dev-server "3.11.0" + webpack-dev-server "3.11.1" webpack-manifest-plugin "2.2.0" workbox-webpack-plugin "5.1.4" optionalDependencies: @@ -15059,6 +14961,14 @@ reactcss@^1.2.0: dependencies: lodash "^4.0.1" +read-chunk@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/read-chunk/-/read-chunk-3.2.0.tgz#2984afe78ca9bfbbdb74b19387bf9e86289c16ca" + integrity sha512-CEjy9LCzhmD7nUpJ1oVOE6s/hBkejlcJEgLQHVnQznOSilOPb+kpKktlLfFDK3/WP43+F80xkUTM2VOkYoSYvQ== + dependencies: + pify "^4.0.1" + with-open-file "^0.1.6" + read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" @@ -15464,7 +15374,7 @@ request-promise-core@1.1.4: dependencies: lodash "^4.17.19" -request-promise-native@^1.0.8: +request-promise-native@^1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== @@ -15733,14 +15643,7 @@ rsvp@^4.8.4: resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== -run-async@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= - dependencies: - is-promise "^2.1.0" - -run-async@^2.4.0: +run-async@^2.2.0, run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== @@ -15762,17 +15665,10 @@ rx@^4.1.0: resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" integrity sha1-pfE/957zt0D+MKqAP7CfmIBdR4I= -rxjs@^6.4.0: - version "6.6.3" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" - integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== - dependencies: - tslib "^1.9.0" - -rxjs@^6.5.3, rxjs@^6.6.0: - version "6.6.2" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.2.tgz#8096a7ac03f2cc4fe5860ef6e572810d9e01c0d2" - integrity sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg== +rxjs@^6.4.0, rxjs@^6.6.0, rxjs@^6.6.6: + version "6.6.6" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.6.tgz#14d8417aa5a07c5e633995b525e1e3c0dec03b70" + integrity sha512-/oTwee4N4iWzAMAL9xdGKjkEHmIwupR3oXbQjCKywF1BeFohswF3vZdogbmEF6pZkOsXTzWkrZszrWpQTByYVg== dependencies: tslib "^1.9.0" @@ -15841,10 +15737,10 @@ sass-loader@^10.0.5: schema-utils "^3.0.0" semver "^7.3.2" -sass@^1.32.7: - version "1.32.7" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.32.7.tgz#632a9df2b85dc4b346977fcaf2d5e6f2b7039fd8" - integrity sha512-C8Z4bjqGWnsYa11o8hpKAuoyFdRhrSHcYjCr+XAWVPSIQqC8mp2f5Dx4em0dKYehPzg5XSekmCjqJnEZbIls9A== +sass@^1.32.8: + version "1.32.8" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.32.8.tgz#f16a9abd8dc530add8834e506878a2808c037bdc" + integrity sha512-Sl6mIeGpzjIUZqvKnKETfMf0iDAswD9TNlv13A7aAF3XZlRPMq4VvJWBC2N2DXbp94MQVdNSFG6LfF/iOXrPHQ== dependencies: chokidar ">=2.0.0 <4.0.0" @@ -15853,7 +15749,7 @@ sax@~1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -saxes@^5.0.0: +saxes@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== @@ -15921,12 +15817,12 @@ select@^1.1.2: resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= -selfsigned@^1.10.7: - version "1.10.7" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.7.tgz#da5819fd049d5574f28e88a9bcc6dbc6e6f3906b" - integrity sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA== +selfsigned@^1.10.8: + version "1.10.8" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.8.tgz#0d17208b7d12c33f8eac85c41835f27fc3d81a30" + integrity sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w== dependencies: - node-forge "0.9.0" + node-forge "^0.10.0" semver-compare@^1.0.0: version "1.0.0" @@ -16191,11 +16087,6 @@ sisteransi@^1.0.5: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= - slash@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" @@ -16254,26 +16145,26 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -sockjs-client@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.4.0.tgz#c9f2568e19c8fd8173b4997ea3420e0bb306c7d5" - integrity sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g== +sockjs-client@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.0.tgz#2f8ff5d4b659e0d092f7aba0b7c386bd2aa20add" + integrity sha512-8Dt3BDi4FYNrCFGTL/HtwVzkARrENdwOUf1ZoW/9p3M8lZdFT35jVdrHza+qgxuG9H3/shR4cuX/X9umUrjP8Q== dependencies: - debug "^3.2.5" + debug "^3.2.6" eventsource "^1.0.7" - faye-websocket "~0.11.1" - inherits "^2.0.3" - json3 "^3.3.2" - url-parse "^1.4.3" + faye-websocket "^0.11.3" + inherits "^2.0.4" + json3 "^3.3.3" + url-parse "^1.4.7" -sockjs@0.3.20: - version "0.3.20" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.20.tgz#b26a283ec562ef8b2687b44033a4eeceac75d855" - integrity sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA== +sockjs@^0.3.21: + version "0.3.21" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417" + integrity sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw== dependencies: - faye-websocket "^0.10.0" + faye-websocket "^0.11.3" uuid "^3.4.0" - websocket-driver "0.6.5" + websocket-driver "^0.7.4" sort-keys-length@^1.0.0: version "1.0.1" @@ -16301,10 +16192,10 @@ sort-object-keys@^1.1.3: resolved "https://registry.yarnpkg.com/sort-object-keys/-/sort-object-keys-1.1.3.tgz#bff833fe85cab147b34742e45863453c1e190b45" integrity sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg== -sort-package-json@1.48.1: - version "1.48.1" - resolved "https://registry.yarnpkg.com/sort-package-json/-/sort-package-json-1.48.1.tgz#58629823da53a3ccccc049cb7e7300bc23072b33" - integrity sha512-YvDm1iBzhphfXtctTS0XIBlIW/2N1DZNHx3YMcZnptpZhchqH4zazUOuEWmjfNXndwamITMt9hFPliqwx1SHvQ== +sort-package-json@1.49.0: + version "1.49.0" + resolved "https://registry.yarnpkg.com/sort-package-json/-/sort-package-json-1.49.0.tgz#82845ab598501bb35875f326e4768a5ab5f15335" + integrity sha512-3YuqFGThwc9X0TZLYohOUJJ/P6uJIVcTeuJOc6ZWw4f1fHpTHIfVysKer4qXtrZ2zvwwU2aEcb555Bo+2fwIgQ== dependencies: detect-indent "^6.0.0" detect-newline "3.1.0" @@ -16612,10 +16503,10 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" + integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" @@ -16859,10 +16750,10 @@ stylelint-order@^4.0.0: postcss "^7.0.31" postcss-sorting "^5.0.1" -stylelint-prettier@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/stylelint-prettier/-/stylelint-prettier-1.1.2.tgz#2b19abe40789c380bffee3d4267c413d981a86ea" - integrity sha512-8QZ+EtBpMCXYB6cY0hNE3aCDKMySIx4Q8/malLaqgU/KXXa6Cj2KK8ulG1AJvUMD5XSSP8rOotqaCzR/BW6qAA== +stylelint-prettier@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/stylelint-prettier/-/stylelint-prettier-1.2.0.tgz#a133d75c794ba820ee47136fc4bf8c72ea185427" + integrity sha512-/MYz6W2CNgKHblPzPtk7cybu8H5dGG3c2GevL64RButERj1uJg4SdBIIat1hMfDOmN6QQpldc6tCc//ZAWh9WQ== dependencies: prettier-linter-helpers "^1.0.0" @@ -16877,10 +16768,10 @@ stylelint-scss@^3.18.0, stylelint-scss@^3.19.0: postcss-selector-parser "^6.0.2" postcss-value-parser "^4.1.0" -stylelint@^13.10.0: - version "13.10.0" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-13.10.0.tgz#67b0c6f378c3fa61aa569a55d38feb8570b0b587" - integrity sha512-eDuLrL0wzPKbl5/TbNGZcbw0lTIGbDEr5W6lCODvb1gAg0ncbgCRt7oU0C2VFDvbrcY0A3MFZOwltwTRmc0XCw== +stylelint@^13.12.0: + version "13.12.0" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-13.12.0.tgz#cceb922be0d0c7b7b6926271eea2b90cb924733e" + integrity sha512-P8O1xDy41B7O7iXaSlW+UuFbE5+ZWQDb61ndGDxKIt36fMH50DtlQTbwLpFLf8DikceTAb3r6nPrRv30wBlzXw== dependencies: "@stylelint/postcss-css-in-js" "^0.37.2" "@stylelint/postcss-markdown" "^0.36.2" @@ -16892,7 +16783,7 @@ stylelint@^13.10.0: execall "^2.0.0" fast-glob "^3.2.5" fastest-levenshtein "^1.0.12" - file-entry-cache "^6.0.0" + file-entry-cache "^6.0.1" get-stdin "^8.0.0" global-modules "^2.0.0" globby "^11.0.2" @@ -16902,7 +16793,7 @@ stylelint@^13.10.0: import-lazy "^4.0.0" imurmurhash "^0.1.4" known-css-properties "^0.21.0" - lodash "^4.17.20" + lodash "^4.17.21" log-symbols "^4.0.0" mathml-tag-names "^2.1.3" meow "^9.0.0" @@ -16922,7 +16813,7 @@ stylelint@^13.10.0: resolve-from "^5.0.0" slash "^3.0.0" specificity "^0.4.1" - string-width "^4.2.0" + string-width "^4.2.2" strip-ansi "^6.0.0" style-search "^0.1.0" sugarss "^2.0.0" @@ -16982,7 +16873,7 @@ svg-tags@^1.0.0: resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= -svgo@^1.0.0, svgo@^1.2.2, svgo@^1.3.2: +svgo@^1.0.0, svgo@^1.2.2: version "1.3.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== @@ -17001,6 +16892,20 @@ svgo@^1.0.0, svgo@^1.2.2, svgo@^1.3.2: unquote "~1.1.1" util.promisify "~1.0.0" +svgo@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.2.0.tgz#36bc3950507fd06e210493b8bc7722c1e14b1213" + integrity sha512-78w27VB+Vvca8TNRZrpbN70OTaVXgyQKm/rBiEqFPZmEJkn6i3PqEgIniPqPY6H2kFevakixAfBaQlwuStZuBA== + dependencies: + "@trysound/sax" "0.1.1" + chalk "^4.1.0" + commander "^7.1.0" + css-select "^3.1.2" + css-select-base-adapter "^0.1.1" + css-tree "^1.1.2" + csso "^4.2.0" + stable "^0.1.8" + swr@^0.4.2: version "0.4.2" resolved "https://registry.yarnpkg.com/swr/-/swr-0.4.2.tgz#4a9ed5e9948088af145c79d716d294cb99712a29" @@ -17382,14 +17287,14 @@ tough-cookie@^2.3.3, tough-cookie@~2.5.0: psl "^1.1.28" punycode "^2.1.1" -tough-cookie@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-3.0.1.tgz#9df4f57e739c26930a018184887f4adb7dca73b2" - integrity sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg== +tough-cookie@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" + integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== dependencies: - ip-regex "^2.1.0" - psl "^1.1.28" + psl "^1.1.33" punycode "^2.1.1" + universalify "^0.1.2" tr46@^2.0.2: version "2.0.2" @@ -17462,10 +17367,10 @@ ts-essentials@^2.0.3: resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-2.0.12.tgz#c9303f3d74f75fa7528c3d49b80e089ab09d8745" integrity sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w== -ts-loader@^8.0.17: - version "8.0.17" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.17.tgz#98f2ccff9130074f4079fd89b946b4c637b1f2fc" - integrity sha512-OeVfSshx6ot/TCxRwpBHQ/4lRzfgyTkvi7ghDVrLXOHzTbSK413ROgu/xNqM72i3AFeAIJgQy78FwSMKmOW68w== +ts-loader@^8.0.18: + version "8.0.18" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.18.tgz#b2385cbe81c34ad9f997915129cdde3ad92a61ea" + integrity sha512-hRZzkydPX30XkLaQwJTDcWDoxZHK6IrEMDQpNd7tgcakFruFkeUp/aY+9hBb7BUGb+ZWKI0jiOGMo0MckwzdDQ== dependencies: chalk "^4.1.0" enhanced-resolve "^4.0.0" @@ -17611,10 +17516,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.5.tgz#123a3b214aaff3be32926f0d8f1f6e704eb89a72" - integrity sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA== +typescript@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.3.tgz#39062d8019912d43726298f09493d598048c1ce3" + integrity sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw== unbzip2-stream@^1.0.9: version "1.4.3" @@ -17792,7 +17697,7 @@ unist-util-visit@2.0.3, unist-util-visit@^2.0.0: unist-util-is "^4.0.0" unist-util-visit-parents "^3.0.0" -universalify@^0.1.0: +universalify@^0.1.0, universalify@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== @@ -17897,6 +17802,14 @@ url-parse@^1.4.3: querystringify "^2.1.1" requires-port "^1.0.0" +url-parse@^1.4.7: + version "1.5.1" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.1.tgz#d5fa9890af8a5e1f274a2c98376510f6425f6e3b" + integrity sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + url-to-options@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" @@ -17917,10 +17830,10 @@ use-composed-ref@^1.0.0: dependencies: ts-essentials "^2.0.3" -use-debounce@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/use-debounce/-/use-debounce-5.2.0.tgz#3cb63f5c46f40092c570356e441dbc016ffb2f8b" - integrity sha512-lW4tbPsTnvPKYqOYXp5xZ7SP7No/ARLqqQqoyRKuSzP0HxR9arhSAhznXUZFoNPWDRij8fog+N6sYbjb8c3kzw== +use-debounce@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/use-debounce/-/use-debounce-5.2.1.tgz#7366543c769f1de3e92104dee64de5c4dfddfd33" + integrity sha512-BQG5uEypYHd/ASF6imzYR8tJHh5qGn28oZG/5iVAbljV6MUrfyT4jzxA8co+L+WLCT1U8VBwzzvlb3CHmUDpEA== use-isomorphic-layout-effect@^1.0.0: version "1.0.0" @@ -18195,10 +18108,10 @@ webpack-dev-middleware@^3.7.0, webpack-dev-middleware@^3.7.2: range-parser "^1.2.1" webpack-log "^2.0.0" -webpack-dev-server@3.11.0: - version "3.11.0" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz#8f154a3bce1bcfd1cc618ef4e703278855e7ff8c" - integrity sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg== +webpack-dev-server@3.11.1: + version "3.11.1" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.1.tgz#c74028bf5ba8885aaf230e48a20e8936ab8511f0" + integrity sha512-u4R3mRzZkbxQVa+MBWi2uVpB5W59H3ekZAJsQlKUTdl7Elcah2EhygTPLmeFXybQkf9i2+L0kn7ik9SnXa6ihQ== dependencies: ansi-html "0.0.7" bonjour "^3.5.0" @@ -18220,11 +18133,11 @@ webpack-dev-server@3.11.0: p-retry "^3.0.1" portfinder "^1.0.26" schema-utils "^1.0.0" - selfsigned "^1.10.7" + selfsigned "^1.10.8" semver "^6.3.0" serve-index "^1.9.1" - sockjs "0.3.20" - sockjs-client "1.4.0" + sockjs "^0.3.21" + sockjs-client "^1.5.0" spdy "^4.0.2" strip-ansi "^3.0.1" supports-color "^6.1.0" @@ -18334,14 +18247,7 @@ webpack@4.44.2, webpack@^4.44.2: watchpack "^1.7.4" webpack-sources "^1.4.1" -websocket-driver@0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.6.5.tgz#5cb2556ceb85f4373c6d8238aa691c8454e13a36" - integrity sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY= - dependencies: - websocket-extensions ">=0.1.1" - -websocket-driver@>=0.5.1: +websocket-driver@>=0.5.1, websocket-driver@^0.7.4: version "0.7.4" resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== @@ -18481,6 +18387,15 @@ winston@3.2.1: triple-beam "^1.3.0" winston-transport "^4.3.0" +with-open-file@^0.1.6: + version "0.1.7" + resolved "https://registry.yarnpkg.com/with-open-file/-/with-open-file-0.1.7.tgz#e2de8d974e8a8ae6e58886be4fe8e7465b58a729" + integrity sha512-ecJS2/oHtESJ1t3ZfMI3B7KIDKyfN0O16miWxdn30zdh66Yd3LsRFebXZXq6GU4xfxLf6nVxp9kIqElb5fqczA== + dependencies: + p-finally "^1.0.0" + p-try "^2.1.0" + pify "^4.0.1" + word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" @@ -18693,10 +18608,10 @@ ws@^6.1.0, ws@^6.2.1: dependencies: async-limiter "~1.0.0" -ws@^7.2.3: - version "7.4.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.2.tgz#782100048e54eb36fe9843363ab1c68672b261dd" - integrity sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA== +ws@^7.4.4: + version "7.4.4" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.4.tgz#383bc9742cb202292c9077ceab6f6047b17f2d59" + integrity sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw== xdg-basedir@^4.0.0: version "4.0.0"