diff --git a/.env.production b/.env.production index 0a6355edd..01fb7767d 100644 --- a/.env.production +++ b/.env.production @@ -1 +1 @@ -REACT_APP_INCLUDE_GTAG=true +REACT_APP_GOOGLE_ANALYTICS_ID=UA-387204-13 diff --git a/.github/assets/logo.png b/.github/assets/logo.png index 658bd4f79..d9b8953eb 100644 Binary files a/.github/assets/logo.png and b/.github/assets/logo.png differ diff --git a/.github/workflows/cancel.yml b/.github/workflows/cancel.yml new file mode 100644 index 000000000..19496c5bf --- /dev/null +++ b/.github/workflows/cancel.yml @@ -0,0 +1,12 @@ +name: Cancel +on: [push] +jobs: + cancel: + name: "Cancel Previous Runs" + runs-on: ubuntu-latest + timeout-minutes: 3 + steps: + - uses: styfle/cancel-workflow-action@0.6.0 + with: + workflow_id: 400555, 400556, 905313, 1451724, 1710116, 3185001, 3438604 + access_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/locales-coverage.yml b/.github/workflows/locales-coverage.yml index d391639e1..f43d93afc 100644 --- a/.github/workflows/locales-coverage.yml +++ b/.github/workflows/locales-coverage.yml @@ -43,5 +43,5 @@ jobs: uses: kt3k/update-pr-description@v1.0.1 with: pr_body: ${{ steps.getCommentBody.outputs.body }} - pr_title: "chore: New Crowdin updates" + pr_title: "chore: Update translations from Crowdin" github_token: ${{ secrets.PUSH_TRANSLATIONS_COVERAGE_PAT }} diff --git a/.github/workflows/semantic-pr-title.yml b/.github/workflows/semantic-pr-title.yml index 505c22dc1..be84d2294 100644 --- a/.github/workflows/semantic-pr-title.yml +++ b/.github/workflows/semantic-pr-title.yml @@ -11,6 +11,6 @@ jobs: main: runs-on: ubuntu-latest steps: - - uses: amannn/action-semantic-pull-request@v2.1.0 + - uses: amannn/action-semantic-pull-request@v3.0.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.prettierrc b/.prettierrc index bf357fbbc..32ad81f35 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,3 +1,4 @@ { + "proseWrap": "never", "trailingComma": "all" } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f85df1ad8..e3998dcc2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,8 +8,7 @@ 1. Run `npm install` to install dependencies 1. Create a branch for your PR with `git checkout -b your-branch-name` -> To keep `master` branch pointing to remote repository and make -> pull requests from branches on your fork. To do this, run: +> To keep `master` branch pointing to remote repository and make pull requests from branches on your fork. To do this, run: > > ```sh > git remote add upstream https://github.com/excalidraw/excalidraw.git @@ -25,3 +24,41 @@ 1. Tap on `Fork Sandbox` 1. Write your code 1. Commit and PR automatically + +## Pull Request Guidelines + +Don't worry if you get any of the below wrong, or if you don't know how. We'll gladly help out. + +### Title + +Make sure the title starts with a semantic prefix: + +- **feat**: A new feature +- **fix**: A bug fix +- **improvement**: An improvement to a current feature +- **docs**: Documentation only changes +- **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) +- **refactor**: A code change that neither fixes a bug nor adds a feature +- **perf**: A code change that improves performance +- **test**: Adding missing tests or correcting existing tests +- **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm) +- **ci**: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs) +- **chore**: Other changes that don't modify src or test files +- **revert**: Reverts a previous commit + +### Changelog + +Add a brief description of your pull request to the changelog located here: [`src/packages/excalidraw/CHANGELOG.md`](src/packages/excalidraw/CHANGELOG.md) + +Notes: + +- Make sure to prepend to the section corresponding with the semantic prefix you selected in the title +- Link to your pull request - this will require updating the CHANGELOG _after_ creating the pull request + +### Testing + +Once you submit your pull request it will automatically be tested. Be sure to check the results of the test and fix any issues that arise. + +It's also a good idea to consider if your change should include additional tests. This is highly recommended for new features or bug-fixes. For example, it's good practice to create a test for each bug you fix which ensures that we don't regress the code in the future. + +Finally - always manually test your changes using the convenient staging environment deployed for each pull request. As much as local development attempts to replicate production, there can still be subtle differences in behavior. For larger features consider testing your change in multiple browsers as well. diff --git a/Dockerfile b/Dockerfile index eb9da1721..27f3a7084 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,6 @@ WORKDIR /opt/node_app COPY package.json package-lock.json ./ RUN npm i --no-optional -ARG REACT_APP_INCLUDE_GTAG=false ARG NODE_ENV=production COPY . . diff --git a/README.md b/README.md index 7688c4eac..267db969c 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@
- Excalidraw logo: Sketch handrawn like diagrams. + Excalidraw logo: Sketch handrawn like diagrams. -

Virtual whiteboard for sketching hand-drawn like diagrams.

+

Virtual whiteboard for sketching hand-drawn like diagrams.
Collaborative and end to end encrypted.

Follow Excalidraw on Twitter @@ -10,9 +10,6 @@ - - -

@@ -20,13 +17,51 @@ Go to [excalidraw.com](https://excalidraw.com) to start sketching. -Read our [blog](https://blog.excalidraw.com) and follow the [guides](https://howto.excalidraw.com) to learn more about Excalidraw and how to use it effectively. +Read the latest news and updates on our [blog](https://blog.excalidraw.com). A good start is to see all the updates of [One Year of Excalidraw](https://blog.excalidraw.com/one-year-of-excalidraw/). + +## Documentation + +### Shortcuts + +You can almost do anything with shortcuts. Click on the help icon on the bottom right corner to see them all. + +### Curved lines and arrows + +Choose line or arrow and click click click instead of drag. + +### Charts + +You can easily create charts by copy pasting data from Excel or just plain comma separated text. + +### Translating + +To translate Excalidraw into other languages, please visit [our Crowdin page](https://crowdin.com/project/excalidraw). To add a new language, [open an issue](https://github.com/excalidraw/excalidraw/issues/new) so we can get things set up on our end first. + +Translations will be available on the app if they exceed a certain threshold of completion (currently 85%). + +### Create a collaboration session manually + +In order to create a session manually you just need to generate a link of this form: + +``` +https://excalidraw.com/#room=[0-9a-f]{20},[a-zA-Z0-9_-]{22} +``` + +#### Example + +``` +https://excalidraw.com/#room=91bd46ae3aa84dff9d20,pfLqgEoY1c2ioq8LmGwsFA +``` + +The first set of digits is the room. This is visible from the server that’s going to dispatch messages to everyone that knows this number. + +The second set of digits is the encryption key. The Excalidraw server doesn’t know about it. This is what all the participants use to encrypt/decrypt the messages. ## Shape libraries Find a growing list of libraries containing assets for your drawings at [libraries.excalidraw.com](https://libraries.excalidraw.com). -## Run the code +## Developement ### Code Sandbox @@ -63,7 +98,7 @@ You can use docker-compose to work on excalidraw locally if you don't want to se docker-compose up --build -d ``` -## Self hosting +### Self hosting We publish a Docker image with the Excalidraw client at [excalidraw/excalidraw](https://hub.docker.com/r/excalidraw/excalidraw). You can use it to self host your own client under your own domain, on Kubernetes, AWS ECS, etc. @@ -82,57 +117,11 @@ We are working towards providing a full-fledged solution for self hosting your o Pull requests are welcome. For major changes, please [open an issue](https://github.com/excalidraw/excalidraw/issues/new) first to discuss what you would like to change. -## Translating +## Notable used tools -To translate Excalidraw into other languages, please visit [our Crowdin page](https://crowdin.com/project/excalidraw). To add a new language, [open an issue](https://github.com/excalidraw/excalidraw/issues/new) so we can get things set up on our end first. - -Translations will be available on the app if they exceed a certain threshold of completion (currently 85%). - -## Excalidraw is built using these awesome tools - -- [React](https://reactjs.org) +- [Create React App](https://github.com/facebook/create-react-app) - [Rough.js](https://roughjs.com) - [TypeScript](https://www.typescriptlang.org) - [Vercel](https://vercel.com) And the main source of inspiration for starting the project is the awesome [Zwibbler](https://zwibbler.com/demo/) app. - -## Testimonials - - - - - - - - - -## Contributors - -### Code Contributors - -This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. - - -### Financial Contributors - -Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/excalidraw/contribute)] - -#### Individuals - - - -#### Organizations - -Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/excalidraw/contribute)] - - - - - - - - - - - diff --git a/package-lock.json b/package-lock.json index e306338ce..8ee2b6738 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1368,9 +1368,9 @@ } }, "@firebase/database": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.8.1.tgz", - "integrity": "sha512-/1HhR4ejpqUaM9Cn3KSeNdQvdlehWIhdfTVWFxS73ZlLYf7ayk9jITwH10H3ZOIm5yNzxF67p/U7Z/0IPhgWaQ==", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.8.2.tgz", + "integrity": "sha512-E86yrom0Ii+61UScG44y1q3H3NuozzGGTGbYmiyTe1qK8Qvzuiu7yyfdDnqFW2fkeKvTRLoDeCpgZy27FgEndQ==", "requires": { "@firebase/auth-interop-types": "0.1.5", "@firebase/component": "0.1.21", @@ -1405,9 +1405,9 @@ } }, "@firebase/firestore": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-2.1.1.tgz", - "integrity": "sha512-mcKp8psdKSxujaGjyfmt/thlTG5Gk+gFdJbkx4DnGO1PsJG4H5mE0wG//7tOH7DGeRCAmiagjKhA8nQlf/UNCg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-2.1.2.tgz", + "integrity": "sha512-8yUdBLLr6UhE+IjPR+fxLBD0bDnEqF9GalohfURZeLQPaL3b+LtqqGCLvvXC4MKT0lJAHOV8J9LA6rHj8vI0/Q==", "requires": { "@firebase/component": "0.1.21", "@firebase/firestore-types": "2.1.0", @@ -1672,9 +1672,9 @@ } }, "@grpc/grpc-js": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.2.2.tgz", - "integrity": "sha512-iK/T984Ni6VnmlQK/LJdUk+VsXSaYIWkgzJ0LyOcxN2SowAmoRjG28kS7B1ui/q/MAv42iM3051WBt5QorFxmg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.2.3.tgz", + "integrity": "sha512-hMjS4/TiGFtvMxjmM3mgXCw6VIGeI0EWTNzdcV6R+qqCh33dLDcK1wVceAABXKZ+Fia1nETU49RBesOiukQjGA==", "requires": { "@types/node": "^12.12.47", "google-auth-library": "^6.1.1", @@ -1682,9 +1682,9 @@ }, "dependencies": { "@types/node": { - "version": "12.19.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.9.tgz", - "integrity": "sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q==" + "version": "12.19.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.12.tgz", + "integrity": "sha512-UwfL2uIU9arX/+/PRcIkT08/iBadGN2z6ExOROA2Dh5mAuWTBj6iJbQX4nekiV5H8cTrEG569LeX+HRco9Cbxw==" } } }, @@ -2887,9 +2887,9 @@ } }, "@testing-library/dom": { - "version": "7.28.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.28.1.tgz", - "integrity": "sha512-acv3l6kDwZkQif/YqJjstT3ks5aaI33uxGNVIQmdKzbZ2eMKgg3EV2tB84GDdc72k3Kjhl6mO8yUt6StVIdRDg==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.29.2.tgz", + "integrity": "sha512-CBMELfyY1jKdtLcSRmEnZWRzRkCRVSNPTzhzrn8wY8OnzUo7Pe/W+HgLzt4TDnWIPYeusHBodf9wUjJF48kPmA==", "requires": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -2902,9 +2902,9 @@ }, "dependencies": { "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", "requires": { "@babel/highlight": "^7.10.4" } @@ -2939,18 +2939,6 @@ "regenerator-runtime": "^0.13.4" } }, - "@jest/types": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", - "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0" - } - }, "chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -2996,32 +2984,6 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, - "pretty-format": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", - "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", - "requires": { - "@jest/types": "^26.6.2", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^17.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - } - } - }, - "react-is": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.1.tgz", - "integrity": "sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA==" - }, "regenerator-runtime": { "version": "0.13.7", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", @@ -3144,9 +3106,9 @@ } }, "@testing-library/react": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.2.tgz", - "integrity": "sha512-jaxm0hwUjv+hzC+UFEywic7buDC9JQ1q3cDsrWVSDAPmLotfA6E6kUHlYm/zOeGCac6g48DR36tFHxl7Zb+N5A==", + "version": "11.2.3", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.3.tgz", + "integrity": "sha512-BirBUGPkTW28ULuCwIbYo0y2+0aavHczBT6N9r3LrsswEW3pg25l1wgoE7I8QBIy1upXWkwKpYdWY7NYYP0Bxw==", "requires": { "@babel/runtime": "^7.12.5", "@testing-library/dom": "^7.28.1" @@ -3167,6 +3129,12 @@ } } }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, "@types/anymatch": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", @@ -3287,9 +3255,9 @@ } }, "@types/jest": { - "version": "26.0.19", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.19.tgz", - "integrity": "sha512-jqHoirTG61fee6v6rwbnEuKhpSKih0tuhqeFbCmMmErhtu3BYlOZaXWjffgOstMM4S/3iQD31lI5bGLTrs97yQ==", + "version": "26.0.20", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.20.tgz", + "integrity": "sha512-9zi2Y+5USJRxd0FsahERhBwlcvFh6D2GLQnY2FH2BzK8J9s9omvNHIbvABwIluXa0fD8XVKMLTO0aOEuUfACAA==", "requires": { "jest-diff": "^26.0.0", "pretty-format": "^26.0.0" @@ -3330,14 +3298,6 @@ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" }, - "@types/nanoid": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/nanoid/-/nanoid-2.1.0.tgz", - "integrity": "sha512-xdkn/oRTA0GSNPLIKZgHWqDTWZsVrieKomxJBOQUK9YDD+zfSgmwD5t4WJYra5S7XyhTw7tfvwznW+pFexaepQ==", - "requires": { - "@types/node": "*" - } - }, "@types/node": { "version": "13.5.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-13.5.1.tgz", @@ -4292,6 +4252,23 @@ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" }, + "ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dev": true, + "requires": { + "tslib": "^2.0.1" + }, + "dependencies": { + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true + } + } + }, "ast-types-flow": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", @@ -6870,6 +6847,12 @@ "assert-plus": "^1.0.0" } }, + "data-uri-to-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", + "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", + "dev": true + }, "data-urls": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", @@ -7021,6 +7004,17 @@ } } }, + "degenerator": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-2.2.0.tgz", + "integrity": "sha512-aiQcQowF01RxFI4ZLFMpzyotbQonhNpBao6dkI8JPk5a+hmSjR5ErHp2CQySmQe8os3VBqLCIh87nDBgZXvsmg==", + "dev": true, + "requires": { + "ast-types": "^0.13.2", + "escodegen": "^1.8.1", + "esprima": "^4.0.0" + } + }, "del": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", @@ -8163,9 +8157,9 @@ } }, "eslint-plugin-prettier": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.0.tgz", - "integrity": "sha512-tMTwO8iUWlSRZIwS9k7/E4vrTsfvsrcM5p1eftyuqWH25nKsz/o6/54I7jwQ/3zobISyC7wMy9ZsFwgTxOcOpQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz", + "integrity": "sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ==", "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0" @@ -9009,25 +9003,25 @@ } }, "find-versions": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", - "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", + "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", "dev": true, "requires": { - "semver-regex": "^2.0.0" + "semver-regex": "^3.1.2" } }, "firebase": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/firebase/-/firebase-8.2.1.tgz", - "integrity": "sha512-u2dvRIbyHZ2g0dziHKwXvMBubTSf+fgJcijXyy7fXcFFPd3wbDaGlHz7Sc6saOnlJtzZAYmvZUXaIxnStKOOXg==", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-8.2.2.tgz", + "integrity": "sha512-a07aW2TTAA9S7p4mx5pu8hvtVokJEjAQlAocHKOWwmRJRIduE9Vvr/3i50FtujT5gGNr0Qm+EyWyB+/7TJiwnw==", "requires": { "@firebase/analytics": "0.6.2", "@firebase/app": "0.6.13", "@firebase/app-types": "0.6.1", "@firebase/auth": "0.16.1", - "@firebase/database": "0.8.1", - "@firebase/firestore": "2.1.1", + "@firebase/database": "0.8.2", + "@firebase/firestore": "2.1.2", "@firebase/functions": "0.6.1", "@firebase/installations": "0.4.19", "@firebase/messaging": "0.7.3", @@ -9039,9 +9033,9 @@ } }, "firebase-tools": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/firebase-tools/-/firebase-tools-9.1.0.tgz", - "integrity": "sha512-hTfxL2meJSl5WuwAS6bEJ5nay7tu3MNYb4ZL2KmPL7yLM3IeT+Qd2z1evHhW1VvbDXKR6RTwlBxzdWPs4l75kA==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/firebase-tools/-/firebase-tools-9.1.2.tgz", + "integrity": "sha512-YUiqMuQ+nbdCNpahSO0eyKxxVfT0nDdijkUEUplTGArkDwqdOKPIxVqHj1edq7GEPXTRWlk7zibnbOnCCHaedw==", "dev": true, "requires": { "@google-cloud/pubsub": "^2.7.0", @@ -9082,6 +9076,7 @@ "plist": "^3.0.1", "portfinder": "^1.0.23", "progress": "^2.0.3", + "proxy-agent": "^4.0.0", "request": "^2.87.0", "rimraf": "^3.0.0", "semver": "^5.7.1", @@ -9755,6 +9750,42 @@ "rimraf": "2" } }, + "ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "dev": true, + "requires": { + "readable-stream": "1.1.x", + "xregexp": "2.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -9892,6 +9923,54 @@ "pump": "^3.0.0" } }, + "get-uri": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-3.0.2.tgz", + "integrity": "sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "data-uri-to-buffer": "3", + "debug": "4", + "file-uri-to-path": "2", + "fs-extra": "^8.1.0", + "ftp": "^0.3.10" + }, + "dependencies": { + "file-uri-to-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz", + "integrity": "sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==", + "dev": true + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -10040,89 +10119,28 @@ } }, "google-gax": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.9.2.tgz", - "integrity": "sha512-Pve4osEzNKpBZqFXMfGKBbKCtgnHpUe5IQMh5Ou+Xtg8nLcba94L3gF0xgM5phMdGRRqJn0SMjcuEVmOYu7EBg==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.10.0.tgz", + "integrity": "sha512-K+1JK5ofNl5k30LsI8UQb/DeLMEbhL/SWirCx0L9pnMcApSfAjRAO7yajXT5X1vicxDBnNSwKs+cu4elxpYraw==", "dev": true, "requires": { - "@grpc/grpc-js": "~1.1.1", + "@grpc/grpc-js": "~1.2.0", "@grpc/proto-loader": "^0.5.1", "@types/long": "^4.0.0", "abort-controller": "^3.0.0", "duplexify": "^4.0.0", + "fast-text-encoding": "^1.0.3", "google-auth-library": "^6.1.3", "is-stream-ended": "^0.1.4", "node-fetch": "^2.6.1", - "protobufjs": "^6.9.0", + "protobufjs": "^6.10.2", "retry-request": "^4.0.0" }, "dependencies": { - "@grpc/grpc-js": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.1.8.tgz", - "integrity": "sha512-64hg5rmEm6F/NvlWERhHmmgxbWU8nD2TMWE+9TvG7/WcOrFT3fzg/Uu631pXRFwmJ4aWO/kp9vVSlr8FUjBDLA==", - "dev": true, - "requires": { - "@grpc/proto-loader": "^0.6.0-pre14", - "@types/node": "^12.12.47", - "google-auth-library": "^6.0.0", - "semver": "^6.2.0" - }, - "dependencies": { - "@grpc/proto-loader": { - "version": "0.6.0-pre9", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.0-pre9.tgz", - "integrity": "sha512-oM+LjpEjNzW5pNJjt4/hq1HYayNeQT+eGrOPABJnYHv7TyNPDNzkQ76rDYZF86X5swJOa4EujEMzQ9iiTdPgww==", - "dev": true, - "requires": { - "@types/long": "^4.0.1", - "lodash.camelcase": "^4.3.0", - "long": "^4.0.0", - "protobufjs": "^6.9.0", - "yargs": "^15.3.1" - } - } - } - }, "@types/node": { - "version": "12.19.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.11.tgz", - "integrity": "sha512-bwVfNTFZOrGXyiQ6t4B9sZerMSShWNsGRw8tC5DY1qImUNczS9SjT4G6PnzjCnxsu5Ubj6xjL2lgwddkxtQl5w==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "version": "13.13.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.39.tgz", + "integrity": "sha512-wct+WgRTTkBm2R3vbrFOqyZM5w0g+D8KnhstG9463CJBVC3UVZHMToge7iMBR1vDl/I+NWFHUeK9X+JcF0rWKw==", "dev": true }, "duplexify": { @@ -10137,87 +10155,25 @@ "stream-shift": "^1.0.0" } }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "protobufjs": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.10.2.tgz", + "integrity": "sha512-27yj+04uF6ya9l+qfpH187aqEzfCF4+Uit0I9ZBQVqK09hk/SQzKa2MUqUpXaVa7LOFRg1TSSr3lVxGOk6c0SQ==", "dev": true, "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": "^13.7.0", + "long": "^4.0.0" } } } @@ -10671,6 +10627,17 @@ "requires-port": "^1.0.0" } }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, "http-proxy-middleware": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", @@ -10809,18 +10776,18 @@ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==" }, "husky": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.6.tgz", - "integrity": "sha512-o6UjVI8xtlWRL5395iWq9LKDyp/9TE7XMOTvIpEVzW638UcGxTmV5cfel6fsk/jbZSTlvfGVJf2svFtybcIZag==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.7.tgz", + "integrity": "sha512-0fQlcCDq/xypoyYSJvEuzbDPHFf8ZF9IXKJxlrnvxABTSzK1VPT2RKYQKrcgJ+YD39swgoB6sbzywUqFxUiqjw==", "dev": true, "requires": { "chalk": "^4.0.0", "ci-info": "^2.0.0", "compare-versions": "^3.6.0", "cosmiconfig": "^7.0.0", - "find-versions": "^3.2.0", + "find-versions": "^4.0.0", "opencollective-postinstall": "^2.0.2", - "pkg-dir": "^4.2.0", + "pkg-dir": "^5.0.0", "please-upgrade-node": "^3.2.0", "slash": "^3.0.0", "which-pm-runs": "^1.0.0" @@ -10861,12 +10828,12 @@ "dev": true }, "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "requires": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, @@ -10877,21 +10844,30 @@ "dev": true }, "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" } }, "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "p-limit": "^3.0.2" } }, "path-exists": { @@ -10901,12 +10877,12 @@ "dev": true }, "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", "dev": true, "requires": { - "find-up": "^4.0.0" + "find-up": "^5.0.0" } }, "supports-color": { @@ -13689,9 +13665,9 @@ }, "dependencies": { "tslib": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", - "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", "dev": true } } @@ -14789,19 +14765,33 @@ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "memoizee": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", - "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", + "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", "dev": true, "requires": { - "d": "1", - "es5-ext": "^0.10.45", - "es6-weak-map": "^2.0.2", + "d": "^1.0.1", + "es5-ext": "^0.10.53", + "es6-weak-map": "^2.0.3", "event-emitter": "^0.3.5", - "is-promise": "^2.1", - "lru-queue": "0.1", - "next-tick": "1", - "timers-ext": "^0.1.5" + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + }, + "dependencies": { + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, + "next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true + } } }, "memory-fs": { @@ -15265,9 +15255,9 @@ "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" }, "nanoid": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", - "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==" + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==" }, "nanomatch": { "version": "1.2.13", @@ -15330,6 +15320,12 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, + "netmask": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", + "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", + "dev": true + }, "next-tick": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", @@ -15642,3100 +15638,6 @@ "sort-keys": "^1.0.0" } }, - "npm": { - "version": "6.14.9", - "resolved": "https://registry.npmjs.org/npm/-/npm-6.14.9.tgz", - "integrity": "sha512-yHi1+i9LyAZF1gAmgyYtVk+HdABlLy94PMIDoK1TRKWvmFQAt5z3bodqVwKvzY0s6dLqQPVsRLiwhJfNtiHeCg==", - "requires": { - "JSONStream": "^1.3.5", - "abbrev": "~1.1.1", - "ansicolors": "~0.3.2", - "ansistyles": "~0.1.3", - "aproba": "^2.0.0", - "archy": "~1.0.0", - "bin-links": "^1.1.8", - "bluebird": "^3.5.5", - "byte-size": "^5.0.1", - "cacache": "^12.0.3", - "call-limit": "^1.1.1", - "chownr": "^1.1.4", - "ci-info": "^2.0.0", - "cli-columns": "^3.1.2", - "cli-table3": "^0.5.1", - "cmd-shim": "^3.0.3", - "columnify": "~1.5.4", - "config-chain": "^1.1.12", - "debuglog": "*", - "detect-indent": "~5.0.0", - "detect-newline": "^2.1.0", - "dezalgo": "~1.0.3", - "editor": "~1.0.0", - "figgy-pudding": "^3.5.1", - "find-npm-prefix": "^1.0.2", - "fs-vacuum": "~1.2.10", - "fs-write-stream-atomic": "~1.0.10", - "gentle-fs": "^2.3.1", - "glob": "^7.1.6", - "graceful-fs": "^4.2.4", - "has-unicode": "~2.0.1", - "hosted-git-info": "^2.8.8", - "iferr": "^1.0.2", - "imurmurhash": "*", - "infer-owner": "^1.0.4", - "inflight": "~1.0.6", - "inherits": "^2.0.4", - "ini": "^1.3.5", - "init-package-json": "^1.10.3", - "is-cidr": "^3.0.0", - "json-parse-better-errors": "^1.0.2", - "lazy-property": "~1.0.0", - "libcipm": "^4.0.8", - "libnpm": "^3.0.1", - "libnpmaccess": "^3.0.2", - "libnpmhook": "^5.0.3", - "libnpmorg": "^1.0.1", - "libnpmsearch": "^2.0.2", - "libnpmteam": "^1.0.2", - "libnpx": "^10.2.4", - "lock-verify": "^2.1.0", - "lockfile": "^1.0.4", - "lodash._baseindexof": "*", - "lodash._baseuniq": "~4.6.0", - "lodash._bindcallback": "*", - "lodash._cacheindexof": "*", - "lodash._createcache": "*", - "lodash._getnative": "*", - "lodash.clonedeep": "~4.5.0", - "lodash.restparam": "*", - "lodash.union": "~4.6.0", - "lodash.uniq": "~4.5.0", - "lodash.without": "~4.4.0", - "lru-cache": "^5.1.1", - "meant": "^1.0.2", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.5", - "move-concurrently": "^1.0.1", - "node-gyp": "^5.1.0", - "nopt": "^4.0.3", - "normalize-package-data": "^2.5.0", - "npm-audit-report": "^1.3.3", - "npm-cache-filename": "~1.0.2", - "npm-install-checks": "^3.0.2", - "npm-lifecycle": "^3.1.5", - "npm-package-arg": "^6.1.1", - "npm-packlist": "^1.4.8", - "npm-pick-manifest": "^3.0.2", - "npm-profile": "^4.0.4", - "npm-registry-fetch": "^4.0.7", - "npm-user-validate": "^1.0.1", - "npmlog": "~4.1.2", - "once": "~1.4.0", - "opener": "^1.5.1", - "osenv": "^0.1.5", - "pacote": "^9.5.12", - "path-is-inside": "~1.0.2", - "promise-inflight": "~1.0.1", - "qrcode-terminal": "^0.12.0", - "query-string": "^6.8.2", - "qw": "~1.0.1", - "read": "~1.0.7", - "read-cmd-shim": "^1.0.5", - "read-installed": "~4.0.3", - "read-package-json": "^2.1.1", - "read-package-tree": "^5.3.1", - "readable-stream": "^3.6.0", - "readdir-scoped-modules": "^1.1.0", - "request": "^2.88.0", - "retry": "^0.12.0", - "rimraf": "^2.7.1", - "safe-buffer": "^5.1.2", - "semver": "^5.7.1", - "sha": "^3.0.0", - "slide": "~1.1.6", - "sorted-object": "~2.0.1", - "sorted-union-stream": "~2.1.3", - "ssri": "^6.0.1", - "stringify-package": "^1.0.1", - "tar": "^4.4.13", - "text-table": "~0.2.0", - "tiny-relative-date": "^1.3.0", - "uid-number": "0.0.6", - "umask": "~1.1.0", - "unique-filename": "^1.1.1", - "unpipe": "~1.0.0", - "update-notifier": "^2.5.0", - "uuid": "^3.3.3", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "~3.0.0", - "which": "^1.3.1", - "worker-farm": "^1.7.0", - "write-file-atomic": "^2.4.3" - }, - "dependencies": { - "JSONStream": { - "version": "1.3.5", - "bundled": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "abbrev": { - "version": "1.1.1", - "bundled": true - }, - "agent-base": { - "version": "4.3.0", - "bundled": true, - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "agentkeepalive": { - "version": "3.5.2", - "bundled": true, - "requires": { - "humanize-ms": "^1.2.1" - } - }, - "ansi-align": { - "version": "2.0.0", - "bundled": true, - "requires": { - "string-width": "^2.0.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true - }, - "ansi-styles": { - "version": "3.2.1", - "bundled": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "ansicolors": { - "version": "0.3.2", - "bundled": true - }, - "ansistyles": { - "version": "0.1.3", - "bundled": true - }, - "aproba": { - "version": "2.0.0", - "bundled": true - }, - "archy": { - "version": "1.0.0", - "bundled": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "asap": { - "version": "2.0.6", - "bundled": true - }, - "asn1": { - "version": "0.2.4", - "bundled": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "bundled": true - }, - "asynckit": { - "version": "0.4.0", - "bundled": true - }, - "aws-sign2": { - "version": "0.7.0", - "bundled": true - }, - "aws4": { - "version": "1.8.0", - "bundled": true - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "bundled": true, - "optional": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "bin-links": { - "version": "1.1.8", - "bundled": true, - "requires": { - "bluebird": "^3.5.3", - "cmd-shim": "^3.0.0", - "gentle-fs": "^2.3.0", - "graceful-fs": "^4.1.15", - "npm-normalize-package-bin": "^1.0.0", - "write-file-atomic": "^2.3.0" - } - }, - "bluebird": { - "version": "3.5.5", - "bundled": true - }, - "boxen": { - "version": "1.3.0", - "bundled": true, - "requires": { - "ansi-align": "^2.0.0", - "camelcase": "^4.0.0", - "chalk": "^2.0.1", - "cli-boxes": "^1.0.0", - "string-width": "^2.0.0", - "term-size": "^1.2.0", - "widest-line": "^2.0.0" - } - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "buffer-from": { - "version": "1.0.0", - "bundled": true - }, - "builtins": { - "version": "1.0.3", - "bundled": true - }, - "byline": { - "version": "5.0.0", - "bundled": true - }, - "byte-size": { - "version": "5.0.1", - "bundled": true - }, - "cacache": { - "version": "12.0.3", - "bundled": true, - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - } - }, - "call-limit": { - "version": "1.1.1", - "bundled": true - }, - "camelcase": { - "version": "4.1.0", - "bundled": true - }, - "capture-stack-trace": { - "version": "1.0.0", - "bundled": true - }, - "caseless": { - "version": "0.12.0", - "bundled": true - }, - "chalk": { - "version": "2.4.1", - "bundled": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chownr": { - "version": "1.1.4", - "bundled": true - }, - "ci-info": { - "version": "2.0.0", - "bundled": true - }, - "cidr-regex": { - "version": "2.0.10", - "bundled": true, - "requires": { - "ip-regex": "^2.1.0" - } - }, - "cli-boxes": { - "version": "1.0.0", - "bundled": true - }, - "cli-columns": { - "version": "3.1.2", - "bundled": true, - "requires": { - "string-width": "^2.0.0", - "strip-ansi": "^3.0.1" - } - }, - "cli-table3": { - "version": "0.5.1", - "bundled": true, - "requires": { - "colors": "^1.1.2", - "object-assign": "^4.1.0", - "string-width": "^2.1.1" - } - }, - "cliui": { - "version": "5.0.0", - "bundled": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true - }, - "string-width": { - "version": "3.1.0", - "bundled": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "bundled": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "clone": { - "version": "1.0.4", - "bundled": true - }, - "cmd-shim": { - "version": "3.0.3", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "mkdirp": "~0.5.0" - } - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "color-convert": { - "version": "1.9.1", - "bundled": true, - "requires": { - "color-name": "^1.1.1" - } - }, - "color-name": { - "version": "1.1.3", - "bundled": true - }, - "colors": { - "version": "1.3.3", - "bundled": true, - "optional": true - }, - "columnify": { - "version": "1.5.4", - "bundled": true, - "requires": { - "strip-ansi": "^3.0.0", - "wcwidth": "^1.0.0" - } - }, - "combined-stream": { - "version": "1.0.6", - "bundled": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - }, - "concat-stream": { - "version": "1.6.2", - "bundled": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "config-chain": { - "version": "1.1.12", - "bundled": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "configstore": { - "version": "3.1.5", - "bundled": true, - "requires": { - "dot-prop": "^4.2.1", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true - }, - "copy-concurrently": { - "version": "1.0.5", - "bundled": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - }, - "dependencies": { - "aproba": { - "version": "1.2.0", - "bundled": true - }, - "iferr": { - "version": "0.1.5", - "bundled": true - } - } - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "create-error-class": { - "version": "3.0.2", - "bundled": true, - "requires": { - "capture-stack-trace": "^1.0.0" - } - }, - "cross-spawn": { - "version": "5.1.0", - "bundled": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "lru-cache": { - "version": "4.1.5", - "bundled": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "yallist": { - "version": "2.1.2", - "bundled": true - } - } - }, - "crypto-random-string": { - "version": "1.0.0", - "bundled": true - }, - "cyclist": { - "version": "0.2.2", - "bundled": true - }, - "dashdash": { - "version": "1.14.1", - "bundled": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "debug": { - "version": "3.1.0", - "bundled": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "bundled": true - } - } - }, - "debuglog": { - "version": "1.0.1", - "bundled": true - }, - "decamelize": { - "version": "1.2.0", - "bundled": true - }, - "decode-uri-component": { - "version": "0.2.0", - "bundled": true - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true - }, - "defaults": { - "version": "1.0.3", - "bundled": true, - "requires": { - "clone": "^1.0.2" - } - }, - "define-properties": { - "version": "1.1.3", - "bundled": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "delayed-stream": { - "version": "1.0.0", - "bundled": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true - }, - "detect-indent": { - "version": "5.0.0", - "bundled": true - }, - "detect-newline": { - "version": "2.1.0", - "bundled": true - }, - "dezalgo": { - "version": "1.0.3", - "bundled": true, - "requires": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "dot-prop": { - "version": "4.2.1", - "bundled": true, - "requires": { - "is-obj": "^1.0.0" - } - }, - "dotenv": { - "version": "5.0.1", - "bundled": true - }, - "duplexer3": { - "version": "0.1.4", - "bundled": true - }, - "duplexify": { - "version": "3.6.0", - "bundled": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "bundled": true, - "optional": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "editor": { - "version": "1.0.0", - "bundled": true - }, - "emoji-regex": { - "version": "7.0.3", - "bundled": true - }, - "encoding": { - "version": "0.1.12", - "bundled": true, - "requires": { - "iconv-lite": "~0.4.13" - } - }, - "end-of-stream": { - "version": "1.4.1", - "bundled": true, - "requires": { - "once": "^1.4.0" - } - }, - "env-paths": { - "version": "2.2.0", - "bundled": true - }, - "err-code": { - "version": "1.1.2", - "bundled": true - }, - "errno": { - "version": "0.1.7", - "bundled": true, - "requires": { - "prr": "~1.0.1" - } - }, - "es-abstract": { - "version": "1.12.0", - "bundled": true, - "requires": { - "es-to-primitive": "^1.1.1", - "function-bind": "^1.1.1", - "has": "^1.0.1", - "is-callable": "^1.1.3", - "is-regex": "^1.0.4" - } - }, - "es-to-primitive": { - "version": "1.2.0", - "bundled": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es6-promise": { - "version": "4.2.8", - "bundled": true - }, - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "^4.0.3" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "bundled": true - }, - "execa": { - "version": "0.7.0", - "bundled": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "dependencies": { - "get-stream": { - "version": "3.0.0", - "bundled": true - } - } - }, - "extend": { - "version": "3.0.2", - "bundled": true - }, - "extsprintf": { - "version": "1.3.0", - "bundled": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "bundled": true - }, - "figgy-pudding": { - "version": "3.5.1", - "bundled": true - }, - "find-npm-prefix": { - "version": "1.0.2", - "bundled": true - }, - "flush-write-stream": { - "version": "1.0.3", - "bundled": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.4" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "forever-agent": { - "version": "0.6.1", - "bundled": true - }, - "form-data": { - "version": "2.3.2", - "bundled": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "1.0.6", - "mime-types": "^2.1.12" - } - }, - "from2": { - "version": "2.3.0", - "bundled": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "fs-minipass": { - "version": "1.2.7", - "bundled": true, - "requires": { - "minipass": "^2.6.0" - }, - "dependencies": { - "minipass": { - "version": "2.9.0", - "bundled": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - } - } - }, - "fs-vacuum": { - "version": "1.2.10", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "path-is-inside": "^1.0.1", - "rimraf": "^2.5.2" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - }, - "dependencies": { - "iferr": { - "version": "0.1.5", - "bundled": true - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true - }, - "function-bind": { - "version": "1.1.1", - "bundled": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - }, - "dependencies": { - "aproba": { - "version": "1.2.0", - "bundled": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "genfun": { - "version": "5.0.0", - "bundled": true - }, - "gentle-fs": { - "version": "2.3.1", - "bundled": true, - "requires": { - "aproba": "^1.1.2", - "chownr": "^1.1.2", - "cmd-shim": "^3.0.3", - "fs-vacuum": "^1.2.10", - "graceful-fs": "^4.1.11", - "iferr": "^0.1.5", - "infer-owner": "^1.0.4", - "mkdirp": "^0.5.1", - "path-is-inside": "^1.0.2", - "read-cmd-shim": "^1.0.1", - "slide": "^1.1.6" - }, - "dependencies": { - "aproba": { - "version": "1.2.0", - "bundled": true - }, - "iferr": { - "version": "0.1.5", - "bundled": true - } - } - }, - "get-caller-file": { - "version": "2.0.5", - "bundled": true - }, - "get-stream": { - "version": "4.1.0", - "bundled": true, - "requires": { - "pump": "^3.0.0" - } - }, - "getpass": { - "version": "0.1.7", - "bundled": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.1.6", - "bundled": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "global-dirs": { - "version": "0.1.1", - "bundled": true, - "requires": { - "ini": "^1.3.4" - } - }, - "got": { - "version": "6.7.1", - "bundled": true, - "requires": { - "create-error-class": "^3.0.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "unzip-response": "^2.0.1", - "url-parse-lax": "^1.0.0" - }, - "dependencies": { - "get-stream": { - "version": "3.0.0", - "bundled": true - } - } - }, - "graceful-fs": { - "version": "4.2.4", - "bundled": true - }, - "har-schema": { - "version": "2.0.0", - "bundled": true - }, - "har-validator": { - "version": "5.1.5", - "bundled": true, - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "bundled": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "bundled": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "bundled": true - } - } - }, - "has": { - "version": "1.0.3", - "bundled": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "bundled": true - }, - "has-symbols": { - "version": "1.0.0", - "bundled": true - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true - }, - "hosted-git-info": { - "version": "2.8.8", - "bundled": true - }, - "http-cache-semantics": { - "version": "3.8.1", - "bundled": true - }, - "http-proxy-agent": { - "version": "2.1.0", - "bundled": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - } - }, - "http-signature": { - "version": "1.2.0", - "bundled": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "https-proxy-agent": { - "version": "2.2.4", - "bundled": true, - "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - } - }, - "humanize-ms": { - "version": "1.2.1", - "bundled": true, - "requires": { - "ms": "^2.0.0" - } - }, - "iconv-lite": { - "version": "0.4.23", - "bundled": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "iferr": { - "version": "1.0.2", - "bundled": true - }, - "ignore-walk": { - "version": "3.0.3", - "bundled": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "import-lazy": { - "version": "2.1.0", - "bundled": true - }, - "imurmurhash": { - "version": "0.1.4", - "bundled": true - }, - "infer-owner": { - "version": "1.0.4", - "bundled": true - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "bundled": true - }, - "ini": { - "version": "1.3.5", - "bundled": true - }, - "init-package-json": { - "version": "1.10.3", - "bundled": true, - "requires": { - "glob": "^7.1.1", - "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0", - "promzard": "^0.3.0", - "read": "~1.0.1", - "read-package-json": "1 || 2", - "semver": "2.x || 3.x || 4 || 5", - "validate-npm-package-license": "^3.0.1", - "validate-npm-package-name": "^3.0.0" - } - }, - "ip": { - "version": "1.1.5", - "bundled": true - }, - "ip-regex": { - "version": "2.1.0", - "bundled": true - }, - "is-callable": { - "version": "1.1.4", - "bundled": true - }, - "is-ci": { - "version": "1.2.1", - "bundled": true, - "requires": { - "ci-info": "^1.5.0" - }, - "dependencies": { - "ci-info": { - "version": "1.6.0", - "bundled": true - } - } - }, - "is-cidr": { - "version": "3.0.0", - "bundled": true, - "requires": { - "cidr-regex": "^2.0.10" - } - }, - "is-date-object": { - "version": "1.0.1", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-installed-globally": { - "version": "0.1.0", - "bundled": true, - "requires": { - "global-dirs": "^0.1.0", - "is-path-inside": "^1.0.0" - } - }, - "is-npm": { - "version": "1.0.0", - "bundled": true - }, - "is-obj": { - "version": "1.0.1", - "bundled": true - }, - "is-path-inside": { - "version": "1.0.1", - "bundled": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, - "is-redirect": { - "version": "1.0.0", - "bundled": true - }, - "is-regex": { - "version": "1.0.4", - "bundled": true, - "requires": { - "has": "^1.0.1" - } - }, - "is-retry-allowed": { - "version": "1.2.0", - "bundled": true - }, - "is-stream": { - "version": "1.1.0", - "bundled": true - }, - "is-symbol": { - "version": "1.0.2", - "bundled": true, - "requires": { - "has-symbols": "^1.0.0" - } - }, - "is-typedarray": { - "version": "1.0.0", - "bundled": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true - }, - "isexe": { - "version": "2.0.0", - "bundled": true - }, - "isstream": { - "version": "0.1.2", - "bundled": true - }, - "jsbn": { - "version": "0.1.1", - "bundled": true, - "optional": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "bundled": true - }, - "json-schema": { - "version": "0.2.3", - "bundled": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "bundled": true - }, - "jsonparse": { - "version": "1.3.1", - "bundled": true - }, - "jsprim": { - "version": "1.4.1", - "bundled": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "latest-version": { - "version": "3.1.0", - "bundled": true, - "requires": { - "package-json": "^4.0.0" - } - }, - "lazy-property": { - "version": "1.0.0", - "bundled": true - }, - "libcipm": { - "version": "4.0.8", - "bundled": true, - "requires": { - "bin-links": "^1.1.2", - "bluebird": "^3.5.1", - "figgy-pudding": "^3.5.1", - "find-npm-prefix": "^1.0.2", - "graceful-fs": "^4.1.11", - "ini": "^1.3.5", - "lock-verify": "^2.1.0", - "mkdirp": "^0.5.1", - "npm-lifecycle": "^3.0.0", - "npm-logical-tree": "^1.2.1", - "npm-package-arg": "^6.1.0", - "pacote": "^9.1.0", - "read-package-json": "^2.0.13", - "rimraf": "^2.6.2", - "worker-farm": "^1.6.0" - } - }, - "libnpm": { - "version": "3.0.1", - "bundled": true, - "requires": { - "bin-links": "^1.1.2", - "bluebird": "^3.5.3", - "find-npm-prefix": "^1.0.2", - "libnpmaccess": "^3.0.2", - "libnpmconfig": "^1.2.1", - "libnpmhook": "^5.0.3", - "libnpmorg": "^1.0.1", - "libnpmpublish": "^1.1.2", - "libnpmsearch": "^2.0.2", - "libnpmteam": "^1.0.2", - "lock-verify": "^2.0.2", - "npm-lifecycle": "^3.0.0", - "npm-logical-tree": "^1.2.1", - "npm-package-arg": "^6.1.0", - "npm-profile": "^4.0.2", - "npm-registry-fetch": "^4.0.0", - "npmlog": "^4.1.2", - "pacote": "^9.5.3", - "read-package-json": "^2.0.13", - "stringify-package": "^1.0.0" - } - }, - "libnpmaccess": { - "version": "3.0.2", - "bundled": true, - "requires": { - "aproba": "^2.0.0", - "get-stream": "^4.0.0", - "npm-package-arg": "^6.1.0", - "npm-registry-fetch": "^4.0.0" - } - }, - "libnpmconfig": { - "version": "1.2.1", - "bundled": true, - "requires": { - "figgy-pudding": "^3.5.1", - "find-up": "^3.0.0", - "ini": "^1.3.5" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "bundled": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "bundled": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.2.0", - "bundled": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "bundled": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "bundled": true - } - } - }, - "libnpmhook": { - "version": "5.0.3", - "bundled": true, - "requires": { - "aproba": "^2.0.0", - "figgy-pudding": "^3.4.1", - "get-stream": "^4.0.0", - "npm-registry-fetch": "^4.0.0" - } - }, - "libnpmorg": { - "version": "1.0.1", - "bundled": true, - "requires": { - "aproba": "^2.0.0", - "figgy-pudding": "^3.4.1", - "get-stream": "^4.0.0", - "npm-registry-fetch": "^4.0.0" - } - }, - "libnpmpublish": { - "version": "1.1.2", - "bundled": true, - "requires": { - "aproba": "^2.0.0", - "figgy-pudding": "^3.5.1", - "get-stream": "^4.0.0", - "lodash.clonedeep": "^4.5.0", - "normalize-package-data": "^2.4.0", - "npm-package-arg": "^6.1.0", - "npm-registry-fetch": "^4.0.0", - "semver": "^5.5.1", - "ssri": "^6.0.1" - } - }, - "libnpmsearch": { - "version": "2.0.2", - "bundled": true, - "requires": { - "figgy-pudding": "^3.5.1", - "get-stream": "^4.0.0", - "npm-registry-fetch": "^4.0.0" - } - }, - "libnpmteam": { - "version": "1.0.2", - "bundled": true, - "requires": { - "aproba": "^2.0.0", - "figgy-pudding": "^3.4.1", - "get-stream": "^4.0.0", - "npm-registry-fetch": "^4.0.0" - } - }, - "libnpx": { - "version": "10.2.4", - "bundled": true, - "requires": { - "dotenv": "^5.0.1", - "npm-package-arg": "^6.0.0", - "rimraf": "^2.6.2", - "safe-buffer": "^5.1.0", - "update-notifier": "^2.3.0", - "which": "^1.3.0", - "y18n": "^4.0.0", - "yargs": "^14.2.3" - } - }, - "lock-verify": { - "version": "2.1.0", - "bundled": true, - "requires": { - "npm-package-arg": "^6.1.0", - "semver": "^5.4.1" - } - }, - "lockfile": { - "version": "1.0.4", - "bundled": true, - "requires": { - "signal-exit": "^3.0.2" - } - }, - "lodash._baseindexof": { - "version": "3.1.0", - "bundled": true - }, - "lodash._baseuniq": { - "version": "4.6.0", - "bundled": true, - "requires": { - "lodash._createset": "~4.0.0", - "lodash._root": "~3.0.0" - } - }, - "lodash._bindcallback": { - "version": "3.0.1", - "bundled": true - }, - "lodash._cacheindexof": { - "version": "3.0.2", - "bundled": true - }, - "lodash._createcache": { - "version": "3.1.2", - "bundled": true, - "requires": { - "lodash._getnative": "^3.0.0" - } - }, - "lodash._createset": { - "version": "4.0.3", - "bundled": true - }, - "lodash._getnative": { - "version": "3.9.1", - "bundled": true - }, - "lodash._root": { - "version": "3.0.1", - "bundled": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "bundled": true - }, - "lodash.restparam": { - "version": "3.6.1", - "bundled": true - }, - "lodash.union": { - "version": "4.6.0", - "bundled": true - }, - "lodash.uniq": { - "version": "4.5.0", - "bundled": true - }, - "lodash.without": { - "version": "4.4.0", - "bundled": true - }, - "lowercase-keys": { - "version": "1.0.1", - "bundled": true - }, - "lru-cache": { - "version": "5.1.1", - "bundled": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "make-dir": { - "version": "1.3.0", - "bundled": true, - "requires": { - "pify": "^3.0.0" - } - }, - "make-fetch-happen": { - "version": "5.0.2", - "bundled": true, - "requires": { - "agentkeepalive": "^3.4.1", - "cacache": "^12.0.0", - "http-cache-semantics": "^3.8.1", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "node-fetch-npm": "^2.0.2", - "promise-retry": "^1.1.1", - "socks-proxy-agent": "^4.0.0", - "ssri": "^6.0.0" - } - }, - "meant": { - "version": "1.0.2", - "bundled": true - }, - "mime-db": { - "version": "1.35.0", - "bundled": true - }, - "mime-types": { - "version": "2.1.19", - "bundled": true, - "requires": { - "mime-db": "~1.35.0" - } - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "bundled": true - }, - "minizlib": { - "version": "1.3.3", - "bundled": true, - "requires": { - "minipass": "^2.9.0" - }, - "dependencies": { - "minipass": { - "version": "2.9.0", - "bundled": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - } - } - }, - "mississippi": { - "version": "3.0.0", - "bundled": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, - "mkdirp": { - "version": "0.5.5", - "bundled": true, - "requires": { - "minimist": "^1.2.5" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "bundled": true - } - } - }, - "move-concurrently": { - "version": "1.0.1", - "bundled": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - }, - "dependencies": { - "aproba": { - "version": "1.2.0", - "bundled": true - } - } - }, - "ms": { - "version": "2.1.1", - "bundled": true - }, - "mute-stream": { - "version": "0.0.7", - "bundled": true - }, - "node-fetch-npm": { - "version": "2.0.2", - "bundled": true, - "requires": { - "encoding": "^0.1.11", - "json-parse-better-errors": "^1.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node-gyp": { - "version": "5.1.0", - "bundled": true, - "requires": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.2", - "mkdirp": "^0.5.1", - "nopt": "^4.0.1", - "npmlog": "^4.1.2", - "request": "^2.88.0", - "rimraf": "^2.6.3", - "semver": "^5.7.1", - "tar": "^4.4.12", - "which": "^1.3.1" - } - }, - "nopt": { - "version": "4.0.3", - "bundled": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "bundled": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "resolve": { - "version": "1.10.0", - "bundled": true, - "requires": { - "path-parse": "^1.0.6" - } - } - } - }, - "npm-audit-report": { - "version": "1.3.3", - "bundled": true, - "requires": { - "cli-table3": "^0.5.0", - "console-control-strings": "^1.1.0" - } - }, - "npm-bundled": { - "version": "1.1.1", - "bundled": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-cache-filename": { - "version": "1.0.2", - "bundled": true - }, - "npm-install-checks": { - "version": "3.0.2", - "bundled": true, - "requires": { - "semver": "^2.3.0 || 3.x || 4 || 5" - } - }, - "npm-lifecycle": { - "version": "3.1.5", - "bundled": true, - "requires": { - "byline": "^5.0.0", - "graceful-fs": "^4.1.15", - "node-gyp": "^5.0.2", - "resolve-from": "^4.0.0", - "slide": "^1.1.6", - "uid-number": "0.0.6", - "umask": "^1.1.0", - "which": "^1.3.1" - } - }, - "npm-logical-tree": { - "version": "1.2.1", - "bundled": true - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "bundled": true - }, - "npm-package-arg": { - "version": "6.1.1", - "bundled": true, - "requires": { - "hosted-git-info": "^2.7.1", - "osenv": "^0.1.5", - "semver": "^5.6.0", - "validate-npm-package-name": "^3.0.0" - } - }, - "npm-packlist": { - "version": "1.4.8", - "bundled": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-pick-manifest": { - "version": "3.0.2", - "bundled": true, - "requires": { - "figgy-pudding": "^3.5.1", - "npm-package-arg": "^6.0.0", - "semver": "^5.4.1" - } - }, - "npm-profile": { - "version": "4.0.4", - "bundled": true, - "requires": { - "aproba": "^1.1.2 || 2", - "figgy-pudding": "^3.4.1", - "npm-registry-fetch": "^4.0.0" - } - }, - "npm-registry-fetch": { - "version": "4.0.7", - "bundled": true, - "requires": { - "JSONStream": "^1.3.4", - "bluebird": "^3.5.1", - "figgy-pudding": "^3.4.1", - "lru-cache": "^5.1.1", - "make-fetch-happen": "^5.0.0", - "npm-package-arg": "^6.1.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "bundled": true - } - } - }, - "npm-run-path": { - "version": "2.0.2", - "bundled": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "npm-user-validate": { - "version": "1.0.1", - "bundled": true - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true - }, - "oauth-sign": { - "version": "0.9.0", - "bundled": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true - }, - "object-keys": { - "version": "1.0.12", - "bundled": true - }, - "object.getownpropertydescriptors": { - "version": "2.0.3", - "bundled": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" - } - }, - "once": { - "version": "1.4.0", - "bundled": true, - "requires": { - "wrappy": "1" - } - }, - "opener": { - "version": "1.5.1", - "bundled": true - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "p-finally": { - "version": "1.0.0", - "bundled": true - }, - "package-json": { - "version": "4.0.1", - "bundled": true, - "requires": { - "got": "^6.7.1", - "registry-auth-token": "^3.0.1", - "registry-url": "^3.0.3", - "semver": "^5.1.0" - } - }, - "pacote": { - "version": "9.5.12", - "bundled": true, - "requires": { - "bluebird": "^3.5.3", - "cacache": "^12.0.2", - "chownr": "^1.1.2", - "figgy-pudding": "^3.5.1", - "get-stream": "^4.1.0", - "glob": "^7.1.3", - "infer-owner": "^1.0.4", - "lru-cache": "^5.1.1", - "make-fetch-happen": "^5.0.0", - "minimatch": "^3.0.4", - "minipass": "^2.3.5", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "normalize-package-data": "^2.4.0", - "npm-normalize-package-bin": "^1.0.0", - "npm-package-arg": "^6.1.0", - "npm-packlist": "^1.1.12", - "npm-pick-manifest": "^3.0.0", - "npm-registry-fetch": "^4.0.0", - "osenv": "^0.1.5", - "promise-inflight": "^1.0.1", - "promise-retry": "^1.1.1", - "protoduck": "^5.0.1", - "rimraf": "^2.6.2", - "safe-buffer": "^5.1.2", - "semver": "^5.6.0", - "ssri": "^6.0.1", - "tar": "^4.4.10", - "unique-filename": "^1.1.1", - "which": "^1.3.1" - }, - "dependencies": { - "minipass": { - "version": "2.9.0", - "bundled": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - } - } - }, - "parallel-transform": { - "version": "1.1.0", - "bundled": true, - "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "path-exists": { - "version": "3.0.0", - "bundled": true - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true - }, - "path-is-inside": { - "version": "1.0.2", - "bundled": true - }, - "path-key": { - "version": "2.0.1", - "bundled": true - }, - "path-parse": { - "version": "1.0.6", - "bundled": true - }, - "performance-now": { - "version": "2.1.0", - "bundled": true - }, - "pify": { - "version": "3.0.0", - "bundled": true - }, - "prepend-http": { - "version": "1.0.4", - "bundled": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true - }, - "promise-inflight": { - "version": "1.0.1", - "bundled": true - }, - "promise-retry": { - "version": "1.1.1", - "bundled": true, - "requires": { - "err-code": "^1.0.0", - "retry": "^0.10.0" - }, - "dependencies": { - "retry": { - "version": "0.10.1", - "bundled": true - } - } - }, - "promzard": { - "version": "0.3.0", - "bundled": true, - "requires": { - "read": "1" - } - }, - "proto-list": { - "version": "1.2.4", - "bundled": true - }, - "protoduck": { - "version": "5.0.1", - "bundled": true, - "requires": { - "genfun": "^5.0.0" - } - }, - "prr": { - "version": "1.0.1", - "bundled": true - }, - "pseudomap": { - "version": "1.0.2", - "bundled": true - }, - "psl": { - "version": "1.1.29", - "bundled": true - }, - "pump": { - "version": "3.0.0", - "bundled": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "bundled": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "bundled": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "punycode": { - "version": "1.4.1", - "bundled": true - }, - "qrcode-terminal": { - "version": "0.12.0", - "bundled": true - }, - "qs": { - "version": "6.5.2", - "bundled": true - }, - "query-string": { - "version": "6.8.2", - "bundled": true, - "requires": { - "decode-uri-component": "^0.2.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - } - }, - "qw": { - "version": "1.0.1", - "bundled": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, - "read": { - "version": "1.0.7", - "bundled": true, - "requires": { - "mute-stream": "~0.0.4" - } - }, - "read-cmd-shim": { - "version": "1.0.5", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2" - } - }, - "read-installed": { - "version": "4.0.3", - "bundled": true, - "requires": { - "debuglog": "^1.0.1", - "graceful-fs": "^4.1.2", - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "slide": "~1.1.3", - "util-extend": "^1.0.1" - } - }, - "read-package-json": { - "version": "2.1.1", - "bundled": true, - "requires": { - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "json-parse-better-errors": "^1.0.1", - "normalize-package-data": "^2.0.0", - "npm-normalize-package-bin": "^1.0.0" - } - }, - "read-package-tree": { - "version": "5.3.1", - "bundled": true, - "requires": { - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0", - "util-promisify": "^2.1.0" - } - }, - "readable-stream": { - "version": "3.6.0", - "bundled": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdir-scoped-modules": { - "version": "1.1.0", - "bundled": true, - "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" - } - }, - "registry-auth-token": { - "version": "3.4.0", - "bundled": true, - "requires": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" - } - }, - "registry-url": { - "version": "3.1.0", - "bundled": true, - "requires": { - "rc": "^1.0.1" - } - }, - "request": { - "version": "2.88.0", - "bundled": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "require-directory": { - "version": "2.1.1", - "bundled": true - }, - "require-main-filename": { - "version": "2.0.0", - "bundled": true - }, - "resolve-from": { - "version": "4.0.0", - "bundled": true - }, - "retry": { - "version": "0.12.0", - "bundled": true - }, - "rimraf": { - "version": "2.7.1", - "bundled": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-queue": { - "version": "1.0.3", - "bundled": true, - "requires": { - "aproba": "^1.1.1" - }, - "dependencies": { - "aproba": { - "version": "1.2.0", - "bundled": true - } - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true - }, - "semver": { - "version": "5.7.1", - "bundled": true - }, - "semver-diff": { - "version": "2.1.0", - "bundled": true, - "requires": { - "semver": "^5.0.3" - } - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true - }, - "sha": { - "version": "3.0.0", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2" - } - }, - "shebang-command": { - "version": "1.2.0", - "bundled": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "bundled": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true - }, - "slide": { - "version": "1.1.6", - "bundled": true - }, - "smart-buffer": { - "version": "4.1.0", - "bundled": true - }, - "socks": { - "version": "2.3.3", - "bundled": true, - "requires": { - "ip": "1.1.5", - "smart-buffer": "^4.1.0" - } - }, - "socks-proxy-agent": { - "version": "4.0.2", - "bundled": true, - "requires": { - "agent-base": "~4.2.1", - "socks": "~2.3.2" - }, - "dependencies": { - "agent-base": { - "version": "4.2.1", - "bundled": true, - "requires": { - "es6-promisify": "^5.0.0" - } - } - } - }, - "sorted-object": { - "version": "2.0.1", - "bundled": true - }, - "sorted-union-stream": { - "version": "2.1.3", - "bundled": true, - "requires": { - "from2": "^1.3.0", - "stream-iterate": "^1.1.0" - }, - "dependencies": { - "from2": { - "version": "1.3.0", - "bundled": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "~1.1.10" - } - }, - "isarray": { - "version": "0.0.1", - "bundled": true - }, - "readable-stream": { - "version": "1.1.14", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "bundled": true - } - } - }, - "spdx-correct": { - "version": "3.0.0", - "bundled": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.1.0", - "bundled": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "bundled": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "bundled": true - }, - "split-on-first": { - "version": "1.1.0", - "bundled": true - }, - "sshpk": { - "version": "1.14.2", - "bundled": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "ssri": { - "version": "6.0.1", - "bundled": true, - "requires": { - "figgy-pudding": "^3.5.1" - } - }, - "stream-each": { - "version": "1.2.2", - "bundled": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "stream-iterate": { - "version": "1.2.0", - "bundled": true, - "requires": { - "readable-stream": "^2.1.5", - "stream-shift": "^1.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "stream-shift": { - "version": "1.0.0", - "bundled": true - }, - "strict-uri-encode": { - "version": "2.0.0", - "bundled": true - }, - "string-width": { - "version": "2.1.1", - "bundled": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true - }, - "strip-ansi": { - "version": "4.0.0", - "bundled": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "string_decoder": { - "version": "1.3.0", - "bundled": true, - "requires": { - "safe-buffer": "~5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.0", - "bundled": true - } - } - }, - "stringify-package": { - "version": "1.0.1", - "bundled": true - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-eof": { - "version": "1.0.0", - "bundled": true - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true - }, - "supports-color": { - "version": "5.4.0", - "bundled": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "tar": { - "version": "4.4.13", - "bundled": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - }, - "dependencies": { - "minipass": { - "version": "2.9.0", - "bundled": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - } - } - }, - "term-size": { - "version": "1.2.0", - "bundled": true, - "requires": { - "execa": "^0.7.0" - } - }, - "text-table": { - "version": "0.2.0", - "bundled": true - }, - "through": { - "version": "2.3.8", - "bundled": true - }, - "through2": { - "version": "2.0.3", - "bundled": true, - "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "timed-out": { - "version": "4.0.1", - "bundled": true - }, - "tiny-relative-date": { - "version": "1.3.0", - "bundled": true - }, - "tough-cookie": { - "version": "2.4.3", - "bundled": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "bundled": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "bundled": true, - "optional": true - }, - "typedarray": { - "version": "0.0.6", - "bundled": true - }, - "uid-number": { - "version": "0.0.6", - "bundled": true - }, - "umask": { - "version": "1.1.0", - "bundled": true - }, - "unique-filename": { - "version": "1.1.1", - "bundled": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.0", - "bundled": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "unique-string": { - "version": "1.0.0", - "bundled": true, - "requires": { - "crypto-random-string": "^1.0.0" - } - }, - "unpipe": { - "version": "1.0.0", - "bundled": true - }, - "unzip-response": { - "version": "2.0.1", - "bundled": true - }, - "update-notifier": { - "version": "2.5.0", - "bundled": true, - "requires": { - "boxen": "^1.2.1", - "chalk": "^2.0.1", - "configstore": "^3.0.0", - "import-lazy": "^2.1.0", - "is-ci": "^1.0.10", - "is-installed-globally": "^0.1.0", - "is-npm": "^1.0.0", - "latest-version": "^3.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, - "uri-js": { - "version": "4.4.0", - "bundled": true, - "requires": { - "punycode": "^2.1.0" - }, - "dependencies": { - "punycode": { - "version": "2.1.1", - "bundled": true - } - } - }, - "url-parse-lax": { - "version": "1.0.0", - "bundled": true, - "requires": { - "prepend-http": "^1.0.1" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true - }, - "util-extend": { - "version": "1.0.3", - "bundled": true - }, - "util-promisify": { - "version": "2.1.0", - "bundled": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3" - } - }, - "uuid": { - "version": "3.3.3", - "bundled": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "bundled": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "validate-npm-package-name": { - "version": "3.0.0", - "bundled": true, - "requires": { - "builtins": "^1.0.3" - } - }, - "verror": { - "version": "1.10.0", - "bundled": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "wcwidth": { - "version": "1.0.1", - "bundled": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "which": { - "version": "1.3.1", - "bundled": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "bundled": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "requires": { - "string-width": "^1.0.2" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "widest-line": { - "version": "2.0.1", - "bundled": true, - "requires": { - "string-width": "^2.1.1" - } - }, - "worker-farm": { - "version": "1.7.0", - "bundled": true, - "requires": { - "errno": "~0.1.7" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "bundled": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true - }, - "string-width": { - "version": "3.1.0", - "bundled": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "bundled": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true - }, - "write-file-atomic": { - "version": "2.4.3", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "xdg-basedir": { - "version": "3.0.0", - "bundled": true - }, - "xtend": { - "version": "4.0.1", - "bundled": true - }, - "y18n": { - "version": "4.0.0", - "bundled": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true - }, - "yargs": { - "version": "14.2.3", - "bundled": true, - "requires": { - "cliui": "^5.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^15.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "bundled": true - }, - "find-up": { - "version": "3.0.0", - "bundled": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true - }, - "locate-path": { - "version": "3.0.0", - "bundled": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "bundled": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "bundled": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "bundled": true - }, - "string-width": { - "version": "3.1.0", - "bundled": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "bundled": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "yargs-parser": { - "version": "15.0.1", - "bundled": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "bundled": true - } - } - } - } - }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -18987,13 +15889,9 @@ } }, "open-color": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/open-color/-/open-color-1.7.0.tgz", - "integrity": "sha512-Kyl74V5gohYxajOVgIaXhvhjKtXfhwl7ddJ28HVXDkPuM8PVdaWbFPucf6qPGW6aXOMxnukw0/R1lLLyXKEffA==", - "requires": { - "lodash": "^4.17.11", - "npm": "^6.9.0" - } + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/open-color/-/open-color-1.8.0.tgz", + "integrity": "sha512-gSHRpWLx83rKlHZIm9ZoUBsSMijhPRMxOOacUETjY8guu9dAwIAbtZgmVqkfglmhs3/pYppGohzp8fUdJ4YBqQ==" }, "openapi3-ts": { "version": "1.4.0", @@ -19187,6 +16085,34 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, + "pac-proxy-agent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-4.1.0.tgz", + "integrity": "sha512-ejNgYm2HTXSIYX9eFlkvqFp8hyJ374uDf0Zq5YUAifiSh1D6fo+iBivQZirGvVv8dCYUsLhmLBRhlAYvBKI5+Q==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4", + "get-uri": "3", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "5", + "pac-resolver": "^4.1.0", + "raw-body": "^2.2.0", + "socks-proxy-agent": "5" + } + }, + "pac-resolver": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-4.1.0.tgz", + "integrity": "sha512-d6lf2IrZJJ7ooVHr7BfwSjRO1yKSJMaiiWYSHcrxSIUtZrCa4KKGwcztdkZ/E9LFleJfjoi1yl+XLR7AX24nbQ==", + "dev": true, + "requires": { + "degenerator": "^2.2.0", + "ip": "^1.1.5", + "netmask": "^1.0.6" + } + }, "package-json": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", @@ -20718,6 +17644,28 @@ "ipaddr.js": "1.9.1" } }, + "proxy-agent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-4.0.0.tgz", + "integrity": "sha512-8P0Y2SkwvKjiGU1IkEfYuTteioMIDFxPL4/j49zzt5Mz3pG1KO+mIrDG1qH0PQUHTTczjwGcYl+EzfXiFj5vUQ==", + "dev": true, + "requires": { + "agent-base": "^6.0.0", + "debug": "4", + "http-proxy-agent": "^4.0.0", + "https-proxy-agent": "^5.0.0", + "lru-cache": "^5.1.1", + "pac-proxy-agent": "^4.1.0", + "proxy-from-env": "^1.0.0", + "socks-proxy-agent": "^5.0.0" + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -21026,9 +17974,9 @@ } }, "tar": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.0.5.tgz", - "integrity": "sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", + "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", "dev": true, "optional": true, "requires": { @@ -22509,9 +19457,9 @@ } }, "semver-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", - "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.2.tgz", + "integrity": "sha512-bXWyL6EAKOJa81XG1OZ/Yyuq+oT0b2YLlxx7c+mrdYPaPbnj6WgVULXhinMIeZGufuUBu/eVRqXEhiv4imfwxA==", "dev": true }, "send": { @@ -22789,6 +19737,12 @@ "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" }, + "smart-buffer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==", + "dev": true + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -23003,6 +19957,27 @@ } } }, + "socks": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.5.1.tgz", + "integrity": "sha512-oZCsJJxapULAYJaEYBSzMcz8m3jqgGrHaGhkmU/o/PQfFWYWxkAaA0UMGImb6s6tEXfKi959X6VJjMMQ3P6TTQ==", + "dev": true, + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.1.0" + } + }, + "socks-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.0.tgz", + "integrity": "sha512-lEpa1zsWCChxiynk+lCycKuC502RxDWLKJZoIhnxrWNjLSDGYRFflHA1/228VkRcnv9TIb8w98derGbpKxJRgA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4", + "socks": "^2.3.3" + } + }, "sort-keys": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", @@ -23770,9 +20745,9 @@ } }, "tar-stream": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.4.tgz", - "integrity": "sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dev": true, "requires": { "bl": "^4.0.3", @@ -26316,6 +23291,12 @@ "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", + "dev": true + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -26389,6 +23370,12 @@ "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + }, "zip-stream": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.1.3.tgz", diff --git a/package.json b/package.json index 3bf149b7f..540fae371 100644 --- a/package.json +++ b/package.json @@ -22,20 +22,19 @@ "@sentry/browser": "5.29.2", "@sentry/integrations": "5.29.2", "@testing-library/jest-dom": "5.11.8", - "@testing-library/react": "11.2.2", - "@types/jest": "26.0.19", - "@types/nanoid": "2.1.0", + "@testing-library/react": "11.2.3", + "@types/jest": "26.0.20", "@types/react": "17.0.0", "@types/react-dom": "17.0.0", "@types/socket.io-client": "1.4.34", "browser-nativefs": "0.12.0", "clsx": "1.1.1", - "firebase": "8.2.1", + "firebase": "8.2.2", "i18next-browser-languagedetector": "6.0.1", "lodash.throttle": "4.1.1", - "nanoid": "2.1.11", + "nanoid": "3.1.20", "node-sass": "4.14.1", - "open-color": "1.7.0", + "open-color": "1.8.0", "pako": "1.0.11", "png-chunk-text": "1.0.0", "png-chunks-encode": "1.0.0", @@ -53,9 +52,9 @@ "@types/lodash.throttle": "4.1.6", "@types/pako": "1.0.1", "eslint-config-prettier": "7.1.0", - "eslint-plugin-prettier": "3.3.0", - "firebase-tools": "9.1.0", - "husky": "4.3.6", + "eslint-plugin-prettier": "3.3.1", + "firebase-tools": "9.1.2", + "husky": "4.3.7", "jest-canvas-mock": "2.3.0", "lint-staged": "10.5.3", "pepjs": "0.5.3", @@ -81,8 +80,8 @@ "private": true, "scripts": { "build-node": "node ./scripts/build-node.js", - "build:app:docker": "REACT_APP_INCLUDE_GTAG=false REACT_APP_DISABLE_SENTRY=true react-scripts build", - "build:app": "REACT_APP_INCLUDE_GTAG=true REACT_APP_GIT_SHA=$NOW_GITHUB_COMMIT_SHA react-scripts build", + "build:app:docker": "REACT_APP_DISABLE_SENTRY=true react-scripts build", + "build:app": "REACT_APP_GIT_SHA=$NOW_GITHUB_COMMIT_SHA react-scripts build", "build:version": "node ./scripts/build-version.js", "build": "npm run build:app && npm run build:version", "eject": "react-scripts eject", diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png index e228a7323..40af4de2f 100644 Binary files a/public/apple-touch-icon.png and b/public/apple-touch-icon.png differ diff --git a/public/index.html b/public/index.html index 138dc4e0e..24b76e866 100644 --- a/public/index.html +++ b/public/index.html @@ -86,10 +86,10 @@ - <% if (process.env.REACT_APP_INCLUDE_GTAG === 'true') { %> + <% if (process.env.REACT_APP_GOOGLE_ANALYTICS_ID) { %> <% } %> diff --git a/public/logo-180x180.png b/public/logo-180x180.png index ade636cda..9aa9b103b 100644 Binary files a/public/logo-180x180.png and b/public/logo-180x180.png differ diff --git a/public/og-image-sm.png b/public/og-image-sm.png new file mode 100644 index 000000000..5e88dba05 Binary files /dev/null and b/public/og-image-sm.png differ diff --git a/public/og-image.png b/public/og-image.png index 1601d16ed..8f05f7bab 100644 Binary files a/public/og-image.png and b/public/og-image.png differ diff --git a/scripts/build-version.js b/scripts/build-version.js index 06b31b433..0d77f7dac 100755 --- a/scripts/build-version.js +++ b/scripts/build-version.js @@ -5,23 +5,40 @@ const path = require("path"); const versionFile = path.join("build", "version.json"); const indexFile = path.join("build", "index.html"); -const zero = (digit) => `0${digit}`.slice(-2); +const versionDate = (date) => date.toISOString().replace(".000", ""); -const versionDate = (date) => { - const date_ = `${date.getFullYear()}-${zero(date.getMonth() + 1)}-${zero( - date.getDate(), - )}`; - const time = `${zero(date.getHours())}-${zero(date.getMinutes())}-${zero( - date.getSeconds(), - )}`; - return `${date_}-${time}`; +const commitHash = () => { + try { + return require("child_process") + .execSync("git rev-parse --short HEAD") + .toString() + .trim(); + } catch { + return "none"; + } }; -const now = new Date(); +const commitDate = (hash) => { + try { + const unix = require("child_process") + .execSync(`git show -s --format=%ct ${hash}`) + .toString() + .trim(); + const date = new Date(parseInt(unix) * 1000); + return versionDate(date); + } catch { + return versionDate(new Date()); + } +}; + +const getFullVersion = () => { + const hash = commitHash(); + return `${commitDate(hash)}-${hash}`; +}; const data = JSON.stringify( { - version: versionDate(now), + version: getFullVersion(), }, undefined, 2, @@ -34,7 +51,7 @@ fs.readFile(indexFile, "utf8", (error, data) => { if (error) { return console.error(error); } - const result = data.replace(/{version}/g, versionDate(now)); + const result = data.replace(/{version}/g, getFullVersion()); fs.writeFile(indexFile, result, "utf8", (error) => { if (error) { diff --git a/scripts/locales-coverage-description.js b/scripts/locales-coverage-description.js index f4715353c..df5794409 100644 --- a/scripts/locales-coverage-description.js +++ b/scripts/locales-coverage-description.js @@ -4,25 +4,26 @@ const THRESSHOLD = 85; const crowdinMap = { "ar-SA": "en-ar", - "el-GR": "en-el", - "fi-FI": "en-fi", - "ja-JP": "en-ja", "bg-BG": "en-bg", "ca-ES": "en-ca", "de-DE": "en-de", + "el-GR": "en-el", "es-ES": "en-es", "fa-IR": "en-fa", + "fi-FI": "en-fi", "fr-FR": "en-fr", "he-IL": "en-he", "hi-IN": "en-hi", "hu-HU": "en-hu", "id-ID": "en-id", "it-IT": "en-it", + "ja-JP": "en-ja", "ko-KR": "en-ko", "my-MM": "en-my", "nb-NO": "en-nb", "nl-NL": "en-nl", "nn-NO": "en-nnno", + "pa-IN": "en-pain", "pl-PL": "en-pl", "pt-BR": "en-ptbr", "pt-PT": "en-pt", @@ -57,6 +58,7 @@ const flags = { "nb-NO": "🇳🇴", "nl-NL": "🇳🇱", "nn-NO": "🇳🇴", + "pa-IN": "🇮🇳", "pl-PL": "🇵🇱", "pt-BR": "🇧🇷", "pt-PT": "🇵🇹", @@ -73,7 +75,7 @@ const flags = { const languages = { "ar-SA": "العربية", "bg-BG": "Български", - "ca-ES": "Catalan", + "ca-ES": "Català", "de-DE": "Deutsch", "el-GR": "Ελληνικά", "es-ES": "Español", @@ -91,6 +93,7 @@ const languages = { "nb-NO": "Norsk bokmål", "nl-NL": "Nederlands", "nn-NO": "Norsk nynorsk", + "pa-IN": "ਪੰਜਾਬੀ", "pl-PL": "Polski", "pt-BR": "Português Brasileiro", "pt-PT": "Português", @@ -134,7 +137,7 @@ const printRow = (id, locale, coverage) => { } else { result += `${boldIf(language, isOver)} | `; } - result += `${coverage === 100 ? "✅" : boldIf(coverage, isOver)} |`; + result += `${coverage === 100 ? "💯" : boldIf(coverage, isOver)} |`; return result; }; diff --git a/src/actions/actionAddToLibrary.ts b/src/actions/actionAddToLibrary.ts index 53727a819..a0abbf5ca 100644 --- a/src/actions/actionAddToLibrary.ts +++ b/src/actions/actionAddToLibrary.ts @@ -3,7 +3,6 @@ import { getSelectedElements } from "../scene"; import { getNonDeletedElements } from "../element"; import { deepCopyElement } from "../element/newElement"; import { Library } from "../data/library"; -import { EVENT_LIBRARY, trackEvent } from "../analytics"; export const actionAddToLibrary = register({ name: "addToLibrary", @@ -16,7 +15,6 @@ export const actionAddToLibrary = register({ Library.loadLibrary().then((items) => { Library.saveLibrary([...items, selectedElements.map(deepCopyElement)]); }); - trackEvent(EVENT_LIBRARY, "add"); return false; }, contextMenuOrder: 6, diff --git a/src/actions/actionAlign.tsx b/src/actions/actionAlign.tsx index 77c1e8800..5397df9b4 100644 --- a/src/actions/actionAlign.tsx +++ b/src/actions/actionAlign.tsx @@ -1,7 +1,5 @@ import React from "react"; -import { KEYS } from "../keys"; -import { t } from "../i18n"; -import { register } from "./register"; +import { alignElements, Alignment } from "../align"; import { AlignBottomIcon, AlignLeftIcon, @@ -10,14 +8,15 @@ import { CenterHorizontallyIcon, CenterVerticallyIcon, } from "../components/icons"; -import { getSelectedElements, isSomeElementSelected } from "../scene"; -import { getElementMap, getNonDeletedElements } from "../element"; import { ToolButton } from "../components/ToolButton"; +import { getElementMap, getNonDeletedElements } from "../element"; import { ExcalidrawElement } from "../element/types"; +import { t } from "../i18n"; +import { KEYS } from "../keys"; +import { getSelectedElements, isSomeElementSelected } from "../scene"; import { AppState } from "../types"; -import { alignElements, Alignment } from "../align"; import { getShortcutKey } from "../utils"; -import { trackEvent, EVENT_ALIGN } from "../analytics"; +import { register } from "./register"; const enableActionGroup = ( elements: readonly ExcalidrawElement[], @@ -44,7 +43,6 @@ const alignSelectedElements = ( export const actionAlignTop = register({ name: "alignTop", perform: (elements, appState) => { - trackEvent(EVENT_ALIGN, "align", "top"); return { appState, elements: alignSelectedElements(elements, appState, { @@ -74,7 +72,6 @@ export const actionAlignTop = register({ export const actionAlignBottom = register({ name: "alignBottom", perform: (elements, appState) => { - trackEvent(EVENT_ALIGN, "align", "bottom"); return { appState, elements: alignSelectedElements(elements, appState, { @@ -104,7 +101,6 @@ export const actionAlignBottom = register({ export const actionAlignLeft = register({ name: "alignLeft", perform: (elements, appState) => { - trackEvent(EVENT_ALIGN, "align", "left"); return { appState, elements: alignSelectedElements(elements, appState, { @@ -134,7 +130,6 @@ export const actionAlignLeft = register({ export const actionAlignRight = register({ name: "alignRight", perform: (elements, appState) => { - trackEvent(EVENT_ALIGN, "align", "right"); return { appState, elements: alignSelectedElements(elements, appState, { @@ -164,7 +159,6 @@ export const actionAlignRight = register({ export const actionAlignVerticallyCentered = register({ name: "alignVerticallyCentered", perform: (elements, appState) => { - trackEvent(EVENT_ALIGN, "vertically", "center"); return { appState, elements: alignSelectedElements(elements, appState, { @@ -190,7 +184,6 @@ export const actionAlignVerticallyCentered = register({ export const actionAlignHorizontallyCentered = register({ name: "alignHorizontallyCentered", perform: (elements, appState) => { - trackEvent(EVENT_ALIGN, "horizontally", "center"); return { appState, elements: alignSelectedElements(elements, appState, { diff --git a/src/actions/actionCanvas.tsx b/src/actions/actionCanvas.tsx index aff1a7f66..d29b7c716 100644 --- a/src/actions/actionCanvas.tsx +++ b/src/actions/actionCanvas.tsx @@ -1,7 +1,5 @@ import React from "react"; -import { EVENT_ACTION, EVENT_CHANGE, trackEvent } from "../analytics"; import { getDefaultAppState } from "../appState"; -import colors from "../colors"; import { ColorPicker } from "../components/ColorPicker"; import { resetZoom, trash, zoomIn, zoomOut } from "../components/icons"; import { ToolButton } from "../components/ToolButton"; @@ -21,15 +19,6 @@ import { register } from "./register"; export const actionChangeViewBackgroundColor = register({ name: "changeViewBackgroundColor", perform: (_, appState, value) => { - if (value !== appState.viewBackgroundColor) { - trackEvent( - EVENT_CHANGE, - "canvas color", - colors.canvasBackground.includes(value) - ? `${value} (picker ${colors.canvasBackground.indexOf(value)})` - : value, - ); - } return { appState: { ...appState, viewBackgroundColor: value }, commitToHistory: true, @@ -52,7 +41,6 @@ export const actionChangeViewBackgroundColor = register({ export const actionClearCanvas = register({ name: "clearCanvas", perform: (elements, appState: AppState) => { - trackEvent(EVENT_ACTION, "clear canvas"); return { elements: elements.map((element) => newElementWith(element, { isDeleted: true }), @@ -98,7 +86,6 @@ export const actionZoomIn = register({ { left: appState.offsetLeft, top: appState.offsetTop }, { x: appState.width / 2, y: appState.height / 2 }, ); - trackEvent(EVENT_ACTION, "zoom", "in", zoom.value * 100); return { appState: { ...appState, @@ -133,7 +120,6 @@ export const actionZoomOut = register({ { x: appState.width / 2, y: appState.height / 2 }, ); - trackEvent(EVENT_ACTION, "zoom", "out", zoom.value * 100); return { appState: { ...appState, @@ -161,7 +147,6 @@ export const actionZoomOut = register({ export const actionResetZoom = register({ name: "resetZoom", perform: (_elements, appState) => { - trackEvent(EVENT_ACTION, "zoom", "reset", 100); return { appState: { ...appState, @@ -234,12 +219,10 @@ const zoomToFitElements = ( left: appState.offsetLeft, top: appState.offsetTop, }); - const action = zoomToSelection ? "selection" : "fit"; const [x1, y1, x2, y2] = commonBounds; const centerX = (x1 + x2) / 2; const centerY = (y1 + y2) / 2; - trackEvent(EVENT_ACTION, "zoom", action, newZoom.value * 100); return { appState: { ...appState, diff --git a/src/actions/actionDistribute.tsx b/src/actions/actionDistribute.tsx index 15669dde0..fdd8267c1 100644 --- a/src/actions/actionDistribute.tsx +++ b/src/actions/actionDistribute.tsx @@ -1,19 +1,18 @@ import React from "react"; -import { CODES } from "../keys"; -import { t } from "../i18n"; -import { register } from "./register"; import { DistributeHorizontallyIcon, DistributeVerticallyIcon, } from "../components/icons"; -import { getSelectedElements, isSomeElementSelected } from "../scene"; -import { getElementMap, getNonDeletedElements } from "../element"; import { ToolButton } from "../components/ToolButton"; -import { ExcalidrawElement } from "../element/types"; -import { AppState } from "../types"; import { distributeElements, Distribution } from "../disitrubte"; +import { getElementMap, getNonDeletedElements } from "../element"; +import { ExcalidrawElement } from "../element/types"; +import { t } from "../i18n"; +import { CODES } from "../keys"; +import { getSelectedElements, isSomeElementSelected } from "../scene"; +import { AppState } from "../types"; import { getShortcutKey } from "../utils"; -import { EVENT_ALIGN, trackEvent } from "../analytics"; +import { register } from "./register"; const enableActionGroup = ( elements: readonly ExcalidrawElement[], @@ -40,7 +39,6 @@ const distributeSelectedElements = ( export const distributeHorizontally = register({ name: "distributeHorizontally", perform: (elements, appState) => { - trackEvent(EVENT_ALIGN, "distribute", "horizontally"); return { appState, elements: distributeSelectedElements(elements, appState, { @@ -69,7 +67,6 @@ export const distributeHorizontally = register({ export const distributeVertically = register({ name: "distributeVertically", perform: (elements, appState) => { - trackEvent(EVENT_ALIGN, "distribute", "vertically"); return { appState, elements: distributeSelectedElements(elements, appState, { diff --git a/src/actions/actionExport.tsx b/src/actions/actionExport.tsx index 2748ad3a4..e341d98fc 100644 --- a/src/actions/actionExport.tsx +++ b/src/actions/actionExport.tsx @@ -1,22 +1,20 @@ import React from "react"; -import { EVENT_CHANGE, EVENT_IO, trackEvent } from "../analytics"; -import { load, save, saveAs } from "../components/icons"; +import { trackEvent } from "../analytics"; +import { load, questionCircle, save, saveAs } from "../components/icons"; import { ProjectName } from "../components/ProjectName"; import { ToolButton } from "../components/ToolButton"; +import "../components/ToolIcon.scss"; import { Tooltip } from "../components/Tooltip"; -import { questionCircle } from "../components/icons"; import { loadFromJSON, saveAsJSON } from "../data"; import { t } from "../i18n"; import useIsMobile from "../is-mobile"; import { KEYS } from "../keys"; -import { muteFSAbortError } from "../utils"; import { register } from "./register"; -import "../components/ToolIcon.scss"; export const actionChangeProjectName = register({ name: "changeProjectName", perform: (_elements, appState, value) => { - trackEvent(EVENT_CHANGE, "title"); + trackEvent("change", "title"); return { appState: { ...appState, name: value }, commitToHistory: false }; }, PanelComponent: ({ appState, updateData }) => ( @@ -100,7 +98,6 @@ export const actionSaveScene = register({ perform: async (elements, appState, value) => { try { const { fileHandle } = await saveAsJSON(elements, appState); - trackEvent(EVENT_IO, "save"); return { commitToHistory: false, appState: { ...appState, fileHandle } }; } catch (error) { if (error?.name !== "AbortError") { @@ -131,7 +128,6 @@ export const actionSaveAsScene = register({ ...appState, fileHandle: null, }); - trackEvent(EVENT_IO, "save as"); return { commitToHistory: false, appState: { ...appState, fileHandle } }; } catch (error) { if (error?.name !== "AbortError") { @@ -159,18 +155,29 @@ export const actionSaveAsScene = register({ export const actionLoadScene = register({ name: "loadScene", - perform: ( - elements, - appState, - { elements: loadedElements, appState: loadedAppState, error }, - ) => ({ - elements: loadedElements, - appState: { - ...loadedAppState, - errorMessage: error, - }, - commitToHistory: true, - }), + perform: async (elements, appState) => { + try { + const { + elements: loadedElements, + appState: loadedAppState, + } = await loadFromJSON(appState); + return { + elements: loadedElements, + appState: loadedAppState, + commitToHistory: true, + }; + } catch (error) { + if (error?.name === "AbortError") { + return false; + } + return { + elements, + appState: { ...appState, errorMessage: error.message }, + commitToHistory: false, + }; + } + }, + keyTest: (event) => event[KEYS.CTRL_OR_CMD] && event.key === KEYS.O, PanelComponent: ({ updateData, appState }) => ( { - loadFromJSON(appState) - .then(({ elements, appState }) => { - updateData({ elements, appState }); - }) - .catch(muteFSAbortError) - .catch((error) => { - updateData({ error: error.message }); - }); - }} + onClick={updateData} /> ), }); diff --git a/src/actions/actionFinalize.tsx b/src/actions/actionFinalize.tsx index 67f4da882..2842615f9 100644 --- a/src/actions/actionFinalize.tsx +++ b/src/actions/actionFinalize.tsx @@ -118,11 +118,14 @@ export const actionFinalize = register({ ); } - if (!appState.elementLocked) { + if (!appState.elementLocked && appState.elementType !== "draw") { appState.selectedElementIds[multiPointElement.id] = true; } } - if (!appState.elementLocked || !multiPointElement) { + if ( + (!appState.elementLocked && appState.elementType !== "draw") || + !multiPointElement + ) { resetCursor(); } return { @@ -130,7 +133,8 @@ export const actionFinalize = register({ appState: { ...appState, elementType: - appState.elementLocked && multiPointElement + (appState.elementLocked || appState.elementType === "draw") && + multiPointElement ? appState.elementType : "selection", draggingElement: null, @@ -139,7 +143,9 @@ export const actionFinalize = register({ startBoundElement: null, suggestedBindings: [], selectedElementIds: - multiPointElement && !appState.elementLocked + multiPointElement && + !appState.elementLocked && + appState.elementType !== "draw" ? { ...appState.selectedElementIds, [multiPointElement.id]: true, diff --git a/src/actions/actionMenu.tsx b/src/actions/actionMenu.tsx index 7abe74c40..6ae29e519 100644 --- a/src/actions/actionMenu.tsx +++ b/src/actions/actionMenu.tsx @@ -7,7 +7,6 @@ import { register } from "./register"; import { allowFullScreen, exitFullScreen, isFullScreen } from "../utils"; import { CODES, KEYS } from "../keys"; import { HelpIcon } from "../components/HelpIcon"; -import { EVENT_DIALOG, trackEvent } from "../analytics"; export const actionToggleCanvasMenu = register({ name: "toggleCanvasMenu", @@ -72,7 +71,6 @@ export const actionFullScreen = register({ export const actionShortcuts = register({ name: "toggleShortcuts", perform: (_elements, appState) => { - trackEvent(EVENT_DIALOG, "shortcuts"); return { appState: { ...appState, diff --git a/src/actions/actionNavigate.tsx b/src/actions/actionNavigate.tsx index 02d981f75..ea9012f9d 100644 --- a/src/actions/actionNavigate.tsx +++ b/src/actions/actionNavigate.tsx @@ -1,16 +1,14 @@ import React from "react"; -import { Avatar } from "../components/Avatar"; -import { register } from "./register"; import { getClientColors, getClientInitials } from "../clients"; -import { Collaborator } from "../types"; +import { Avatar } from "../components/Avatar"; import { centerScrollOn } from "../scene/scroll"; -import { EVENT_SHARE, trackEvent } from "../analytics"; +import { Collaborator } from "../types"; +import { register } from "./register"; export const actionGoToCollaborator = register({ name: "goToCollaborator", perform: (_elements, appState, value) => { const point = value as Collaborator["pointer"]; - trackEvent(EVENT_SHARE, "go to collaborator"); if (!point) { return { appState, commitToHistory: false }; } diff --git a/src/actions/actionProperties.tsx b/src/actions/actionProperties.tsx index a818cf245..b6e39fa32 100644 --- a/src/actions/actionProperties.tsx +++ b/src/actions/actionProperties.tsx @@ -1,56 +1,53 @@ import React from "react"; -import { getLanguage } from "../i18n"; -import { - ExcalidrawElement, - ExcalidrawTextElement, - TextAlign, - FontFamily, - ExcalidrawLinearElement, - Arrowhead, -} from "../element/types"; -import { - getCommonAttributeOfSelectedElements, - isSomeElementSelected, - getTargetElements, - canChangeSharpness, - canHaveArrowheads, -} from "../scene"; -import { ButtonSelect } from "../components/ButtonSelect"; +import { AppState } from "../../src/types"; import { ButtonIconSelect } from "../components/ButtonIconSelect"; +import { ButtonSelect } from "../components/ButtonSelect"; +import { ColorPicker } from "../components/ColorPicker"; import { IconPicker } from "../components/IconPicker"; import { - isTextElement, - redrawTextBoundingBox, - getNonDeletedElements, -} from "../element"; -import { isLinearElement, isLinearElementType } from "../element/typeChecks"; -import { ColorPicker } from "../components/ColorPicker"; -import { AppState } from "../../src/types"; -import { t } from "../i18n"; -import { register } from "./register"; -import { newElementWith } from "../element/mutateElement"; -import { DEFAULT_FONT_SIZE, DEFAULT_FONT_FAMILY } from "../constants"; -import { randomInteger } from "../random"; -import { - FillHachureIcon, - FillCrossHatchIcon, - FillSolidIcon, - StrokeWidthIcon, - StrokeStyleSolidIcon, - StrokeStyleDashedIcon, - StrokeStyleDottedIcon, - EdgeSharpIcon, - EdgeRoundIcon, - SloppinessArchitectIcon, - SloppinessArtistIcon, - SloppinessCartoonistIcon, ArrowheadArrowIcon, ArrowheadBarIcon, ArrowheadDotIcon, ArrowheadNoneIcon, + EdgeRoundIcon, + EdgeSharpIcon, + FillCrossHatchIcon, + FillHachureIcon, + FillSolidIcon, + SloppinessArchitectIcon, + SloppinessArtistIcon, + SloppinessCartoonistIcon, + StrokeStyleDashedIcon, + StrokeStyleDottedIcon, + StrokeStyleSolidIcon, + StrokeWidthIcon, } from "../components/icons"; -import { EVENT_CHANGE, trackEvent } from "../analytics"; -import colors from "../colors"; +import { DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE } from "../constants"; +import { + getNonDeletedElements, + isTextElement, + redrawTextBoundingBox, +} from "../element"; +import { newElementWith } from "../element/mutateElement"; +import { isLinearElement, isLinearElementType } from "../element/typeChecks"; +import { + Arrowhead, + ExcalidrawElement, + ExcalidrawLinearElement, + ExcalidrawTextElement, + FontFamily, + TextAlign, +} from "../element/types"; +import { getLanguage, t } from "../i18n"; +import { randomInteger } from "../random"; +import { + canChangeSharpness, + canHaveArrowheads, + getCommonAttributeOfSelectedElements, + getTargetElements, + isSomeElementSelected, +} from "../scene"; +import { register } from "./register"; const changeProperty = ( elements: readonly ExcalidrawElement[], @@ -92,15 +89,6 @@ const getFormValue = function ( export const actionChangeStrokeColor = register({ name: "changeStrokeColor", perform: (elements, appState, value) => { - if (value !== appState.currentItemStrokeColor) { - trackEvent( - EVENT_CHANGE, - "stroke color", - colors.elementStroke.includes(value) - ? `${value} (picker ${colors.elementStroke.indexOf(value)})` - : value, - ); - } return { elements: changeProperty(elements, appState, (el) => newElementWith(el, { @@ -132,16 +120,6 @@ export const actionChangeStrokeColor = register({ export const actionChangeBackgroundColor = register({ name: "changeBackgroundColor", perform: (elements, appState, value) => { - if (value !== appState.currentItemBackgroundColor) { - trackEvent( - EVENT_CHANGE, - "background color", - colors.elementBackground.includes(value) - ? `${value} (picker ${colors.elementBackground.indexOf(value)})` - : value, - ); - } - return { elements: changeProperty(elements, appState, (el) => newElementWith(el, { @@ -173,7 +151,6 @@ export const actionChangeBackgroundColor = register({ export const actionChangeFillStyle = register({ name: "changeFillStyle", perform: (elements, appState, value) => { - trackEvent(EVENT_CHANGE, "fill", value); return { elements: changeProperty(elements, appState, (el) => newElementWith(el, { @@ -223,7 +200,6 @@ export const actionChangeFillStyle = register({ export const actionChangeStrokeWidth = register({ name: "changeStrokeWidth", perform: (elements, appState, value) => { - trackEvent(EVENT_CHANGE, "stroke", "width", value); return { elements: changeProperty(elements, appState, (el) => newElementWith(el, { @@ -286,7 +262,6 @@ export const actionChangeStrokeWidth = register({ export const actionChangeSloppiness = register({ name: "changeSloppiness", perform: (elements, appState, value) => { - trackEvent(EVENT_CHANGE, "stroke", "sloppiness", value); return { elements: changeProperty(elements, appState, (el) => newElementWith(el, { @@ -335,7 +310,6 @@ export const actionChangeSloppiness = register({ export const actionChangeStrokeStyle = register({ name: "changeStrokeStyle", perform: (elements, appState, value) => { - trackEvent(EVENT_CHANGE, "style", value); return { elements: changeProperty(elements, appState, (el) => newElementWith(el, { @@ -383,7 +357,6 @@ export const actionChangeStrokeStyle = register({ export const actionChangeOpacity = register({ name: "changeOpacity", perform: (elements, appState, value) => { - trackEvent(EVENT_CHANGE, "opacity", "value", value); return { elements: changeProperty(elements, appState, (el) => newElementWith(el, { @@ -580,7 +553,6 @@ export const actionChangeSharpness = register({ const shouldUpdateForLinearElements = targetElements.length ? targetElements.every(isLinearElement) : isLinearElementType(appState.elementType); - trackEvent(EVENT_CHANGE, "edge", value); return { elements: changeProperty(elements, appState, (el) => newElementWith(el, { @@ -642,12 +614,6 @@ export const actionChangeArrowhead = register({ return { elements: changeProperty(elements, appState, (el) => { if (isLinearElement(el)) { - trackEvent( - EVENT_CHANGE, - `arrowhead ${value.position}`, - value.type || "none", - ); - const { position, type } = value; if (position === "start") { diff --git a/src/actions/actionStyles.ts b/src/actions/actionStyles.ts index 991f62b95..dab50b637 100644 --- a/src/actions/actionStyles.ts +++ b/src/actions/actionStyles.ts @@ -4,6 +4,7 @@ import { redrawTextBoundingBox, } from "../element"; import { CODES, KEYS } from "../keys"; +import { t } from "../i18n"; import { register } from "./register"; import { mutateElement, newElementWith } from "../element/mutateElement"; import { @@ -23,6 +24,10 @@ export const actionCopyStyles = register({ copiedStyles = JSON.stringify(element); } return { + appState: { + ...appState, + toastMessage: t("toast.copyStyles"), + }, commitToHistory: false, }; }, diff --git a/src/actions/shortcuts.ts b/src/actions/shortcuts.ts index cab6526b0..e2fcf595a 100644 --- a/src/actions/shortcuts.ts +++ b/src/actions/shortcuts.ts @@ -20,6 +20,7 @@ export type ShortcutName = | "group" | "ungroup" | "gridMode" + | "zenMode" | "stats" | "addToLibrary"; @@ -52,6 +53,7 @@ const shortcutMap: Record = { group: [getShortcutKey("CtrlOrCmd+G")], ungroup: [getShortcutKey("CtrlOrCmd+Shift+G")], gridMode: [getShortcutKey("CtrlOrCmd+'")], + zenMode: [getShortcutKey("Alt+Z")], stats: [], addToLibrary: [], }; diff --git a/src/analytics.ts b/src/analytics.ts index 255862736..30a3887e3 100644 --- a/src/analytics.ts +++ b/src/analytics.ts @@ -1,18 +1,7 @@ -export const EVENT_ACTION = "action"; -export const EVENT_ALIGN = "align"; -export const EVENT_CHANGE = "change"; -export const EVENT_DIALOG = "dialog"; -export const EVENT_EXIT = "exit"; -export const EVENT_IO = "io"; -export const EVENT_LAYER = "layer"; -export const EVENT_LIBRARY = "library"; -export const EVENT_LOAD = "load"; -export const EVENT_SHAPE = "shape"; -export const EVENT_SHARE = "share"; -export const EVENT_MAGIC = "magic"; - export const trackEvent = - typeof window !== "undefined" && window.gtag + process.env.REACT_APP_GOOGLE_ANALYTICS_ID && + typeof window !== "undefined" && + window.gtag ? (category: string, name: string, label?: string, value?: number) => { window.gtag("event", name, { event_category: category, @@ -23,5 +12,6 @@ export const trackEvent = : typeof process !== "undefined" && process?.env?.JEST_WORKER_ID ? (category: string, name: string, label?: string, value?: number) => {} : (category: string, name: string, label?: string, value?: number) => { - console.info("Track Event", category, name, label, value); + // Uncomment the next line to track locally + // console.info("Track Event", category, name, label, value); }; diff --git a/src/appState.ts b/src/appState.ts index 02036a43e..dd2aeb8a2 100644 --- a/src/appState.ts +++ b/src/appState.ts @@ -67,6 +67,7 @@ export const getDefaultAppState = (): Omit< showStats: false, startBoundElement: null, suggestedBindings: [], + toastMessage: null, viewBackgroundColor: oc.white, width: window.innerWidth, zenModeEnabled: false, @@ -145,6 +146,7 @@ const APP_STATE_STORAGE_CONF = (< showStats: { browser: true, export: false }, startBoundElement: { browser: false, export: false }, suggestedBindings: { browser: false, export: false }, + toastMessage: { browser: false, export: false }, viewBackgroundColor: { browser: true, export: true }, width: { browser: false, export: false }, zenModeEnabled: { browser: true, export: false }, diff --git a/src/charts.ts b/src/charts.ts index 48e21d46f..f36a076e4 100644 --- a/src/charts.ts +++ b/src/charts.ts @@ -1,4 +1,3 @@ -import { EVENT_MAGIC, trackEvent } from "./analytics"; import colors from "./colors"; import { DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, ENV } from "./constants"; import { newElement, newLinearElement, newTextElement } from "./element"; @@ -473,7 +472,6 @@ export const renderSpreadsheet = ( x: number, y: number, ): ChartElements => { - trackEvent(EVENT_MAGIC, "chart", chartType, spreadsheet.values.length); if (chartType === "line") { return chartTypeLine(spreadsheet, x, y); } diff --git a/src/components/Actions.tsx b/src/components/Actions.tsx index ad1a0a45e..177fd61c2 100644 --- a/src/components/Actions.tsx +++ b/src/components/Actions.tsx @@ -1,23 +1,22 @@ import React from "react"; -import { AppState, Zoom } from "../types"; -import { ExcalidrawElement } from "../element/types"; import { ActionManager } from "../actions/manager"; +import { getNonDeletedElements } from "../element"; +import { ExcalidrawElement } from "../element/types"; +import { t } from "../i18n"; +import useIsMobile from "../is-mobile"; import { - hasBackground, - hasStroke, canChangeSharpness, - hasText, canHaveArrowheads, getTargetElements, + hasBackground, + hasStroke, + hasText, } from "../scene"; -import { t } from "../i18n"; import { SHAPES } from "../shapes"; -import { ToolButton } from "./ToolButton"; +import { AppState, Zoom } from "../types"; import { capitalizeString, isTransparent, setCursorForShape } from "../utils"; import Stack from "./Stack"; -import useIsMobile from "../is-mobile"; -import { getNonDeletedElements } from "../element"; -import { trackEvent, EVENT_SHAPE, EVENT_DIALOG } from "../analytics"; +import { ToolButton } from "./ToolButton"; export const SelectedShapeActions = ({ appState, @@ -181,7 +180,6 @@ export const ShapesSwitcher = ({ aria-keyshortcuts={shortcut} data-testid={value} onChange={() => { - trackEvent(EVENT_SHAPE, value, "toolbar"); setAppState({ elementType: value, multiElement: null, @@ -203,9 +201,6 @@ export const ShapesSwitcher = ({ title={`${capitalizeString(t("toolBar.library"))} — 9`} aria-label={capitalizeString(t("toolBar.library"))} onClick={() => { - if (!isLibraryOpen) { - trackEvent(EVENT_DIALOG, "library"); - } setAppState({ isLibraryOpen: !isLibraryOpen }); }} /> diff --git a/src/components/App.tsx b/src/components/App.tsx index ecce0fd2f..faca963c6 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -8,12 +8,7 @@ import { createRedoAction, createUndoAction } from "../actions/actionHistory"; import { ActionManager } from "../actions/manager"; import { actions } from "../actions/register"; import { ActionResult } from "../actions/types"; -import { - EVENT_DIALOG, - EVENT_LIBRARY, - EVENT_SHAPE, - trackEvent, -} from "../analytics"; +import { trackEvent } from "../analytics"; import { getDefaultAppState } from "../appState"; import { copyToClipboard, @@ -111,7 +106,7 @@ import { selectGroupsForSelectedElements, } from "../groups"; import { createHistory, SceneHistory } from "../history"; -import { getLanguage, t } from "../i18n"; +import { defaultLang, getLanguage, languages, setLanguage, t } from "../i18n"; import { CODES, getResizeCenterPointKey, @@ -163,6 +158,7 @@ import { import ContextMenu from "./ContextMenu"; import LayerUI from "./LayerUI"; import { Stats } from "./Stats"; +import { Toast } from "./Toast"; const { history } = createHistory(); @@ -332,7 +328,7 @@ class App extends React.Component { offsetLeft, } = this.state; - const { onCollabButtonClick, onExportToBackend } = this.props; + const { onCollabButtonClick, onExportToBackend, renderFooter } = this.props; const canvasScale = window.devicePixelRatio; const canvasWidth = canvasDOMWidth * canvasScale; @@ -369,9 +365,10 @@ class App extends React.Component { } zenModeEnabled={zenModeEnabled} toggleZenMode={this.toggleZenMode} - lng={getLanguage().lng} + langCode={getLanguage().code} isCollaborating={this.props.isCollaborating || false} onExportToBackend={onExportToBackend} + renderCustomFooter={renderFooter} /> {this.state.showStats && ( { onClose={this.toggleStats} /> )} + {this.state.toastMessage !== null && ( + + )}
{ ) ) { await Library.importLibrary(blob); - trackEvent(EVENT_LIBRARY, "import"); this.setState({ isLibraryOpen: true, }); @@ -738,6 +740,10 @@ class App extends React.Component { } componentDidUpdate(prevProps: ExcalidrawProps, prevState: AppState) { + if (prevProps.langCode !== this.props.langCode) { + this.updateLanguage(); + } + if ( prevProps.width !== this.props.width || prevProps.height !== this.props.height || @@ -912,6 +918,7 @@ class App extends React.Component { this.canvas!, this.state, ); + this.setState({ toastMessage: t("toast.copyToClipboardAsPng") }); } catch (error) { console.error(error); this.setState({ errorMessage: error.message }); @@ -1129,7 +1136,6 @@ class App extends React.Component { toggleLock = () => { this.setState((prevState) => { - trackEvent(EVENT_SHAPE, "lock", !prevState.elementLocked ? "on" : "off"); return { elementLocked: !prevState.elementLocked, elementType: prevState.elementLocked @@ -1153,7 +1159,7 @@ class App extends React.Component { toggleStats = () => { if (!this.state.showStats) { - trackEvent(EVENT_DIALOG, "stats"); + trackEvent("dialog", "stats"); } this.setState({ showStats: !this.state.showStats, @@ -1170,6 +1176,10 @@ class App extends React.Component { }); }; + clearToast = () => { + this.setState({ toastMessage: null }); + }; + public updateScene = withBatchedUpdates((sceneData: SceneData) => { if (sceneData.commitToHistory) { history.resumeRecording(); @@ -1265,9 +1275,6 @@ class App extends React.Component { } if (event.code === CODES.NINE) { - if (!this.state.isLibraryOpen) { - trackEvent(EVENT_DIALOG, "library"); - } this.setState({ isLibraryOpen: !this.state.isLibraryOpen }); } @@ -1352,7 +1359,6 @@ class App extends React.Component { ) { const shape = findShapeByKey(event.key); if (shape) { - trackEvent(EVENT_SHAPE, shape, "shortcut"); this.selectShapeTool(shape); } else if (event.key === KEYS.Q) { this.toggleLock(); @@ -1736,7 +1742,6 @@ class App extends React.Component { resetCursor(); if (!event[KEYS.CTRL_OR_CMD]) { - trackEvent(EVENT_SHAPE, "text", "double-click"); this.startTextEditing({ sceneX, sceneY, @@ -3136,7 +3141,7 @@ class App extends React.Component { ); } this.setState({ suggestedBindings: [], startBoundElement: null }); - if (!elementLocked) { + if (!elementLocked && elementType !== "draw") { resetCursor(); this.setState((prevState) => ({ draggingElement: null, @@ -3283,7 +3288,7 @@ class App extends React.Component { return; } - if (!elementLocked && draggingElement) { + if (!elementLocked && elementType !== "draw" && draggingElement) { this.setState((prevState) => ({ selectedElementIds: { ...prevState.selectedElementIds, @@ -3307,7 +3312,7 @@ class App extends React.Component { ); } - if (!elementLocked) { + if (!elementLocked && elementType !== "draw") { resetCursor(); this.setState({ draggingElement: null, @@ -3645,6 +3650,12 @@ class App extends React.Component { label: t("labels.gridMode"), action: this.toggleGridMode, }, + { + checked: this.state.zenModeEnabled, + shortcutName: "zenMode", + label: t("buttons.zenMode"), + action: this.toggleZenMode, + }, { checked: this.state.showStats, shortcutName: "stats", @@ -3817,7 +3828,9 @@ class App extends React.Component { }; private resetShouldCacheIgnoreZoomDebounced = debounce(() => { - this.setState({ shouldCacheIgnoreZoom: false }); + if (!this.unmounted) { + this.setState({ shouldCacheIgnoreZoom: false }); + } }, 300); private getCanvasOffsets(offsets?: { @@ -3849,6 +3862,14 @@ class App extends React.Component { offsetTop: typeof offsets?.offsetTop === "number" ? offsets.offsetTop : 0, }; } + + private async updateLanguage() { + const currentLang = + languages.find((lang) => lang.code === this.props.langCode) || + defaultLang; + await setLanguage(currentLang); + this.setAppState({}); + } } // ----------------------------------------------------------------------------- diff --git a/src/components/BackgroundPickerAndDarkModeToggle.tsx b/src/components/BackgroundPickerAndDarkModeToggle.tsx index e87ff08a9..f2eba1315 100644 --- a/src/components/BackgroundPickerAndDarkModeToggle.tsx +++ b/src/components/BackgroundPickerAndDarkModeToggle.tsx @@ -1,6 +1,5 @@ import React from "react"; import { ActionManager } from "../actions/manager"; -import { EVENT_CHANGE, trackEvent } from "../analytics"; import { AppState } from "../types"; import { DarkModeToggle } from "./DarkModeToggle"; @@ -19,8 +18,6 @@ export const BackgroundPickerAndDarkModeToggle = ({ { - // TODO: track the theme on the first load too - trackEvent(EVENT_CHANGE, "theme", appearance); setAppState({ appearance }); }} /> diff --git a/src/components/CollabButton.tsx b/src/components/CollabButton.tsx index 297b56391..a046041da 100644 --- a/src/components/CollabButton.tsx +++ b/src/components/CollabButton.tsx @@ -6,7 +6,6 @@ import useIsMobile from "../is-mobile"; import { users } from "./icons"; import "./CollabButton.scss"; -import { EVENT_DIALOG, trackEvent } from "../analytics"; const CollabButton = ({ isCollaborating, @@ -23,10 +22,7 @@ const CollabButton = ({ className={clsx("CollabButton", { "is-collaborating": isCollaborating, })} - onClick={() => { - trackEvent(EVENT_DIALOG, "collaboration"); - onClick(); - }} + onClick={onClick} icon={users} type="button" title={t("buttons.roomDialog")} diff --git a/src/components/ContextMenu.scss b/src/components/ContextMenu.scss index 4282685e8..a897ea7e4 100644 --- a/src/components/ContextMenu.scss +++ b/src/components/ContextMenu.scss @@ -54,6 +54,7 @@ .context-menu-option__shortcut { justify-self: end; opacity: 0.6; + font-family: inherit; font-size: 0.7rem; } } diff --git a/src/components/ContextMenu.tsx b/src/components/ContextMenu.tsx index 27d14d880..e8ec95072 100644 --- a/src/components/ContextMenu.tsx +++ b/src/components/ContextMenu.tsx @@ -52,11 +52,11 @@ const ContextMenu = ({ options, onCloseRequest, top, left }: Props) => { onClick={action} >
{label}
-
+ {shortcutName ? getShortcutFromShortcutName(shortcutName) : ""} -
+ ))} diff --git a/src/components/Dialog.scss b/src/components/Dialog.scss index df937f731..b3bd648f3 100644 --- a/src/components/Dialog.scss +++ b/src/components/Dialog.scss @@ -1,6 +1,11 @@ @import "../css/_variables"; .excalidraw { + .Dialog { + user-select: text; + cursor: auto; + } + .Dialog__title { display: grid; align-items: center; diff --git a/src/components/ExportDialog.tsx b/src/components/ExportDialog.tsx index 4abae7552..2df04aa7d 100644 --- a/src/components/ExportDialog.tsx +++ b/src/components/ExportDialog.tsx @@ -1,7 +1,6 @@ import React, { useEffect, useRef, useState } from "react"; import { render, unmountComponentAtNode } from "react-dom"; import { ActionsManagerInterface } from "../actions/types"; -import { EVENT_DIALOG, trackEvent } from "../analytics"; import { probablySupportsClipboardBlob } from "../clipboard"; import { canvasToBlob } from "../data/blob"; import { NonDeletedExcalidrawElement } from "../element/types"; @@ -251,7 +250,6 @@ export const ExportDialog = ({ <> { - trackEvent(EVENT_DIALOG, "export"); setModalIsShown(true); }} icon={exportFile} diff --git a/src/components/GitHubCorner.tsx b/src/components/GitHubCorner.tsx index a61a0b733..e7c2206fe 100644 --- a/src/components/GitHubCorner.tsx +++ b/src/components/GitHubCorner.tsx @@ -1,6 +1,5 @@ -import React from "react"; import oc from "open-color"; -import { EVENT_EXIT, trackEvent } from "../analytics"; +import React from "react"; // https://github.com/tholman/github-corners export const GitHubCorner = React.memo( @@ -17,9 +16,6 @@ export const GitHubCorner = React.memo( target="_blank" rel="noopener noreferrer" aria-label="GitHub repository" - onClick={() => { - trackEvent(EVENT_EXIT, "github"); - }} > { +interface Props { + langCode: Language["code"]; +} +interface State { + isLoading: boolean; +} +export class InitializeApp extends React.Component { public state: { isLoading: boolean } = { isLoading: true, }; async componentDidMount() { - await setLanguageFirstTime(); + const currentLang = + languages.find((lang) => lang.code === this.props.langCode) || + defaultLang; + await setLanguageFirstTime(currentLang); this.setState({ isLoading: false, }); diff --git a/src/components/LayerUI.tsx b/src/components/LayerUI.tsx index 5a806e829..fbd5fdee0 100644 --- a/src/components/LayerUI.tsx +++ b/src/components/LayerUI.tsx @@ -1,57 +1,46 @@ +import clsx from "clsx"; import React, { + RefObject, + useCallback, + useEffect, useRef, useState, - RefObject, - useEffect, - useCallback, } from "react"; -import { showSelectedShapeActions } from "../element"; -import { calculateScrollCenter, getSelectedElements } from "../scene"; -import { exportCanvas } from "../data"; - -import { AppState, LibraryItems, LibraryItem } from "../types"; -import { NonDeletedExcalidrawElement } from "../element/types"; - import { ActionManager } from "../actions/manager"; -import { Island } from "./Island"; -import Stack from "./Stack"; -import { FixedSideContainer } from "./FixedSideContainer"; -import { UserList } from "./UserList"; -import { LockIcon } from "./LockIcon"; -import { ExportDialog, ExportCB } from "./ExportDialog"; -import { LanguageList } from "./LanguageList"; -import { t, languages, setLanguage } from "../i18n"; -import { HintViewer } from "./HintViewer"; +import { CLASSES } from "../constants"; +import { exportCanvas } from "../data"; +import { importLibraryFromJSON, saveLibraryAsJSON } from "../data/json"; +import { Library } from "../data/library"; +import { showSelectedShapeActions } from "../element"; +import { NonDeletedExcalidrawElement } from "../element/types"; +import { Language, t } from "../i18n"; import useIsMobile from "../is-mobile"; - +import { calculateScrollCenter, getSelectedElements } from "../scene"; import { ExportType } from "../scene/types"; -import { MobileMenu } from "./MobileMenu"; -import { ZoomActions, SelectedShapeActions, ShapesSwitcher } from "./Actions"; -import { Section } from "./Section"; +import { AppState, LibraryItem, LibraryItems } from "../types"; +import { muteFSAbortError } from "../utils"; +import { SelectedShapeActions, ShapesSwitcher, ZoomActions } from "./Actions"; +import { BackgroundPickerAndDarkModeToggle } from "./BackgroundPickerAndDarkModeToggle"; import CollabButton from "./CollabButton"; import { ErrorDialog } from "./ErrorDialog"; -import { ShortcutsDialog } from "./ShortcutsDialog"; -import { LoadingMessage } from "./LoadingMessage"; -import { CLASSES } from "../constants"; -import { shield, exportFile, load } from "./icons"; +import { ExportCB, ExportDialog } from "./ExportDialog"; +import { FixedSideContainer } from "./FixedSideContainer"; import { GitHubCorner } from "./GitHubCorner"; -import { Tooltip } from "./Tooltip"; - +import { HintViewer } from "./HintViewer"; +import { exportFile, load, shield } from "./icons"; +import { Island } from "./Island"; import "./LayerUI.scss"; import { LibraryUnit } from "./LibraryUnit"; -import { ToolButton } from "./ToolButton"; -import { saveLibraryAsJSON, importLibraryFromJSON } from "../data/json"; -import { muteFSAbortError } from "../utils"; -import { BackgroundPickerAndDarkModeToggle } from "./BackgroundPickerAndDarkModeToggle"; -import clsx from "clsx"; -import { Library } from "../data/library"; -import { - EVENT_ACTION, - EVENT_EXIT, - EVENT_LIBRARY, - trackEvent, -} from "../analytics"; +import { LoadingMessage } from "./LoadingMessage"; +import { LockIcon } from "./LockIcon"; +import { MobileMenu } from "./MobileMenu"; import { PasteChartDialog } from "./PasteChartDialog"; +import { Section } from "./Section"; +import { ShortcutsDialog } from "./ShortcutsDialog"; +import Stack from "./Stack"; +import { ToolButton } from "./ToolButton"; +import { Tooltip } from "./Tooltip"; +import { UserList } from "./UserList"; interface LayerUIProps { actionManager: ActionManager; @@ -64,13 +53,14 @@ interface LayerUIProps { onInsertElements: (elements: readonly NonDeletedExcalidrawElement[]) => void; zenModeEnabled: boolean; toggleZenMode: () => void; - lng: string; + langCode: Language["code"]; isCollaborating: boolean; onExportToBackend?: ( exportedElements: readonly NonDeletedExcalidrawElement[], appState: AppState, canvas: HTMLCanvasElement | null, ) => void; + renderCustomFooter?: (isMobile: boolean) => JSX.Element; } const useOnClickOutside = ( @@ -159,13 +149,7 @@ const LibraryMenuItems = ({ }} /> - { - trackEvent(EVENT_EXIT, "libraries"); - }} - > + {t("labels.libraries")} , @@ -267,7 +251,6 @@ const LibraryMenu = ({ const items = await Library.loadLibrary(); const nextItems = items.filter((_, index) => index !== indexToRemove); Library.saveLibrary(nextItems); - trackEvent(EVENT_LIBRARY, "remove"); setLibraryItems(nextItems); }, []); @@ -276,7 +259,6 @@ const LibraryMenu = ({ const items = await Library.loadLibrary(); const nextItems = [...items, elements]; onAddToLibrary(); - trackEvent(EVENT_LIBRARY, "add"); Library.saveLibrary(nextItems); setLibraryItems(nextItems); }, @@ -316,6 +298,7 @@ const LayerUI = ({ toggleZenMode, isCollaborating, onExportToBackend, + renderCustomFooter, }: LayerUIProps) => { const isMobile = useIsMobile(); @@ -327,9 +310,6 @@ const LayerUI = ({ href="https://blog.excalidraw.com/end-to-end-encryption/" target="_blank" rel="noopener noreferrer" - onClick={() => { - trackEvent(EVENT_EXIT, "e2ee shield"); - }} > {shield} @@ -551,14 +531,7 @@ const LayerUI = ({ "transition-right disable-pointerEvents": zenModeEnabled, })} > - { - await setLanguage(lng); - setAppState({}); - }} - languages={languages} - floating - /> + {renderCustomFooter?.(false)} {actionManager.renderAction("toggleShortcuts")}