diff --git a/.babelrc b/.babelrc index 93be46583..b2f5cd96d 100644 --- a/.babelrc +++ b/.babelrc @@ -2,7 +2,8 @@ "presets": [ ["@babel/preset-env", { "modules": "umd", - "useBuiltIns": "entry" + "useBuiltIns": "entry", + "corejs": 3 }] ], "plugins": [ diff --git a/.editorconfig b/.editorconfig index 0915b6398..0665d09b8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,4 +6,4 @@ indent_style = space indent_size = 2 end_of_line = lf insert_final_newline = true -trim_trailing_whitespace = true \ No newline at end of file +trim_trailing_whitespace = true diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..54958dac1 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,4 @@ +node_modules +*.d.ts +src/components/tools/paragraph +src/polyfills.ts diff --git a/.eslintrc b/.eslintrc index 2f369b0cf..3e2802ace 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,92 +1,47 @@ { - /** Enable ES6 features */ - "parserOptions": { - "ecmaVersion": 2017, - "sourceType": "module" - }, - "rules": { - - "arrow-spacing": [2, { - "before": true, - "after": true - }], - - /** Variables */ - "no-catch-shadow": 2, - "no-delete-var": 2, - "no-label-var": 2, - "no-shadow-restricted-names": 2, - "no-shadow": 2, - "no-undef-init": 2, - "no-undef": 2, - "no-unused-vars": 0, - - /** Style */ - "array-bracket-spacing": [2, "never", { - "singleValue": true, - "objectsInArrays": true, - "arraysInArrays": true - }], - "quotes": [2, "single", { - "avoidEscape": true, - "allowTemplateLiterals": true - }], - "eqeqeq": 0, - "brace-style": [2, "1tbs"], - "comma-spacing": [2, { - "before": false, - "after": true - }], - "comma-style": [2, "last"], - "eol-last": 0, - "no-nested-ternary": 1, - "no-trailing-spaces": 2, - "no-mixed-spaces-and-tabs": 2, - "padded-blocks": [2, "never"], - "space-before-blocks": 1, - "space-before-function-paren": [1, { - "anonymous": "always", - "named": "never" - }], - "spaced-comment": [2, "always", { - "exceptions": ["-", "+"], - "markers": ["=", "!"] - }], - "semi": [2, "always"], - "indent": [2, 2, { - "SwitchCase": 1 - }], - "camelcase": [2, { - "properties": "always" - }], - "newline-after-var": [1, "always"] - - }, - "globals":{ - "document": true, - "module": true, - "require": true, - "window": true, - "console" : true, - "codex": true, - "VERSION" : true, - "Promise" : true, - "MutationObserver": true, - "FormData": true, - "XMLHttpRequest": true, - "ActiveXObject": true, - "RegExp": true, - "Module": true, - "Node": true, - "Element": true, - "DocumentFragment": true, - "Proxy": true, - "Symbol": true, - "$": true, - "_": true, - "setTimeout": true, - "process": true, - "__dirname": true, - "Map": true + "extends": [ + "codex" + ], + "rules": { + /** + * Temporary suppress some errors. We need to fix them partially in next patches + */ + "import/no-duplicates": ["warn"], + "@typescript-eslint/triple-slash-reference": ["off"] + }, + "settings": { + "jsdoc": { + "mode": "typescript" } + }, + "globals": { + "Node": true, + "Range": true, + "HTMLElement": true, + "HTMLDivElement": true, + "Element": true, + "Selection": true, + "SVGElement": true, + "Text": true, + "InsertPosition": true, + "PropertyKey": true, + "MouseEvent": true, + "TouchEvent": true, + "KeyboardEvent": true, + "ClipboardEvent": true, + "DragEvent": true, + "Event": true, + "EventTarget": true, + "Document": true, + "NodeList": true, + "File": true, + "FileList": true, + "MutationRecord": true, + "AddEventListenerOptions": true, + "DataTransfer": true, + "DOMRect": true, + "ClientRect": true, + "ArrayLike": true, + "unknown": true + } } diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..971aed277 --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at team@codex.so. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..78639a6ca --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,5 @@ +# These are supported funding model platforms + +github: neSpecc +patreon: editorjs +open_collective: editorjs diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..f8df3f874 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,30 @@ +--- +name: Bug report +about: Create a report to help us improve Editor.js +title: "[Bug]" +labels: bug +assignees: '' + +--- + +Describe a bug. + +Steps to reproduce: +1. Go to … +2. Click on … +3. … + +Expected behavior: + +Screenshots: + +Device, Browser, OS: + +Editor.js version: + +Plugins you use with their versions: + + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..40a9197f0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: Team + url: mailto:team@codex.so + about: Direct team contact. + - name: Editor.js Telegram chat + url: https://t.me/codex_editor + about: Telegram chat for Editor.js users communication. + - name: Editor.js contributors Telegram chat + url: https://t.me/editorjsdev + about: Telegram chat for Editor.js contributors communication. diff --git a/.github/ISSUE_TEMPLATE/discussion.md b/.github/ISSUE_TEMPLATE/discussion.md new file mode 100644 index 000000000..f6f6a3ed3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/discussion.md @@ -0,0 +1,17 @@ +--- +name: Discussion +about: Any question about the Editor.js to discuss +title: '' +labels: discussion +assignees: '' + +--- + +The question. + +Why and how the question has come up. + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..6069bf434 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,19 @@ +--- +name: Feature request +about: Suggest an idea to improve Editor.js +title: "\U0001F4A1" +labels: feature +assignees: '' + +--- + +1. Describe a problem. + +2. Describe the solution you'd like. Mockups are welcome. + +3. Are there any alternatives? + + diff --git a/.github/ISSUE_TEMPLATE/issue--discussion.md b/.github/ISSUE_TEMPLATE/issue--discussion.md new file mode 100644 index 000000000..00261395d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue--discussion.md @@ -0,0 +1,24 @@ +--- +name: 'Issue: Discussion' +about: Any question about the project to discuss +title: "❓" +labels: discussion +assignees: '' + +--- + +**Question** + +A clear and consistent question about the project. Ex. How can I do smth? Why smth works this way? etc. + +**Context** + +Why and how the question has come up + +**Related issues** + +If there are related issues which describe a bugs or features, put them here + +**Comments** + +Any thoughts about the question diff --git a/.github/workflows/bump-version-on-merge-next.yml b/.github/workflows/bump-version-on-merge-next.yml new file mode 100644 index 000000000..d1e94ea01 --- /dev/null +++ b/.github/workflows/bump-version-on-merge-next.yml @@ -0,0 +1,77 @@ +name: Bump version on merge + +on: + pull_request: + branches: + - next + types: [closed] + +jobs: + # If pull request was merged then we should check for a package version update + check-for-no-version-changing: + if: github.event.pull_request.merged == true + runs-on: ubuntu-latest + steps: + # Checkout to target branch + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + # Get package new version name + - name: Get package info + id: packageNew + uses: codex-team/action-nodejs-package-info@v1 + + # Checkout to the base commit before merge + - name: Checkout to the base commit before merge + run: git checkout ${{ github.event.pull_request.base.sha }} + + # Get package old version name + - name: Get package info + id: packageOld + uses: codex-team/action-nodejs-package-info@v1 + + # Stop workflow and do not bump version if it was changed already + - name: Stop workflow and do not bump version if it was changed already + uses: actions/github-script@v3 + if: steps.packageOld.outputs.version != steps.packageNew.outputs.version + with: + script: | + core.setFailed('Version was changed! ${{ steps.packageOld.outputs.version }} -> ${{ steps.packageNew.outputs.version }}') + + bump-version: + needs: check-for-no-version-changing + runs-on: ubuntu-latest + steps: + # Checkout to target branch + - uses: actions/checkout@v2 + + # Setup node environment + - uses: actions/setup-node@v1 + with: + node-version: 15 + registry-url: https://registry.npmjs.org/ + + # Bump version to the next prerelease (patch) with rc suffix + - name: Suggest the new version + run: yarn version --prerelease --preid rc --no-git-tag-version + + # Get package new version name + - name: Get package info + id: package + uses: codex-team/action-nodejs-package-info@v1 + + # Create pull request with changes + - name: Create Pull Request + uses: peter-evans/create-pull-request@v3 + with: + commit-message: Bump version + committer: github-actions + author: github-actions + branch: auto-bump-version + base: ${{ steps.vars.outputs.base_branch }} + delete-branch: true + title: "Bump version up to ${{ steps.package.outputs.version }}" + body: | + Auto-generated bump version suggestion because of PR: + **${{ github.event.pull_request.title }}** #${{ github.event.pull_request.number }} diff --git a/.github/workflows/create-a-release-draft.yml b/.github/workflows/create-a-release-draft.yml new file mode 100644 index 000000000..65c46c561 --- /dev/null +++ b/.github/workflows/create-a-release-draft.yml @@ -0,0 +1,108 @@ +name: Create a release draft + +on: + pull_request: + branches: + - next + types: [closed] + +jobs: + # If pull request was merged then we should check for a package version update + check-version-changing: + if: github.event.pull_request.merged == true + runs-on: ubuntu-latest + steps: + # Checkout to target branch + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + # Get package new version name + - name: Get package info + id: packageNew + uses: codex-team/action-nodejs-package-info@v1 + + # Checkout to the base commit before merge + - name: Checkout to the base commit before merge + run: git checkout ${{ github.event.pull_request.base.sha }} + + # Get package old version name + - name: Get package info + id: packageOld + uses: codex-team/action-nodejs-package-info@v1 + + # Stop workflow if version was not changed + - name: Stop workflow if version was not changed + uses: actions/github-script@v3 + if: steps.packageOld.outputs.version == steps.packageNew.outputs.version + with: + script: | + core.setFailed('No version changes. ${{ steps.packageOld.outputs.version }}') + + # Create a new draft release + release-draft: + needs: check-version-changing + runs-on: ubuntu-latest + steps: + # Checkout to target branch + - uses: actions/checkout@v2 + with: + # Pull submodules + submodules: 'recursive' + + # Setup node environment + - uses: actions/setup-node@v1 + with: + node-version: 15 + registry-url: https://registry.npmjs.org/ + + # Prepare, build and publish project + - name: Install dependencies + run: yarn + + # Build Editor.js + - name: Build output files + run: yarn build + + # Get package version name + - name: Get package info + id: package + uses: codex-team/action-nodejs-package-info@v1 + + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: v${{ steps.package.outputs.version }} + release_name: v${{ steps.package.outputs.version }} + + # Fill release description from pull request body name + body: "${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }}" + + # Save as a draft release + draft: true + + # If version name contains "-rc" suffix than mark a "pre-release" checkbox + prerelease: ${{ contains(steps.package.outputs.version, '-rc') }} + + # Build and upload target Editor.js build to release as artifact + - name: Upload Release Asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: dist/editor.js + asset_name: editor.js + asset_content_type: application/javascript + + # Send a notification message + - name: Send a message + uses: codex-team/action-codexbot-notify@v1 + with: + webhook: ${{ secrets.CODEX_BOT_WEBHOOK_FRONTEND }} + message: '🦥 [Draft release v${{ steps.package.outputs.version }}](${{ steps.create_release.outputs.html_url }}) for package [${{ steps.package.outputs.name }}](${{ steps.package.outputs.npmjs-link }}) has been created. Add changelog and publish it!' + parse_mode: 'markdown' + disable_web_page_preview: true diff --git a/.github/workflows/eslint.yml b/.github/workflows/eslint.yml new file mode 100644 index 000000000..052c68355 --- /dev/null +++ b/.github/workflows/eslint.yml @@ -0,0 +1,24 @@ +name: ESLint CodeX + +on: [pull_request] + +jobs: + lint: + name: ESlint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Cache node modules + uses: actions/cache@v1 + with: + path: node_modules + key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.OS }}-build-${{ env.cache-name }}- + ${{ runner.OS }}-build- + ${{ runner.OS }}- + + - run: yarn install + + - run: yarn lint diff --git a/.github/workflows/publish-package-to-npm.yml b/.github/workflows/publish-package-to-npm.yml new file mode 100644 index 000000000..008c90f75 --- /dev/null +++ b/.github/workflows/publish-package-to-npm.yml @@ -0,0 +1,53 @@ +name: Publish package to NPM + +on: + release: + types: + - published + +jobs: + publish: + runs-on: ubuntu-latest + steps: + # Checkout to target branch + - uses: actions/checkout@v2 + with: + # Pull submodules + submodules: 'recursive' + + # Setup node environment + - uses: actions/setup-node@v1 + with: + node-version: 15 + registry-url: https://registry.npmjs.org/ + + # Prepare, build and publish project + - name: Install dependencies + run: yarn + + - name: Build output files + run: yarn build + + - name: Publish the package + run: yarn publish --access=public ${{ github.event.release.prerelease && '--tag=next' || '--tag=latest' }} + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + notify: + needs: publish + runs-on: ubuntu-latest + steps: + # Checkout to target branch + - uses: actions/checkout@v2 + + - name: Get package info + id: package + uses: codex-team/action-nodejs-package-info@v1 + + - name: Send a message + uses: codex-team/action-codexbot-notify@v1 + with: + webhook: ${{ secrets.CODEX_BOT_NOTIFY_EDITORJS_PUBLIC_CHAT }} + message: '📦 [${{ steps.package.outputs.name }}](${{ steps.package.outputs.npmjs-link }}) ${{ steps.package.outputs.version }} was published' + parse_mode: 'markdown' + disable_web_page_preview: true diff --git a/.gitignore b/.gitignore index 729389616..52c29337a 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,8 @@ node_modules/* npm-debug.log yarn-error.log + +test/cypress/screenshots +test/cypress/videos + +dist/ diff --git a/.gitmodules b/.gitmodules index b4064182e..8e40c5e63 100644 --- a/.gitmodules +++ b/.gitmodules @@ -46,3 +46,6 @@ [submodule "example/tools/warning"] path = example/tools/warning url = https://github.com/editor-js/warning +[submodule "example/tools/underline"] + path = example/tools/underline + url = https://github.com/editor-js/underline diff --git a/.npmignore b/.npmignore index 7b5bf0a85..c00f2cbbb 100644 --- a/.npmignore +++ b/.npmignore @@ -1,17 +1,20 @@ -.idea/ -build/sprite.svg -docs/ -example/ -src/ +.idea +.github +docs +example +src +test .babelrc .editorconfig +.eslintignore .eslintrc .git .gitmodules .jshintrc -.postcssrc +.postcssrc.yml .stylelintrc CODEOWNERS +cypress.json tsconfig.json tslint.json webpack.config.js diff --git a/CODEOWNERS b/CODEOWNERS index 70de4fd1f..aaa5e0be6 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1 @@ -* @neSpecc @gohabereg @khaydarov @talyguryn +* @neSpecc @gohabereg @khaydarov diff --git a/LICENSE b/LICENSE index b0fcab8dd..cbea25181 100644 --- a/LICENSE +++ b/LICENSE @@ -175,7 +175,7 @@ END OF TERMS AND CONDITIONS - Copyright © 2015-2018 CodeX + Copyright © 2015-present CodeX Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 44a994922..a3e24b55d 100644 --- a/README.md +++ b/README.md @@ -1,103 +1,87 @@ -

+

[![](https://flat.badgen.net/npm/v/@editorjs/editorjs?icon=npm)](https://www.npmjs.com/package/@editorjs/editorjs) [![](https://flat.badgen.net/bundlephobia/min/@editorjs/editorjs?color=cyan)](https://www.npmjs.com/package/@editorjs/editorjs) [![](https://flat.badgen.net/bundlephobia/minzip/@editorjs/editorjs?color=green)](https://www.npmjs.com/package/@editorjs/editorjs) -[![](https://flat.badgen.net/npm/license/@editorjs/editorjs)](https://www.npmjs.com/package/@editorjs/editorjs) +[![Backers on Open Collective](https://opencollective.com/editorjs/backers/badge.svg)](#backers) +[![Sponsors on Open Collective](https://opencollective.com/editorjs/sponsors/badge.svg)](#sponsors) +[![](https://img.shields.io/npm/l/@editorjs/editorjs?style=flat-square)](https://www.npmjs.com/package/@editorjs/editorjs) [![Join the chat at https://gitter.im/codex-team/editor.js](https://badges.gitter.im/codex-team/editor.js.svg)](https://gitter.im/codex-team/editor.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -## Version 2.0 is here! +| [IE / Edge](http://godban.github.io/browsers-support-badges/)
IE / Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | [iOS Safari](http://godban.github.io/browsers-support-badges/)
iOS Safari | [Opera](http://godban.github.io/browsers-support-badges/)
Opera | +| --------- | --------- | --------- | --------- | --------- | --------- | +| Edge 12+ | Firefox 18+ | Chrome 49+ | Safari 10+ | Safari 10+ | Opera 36+ -We are glad to introduce the next version of Editor.js. Totally new core, structure and plugins — that was an impressive adventure 🤓. +## If you like a project 💗💗💗 -Join [public Telegram-chat](//t.me/codex_editor) or [Gitter-channel](https://gitter.im/codex-team/editor.js) where you can always find a support. +If you like Editor.js you can support project improvements and development of new features with a donation to our collective. -### Browsers support + 👉 [https://opencollective.com/editorjs](https://opencollective.com/editorjs) -| [IE / Edge](http://godban.github.io/browsers-support-badges/)
IE / Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | [iOS Safari](http://godban.github.io/browsers-support-badges/)
iOS Safari | [Opera](http://godban.github.io/browsers-support-badges/)
Opera | -| --------- | --------- | --------- | --------- | --------- | --------- | -| Edge 12+ | Firefox 18+ | Chrome 49+ | Safari 10+ | Safari 10+ | Opera 36+ +### Sponsors + +Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/editorjs#sponsor)] + + + + ### Backers + + Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/editorjs#backer)] + + + +### Contributors -### 2.7-2.9 changelog - -- `Fix` - Clear focus when click is outside the Editor instance -- `Fix` — Fix CMD+A Selection on multiple Editor instances -- `New` — Toolbox now have beautiful helpers with Tool names and shortcuts -- `Improvements` — Prevent navigating back on Firefox when Block is removing by backspace -- `New` — Blocks selected with Rectangle Selection can be also removed, copied or cut -- `New` — Migrate from `postcss-cssnext` to `postcss-preset-env` and disable `postcss-custom-properties` which conflicts with `postcss-preset-env` -- `New` *RectangeSelection* — Ability to select Block or several Blocks with mouse - -### 2.2—2.7 changelog - -- `New` *Sanitize API* — [Sanitize Config](https://github.com/codex-team/editor.js/blob/master/docs/tools.md#automatic-sanitize) of `Block Tools` now automatically extends by tags of `Inline Tools` that is enabled by current Tool by `inlineToolbar` option. You don't need more to specify `a, b, mark, code` manually. This feature will be added to fields that supports inline markup. -- `New` *Block Selection* — Ability to select Block by `CMD+A`, and the whole Editor by double `CMD+A`. After that, you can copy (`CMD+C`), remove (`Backspace`) or clear (`Enter`) selected Blocks. -- `New` *[Styles API](https://github.com/codex-team/editor.js/blob/master/types/api/styles.d.ts)* — Added `button` class for stylization of any buttons provided by Tools with one unified style. -- `New` *[Notifier API](https://github.com/codex-team/editor.js/blob/master/docs/api.md#notifierapi)* — methods for showing user notifications: on success, errors, warnings, etc. -- `New` *Block Tool* — [Table](http://github.com/editor-js/table) constructor 💪 -- `New` If one of the Tools is unavailable on Editor initialization, its Blocks will be rendered with *Dummy Block*, describing that user can not edit content of this Block. Dummy Blocks can be moved, removed and saved as normal Blocks. So saved data won't be lost if one of the Tools is failed -- `New` [Public TS-types](https://github.com/codex-team/editor.js/tree/master/types) are presented. -- `Changes` *Tools API* — options `irreplaceable` and `contentless` was removed. -- `Changes` *Tools API* — [Paste API](https://github.com/codex-team/editor.js/blob/master/docs/tools.md#paste-handling): tags, patterns and mime-types now should be specified by Tool's `pasteConfig` static property. Custom Paste Event should be handled by `onPaste(event)` that should not be static from now. -- `Changes` *Tools API* — options `displayInToolbox ` and `toolboxIcon` was removed. Use [`toolbox`](https://github.com/codex-team/editor.js/blob/master/docs/tools.md#internal-tool-settings) instead, that should return object with `icon` and `title` field, or `false` if Tool should not be placed at the Toolbox. Also, there are a way to override `toolbox {icon, title}` settings provided by Tool with you own settings at the Initial Config. -- `Improvements` — All Projects code now on TypeScript -- `Improvements` — NPM package size decreased from 1300kb to 422kb -- `Improvements` — Bundle size decreased from 438kb to 252kb -- `Improvements` — `Inline Toolbar`: when you add a Link to the selected fragment, Editor will highlight this fragment even when Caret is placed into the URL-input. -- `Improvements` — Block Settings won't be shown near empty Blocks of `initialType` by default. You should click on them instead. -- `Improvements` — `onChange`-callback now will be fired even with children attributes changing. -- `Improvements` — HTMLJanitor package was updated due to found vulnerability -- `Improvements` — Logging improved: now all Editor's logs will be preceded by beautiful label with current Editor version. -- `Improvements` — Internal `isEmpty` checking was improved for Blocks with many children nodes (200 and more) -- `Improvements` — Paste improvements: tags that can be substituted by Tool now will matched even on deep-level of pasted DOM three. -- `Improvements` — There is no more «unavailable» sound on copying Block by `CMD+C` on macOS -- `Improvements` — Dozens of bugfixes and small improvements - -See a whole [Changelog](/docs/CHANGELOG.md) +This project exists thanks to all the people who contribute. + +We really welcome new contributors. If you want to make some code with us, please take a look at the [Good First Tasks](https://github.com/codex-team/editor.js/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+task%22). You can write to us on `team@codex.so` or via special [Telegram chat](https://t.me/editorjsdev), or any other way. ## Documentation -While we develop the new Documentation Site with all stuff, you can check some available docs at the [docs/](docs/) dir. +Please visit [https://editorjs.io/](https://editorjs.io) to view all documentation articles. + +- [Base concepts](https://editorjs.io/base-concepts) +- [Getting started](https://editorjs.io/getting-started) +- [Configuration](https://editorjs.io/configuration) +- [How to create a Block Tool Plugin](https://editorjs.io/creating-a-block-tool) +- [How to create an Inline Tool Plugin](https://editorjs.io/creating-an-inline-tool) +- [API for Tools](https://editorjs.io/tools-api) -- [Installation](docs/installation.md) -- [How to use](docs/usage.md) -- [How to create a Block Tool Plugin](docs/tools.md) -- [How to create an Inline Tool Plugin](docs/tools-inline.md) -- [API for Tools](docs/api.md) +You can join a [Gitter-channel](https://gitter.im/codex-team/editor.js) or [Telegram-chat](//t.me/codex_editor) and ask a question. -Sorry if we missed something. You can join a [Telegram-chat](//t.me/codex_editor) and ask a question. +## Changelog ---- +See the whole [Changelog](/docs/CHANGELOG.md) -# So how to use Editor.js +## How to use Editor.js -## Basics +### Basics Editor.js is a Block-Styled editor. Blocks are structural units, of which the Entry is composed. For example, `Paragraph`, `Heading`, `Image`, `Video`, `List` are Blocks. Each Block is represented by Plugin. -We have [many](http://github.com/editor-js/) ready-to-use Plugins and the [simple API](docs/tools.md) for creation new ones. +We have [many](http://github.com/editor-js/) ready-to-use Plugins and a [simple API](https://editorjs.io/tools-api) for creating new ones. -So how to use the Editor after [Installation](docs/installation.md). +How to use the Editor after [Installation](https://editorjs.io/getting-started). -- Create new Blocks by Enter or with the Plus Button +- Create new Blocks by pressing Enter or clicking the Plus Button - Press `TAB` or click on the Plus Button to view the Toolbox - Press `TAB` again to leaf Toolbox and select a Block you need. Then press Enter. ![](https://github.com/editor-js/list/raw/master/assets/example.gif) -- Select text fragment and apply a style or insert a link from the Inline Toolbar +- Select a text fragment and apply a style or insert a link from the Inline Toolbar ![](https://capella.pics/7ccbcfcd-1c49-4674-bea7-71021468a1bd.jpg) -- Use «three-dots» button on the right to open Block Settings. From here, you can move and delete a Block -or apply Tool's settings, if it provided. For example, set a Heading level or List style. +- Use the «three-dots» button on the right to open Block Settings. From here, you can move and delete a Block +or apply a Tool's settings, if it provided. For example, you can set a Heading level or List style. ![](https://capella.pics/01a55381-46cd-47c7-b92e-34765434f2ca.jpg) -## Shortcuts +### Shortcuts -We really appreciate shortcuts. So there are few presets. +A few shortcuts are preset as available. Shortcut | Action | Restrictions -- | -- | -- @@ -108,10 +92,10 @@ Shortcut | Action | Restrictions `CMD+I` | Italic style | On selection `CMD+K` | Insert a link | On selection -Also we support shortcuts on the all type of Tools. Specify a shortcut with the Tools configuration. For example: +Each Tool can also have its own shortcuts. These are specified in the configuration of the Tool, for example: ```js -var editor = EditorJS({ +var editor = new EditorJS({ //... tools: { header: { @@ -129,7 +113,7 @@ var editor = EditorJS({ ``` -# Installation Guide +## Installation Guide There are few steps to run Editor.js on your site. @@ -137,59 +121,50 @@ There are few steps to run Editor.js on your site. 2. [Load Tools](#load-tools) 3. [Initialize Editor's instance](#create-editor-instance) -## Load Editor's core +### Step 1. Load Editor's core -Firstly you need to get Editor.js itself. It is a [minified script](build/editor.js) with Editor's core and some default must-have tools. +Get Editor.js itself. It is a [minified script](dist/editor.js) with Editor's core and some default must-have tools. Choose the most usable method of getting Editor for you. - Node package - Source from CDN -- Local file from project -### Node.js +##### Option A. NPM install Install the package via NPM or Yarn ```shell -npm i @editorjs/editorjs --save-dev +npm i @editorjs/editorjs ``` Include module in your application ```javascript -const EditorJS = require('@editorjs/editorjs'); +import EditorJS from '@editorjs/editorjs'; ``` -### Use from CDN +##### Option B. Use a CDN -You can load specific version of package from [jsDelivr CDN](https://www.jsdelivr.com/package/npm/@editorjs/editorjs). +You can load EditorJS directly from from [jsDelivr CDN](https://www.jsdelivr.com/package/npm/@editorjs/editorjs). `https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest` -Then require this script. +For example, place this in your HTML: ```html - + ``` -### Save sources to project - -Copy [editor.js](build/editor.js) file to your project and load it. +Or download the bundle file and use it from your server. ```html ``` -## Load Tools +### Step 2. Load the Tools that you want to make available -Each Block at the Editor.js represented by [Tools](docs/tools.md). There are simple external scripts with own logic. Probably you want to use several Block Tools that should be connected. - -For example check out our [Header](https://github.com/editor-js/header) Tool that represents heading blocks. - -You can install Header Tool by the same way as the Editor (Node.js, CDN, local file). - -Check [Editor.js's community](https://github.com/editor-js/) to see more ready-to-use Tools. +Each Block is represented by a [Tool](docs/tools.md). Tools are simple external scripts with their own logic. For example, there is a [Header](https://github.com/editor-js/header) Tool into which you type your heading text. If you want to be able to use this, install the Header Tool the same way as the Editor (Node.js, CDN, local file). **Example:** use Header from CDN @@ -197,7 +172,9 @@ Check [Editor.js's community](https://github.com/editor-js/) to see more ready-t ``` -## Create Editor instance +Check [Editor.js's community](https://github.com/editor-js/) to see more ready-to-use Tools. + +### Step 3. Create Editor instance Create an instance of Editor.js and pass [Configuration Object](types/configs/editor-config.d.ts) with `holderId` and tools list. @@ -222,7 +199,7 @@ var editor = new EditorJS({ /** * Create a holder for the Editor and pass its ID */ - holderId : 'editorjs', + holder : 'editorjs', /** * Available Tools list. @@ -243,36 +220,31 @@ var editor = new EditorJS({ }); ``` -## Saving Data +### Saving Data -Call `editor.saver.save()` and handle returned Promise with saved data. +Call `editor.save()` and handle returned Promise with saved data. ```javascript -editor.saver.save() +editor.save() .then((savedData) => { console.log(savedData); }); ``` -## Example +### Example Take a look at the [example.html](example/example.html) to view more detailed examples. ## Credits and references -- We use [HTMLJanitor](https://github.com/guardian/html-janitor) module in our Sanitizer module. +- We use [HTMLJanitor](https://github.com/guardian/html-janitor) module in our Sanitizer module. -# About team +## About team -We are CodeX and we build products for developers and makers. +We are CodeX and we build products for developers and makers. Follow us on Twitter: [twitter.com/codex_team](https://twitter.com/codex_team) Feel free to contact: team@codex.so [codex.so](https://codex.so) - -# Support project improvements - -Love Editor.js? Please consider supporting our collective: - 👉 [https://opencollective.com/editorjs](https://opencollective.com/editorjs) diff --git a/cypress.json b/cypress.json new file mode 100644 index 000000000..732aea680 --- /dev/null +++ b/cypress.json @@ -0,0 +1,9 @@ +{ + "env": { + }, + "fixturesFolder": "test/cypress/fixtures", + "integrationFolder": "test/cypress/tests", + "screenshotsFolder": "test/cypress/screenshots", + "videosFolder": "test/cypress/videos", + "supportFile": "test/cypress/support/index.ts" +} diff --git a/dist/editor.js b/dist/editor.js deleted file mode 100644 index 5eafc9bb8..000000000 --- a/dist/editor.js +++ /dev/null @@ -1,45 +0,0 @@ -/*! - * Editor.js - * - * @version 2.12.3 - * - * @licence Apache-2.0 - * @author CodeX - * - * @uses html-janitor - * @licence Apache-2.0 (https://github.com/guardian/html-janitor/blob/master/LICENSE) - */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.EditorJS=e():t.EditorJS=e()}(window,function(){return function(t){var e={};function n(o){if(e[o])return e[o].exports;var r=e[o]={i:o,l:!1,exports:{}};return t[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=t,n.c=e,n.d=function(t,e,o){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)n.d(o,r,function(e){return t[e]}.bind(null,r));return o},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=159)}([function(t,e,n){var o=n(9),r=n(16),i=n(22),a=n(19),s=n(31),c=function(t,e,n){var u,l,f,d,p=t&c.F,h=t&c.G,v=t&c.S,g=t&c.P,y=t&c.B,b=h?o:v?o[e]||(o[e]={}):(o[e]||{}).prototype,m=h?r:r[e]||(r[e]={}),k=m.prototype||(m.prototype={});for(u in h&&(n=e),n)f=((l=!p&&b&&void 0!==b[u])?b:n)[u],d=y&&l?s(f,o):g&&"function"==typeof f?s(Function.call,f):f,b&&a(b,u,f,t&c.U),m[u]!=f&&i(m,u,d),g&&k[u]!=f&&(k[u]=f)};o.core=r,c.F=1,c.G=2,c.S=4,c.P=8,c.B=16,c.W=32,c.U=64,c.R=128,t.exports=c},function(t,e){t.exports=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}},function(t,e){function n(t,e){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:null,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=document.createElement(t);for(var a in Array.isArray(n)?(e=r.classList).add.apply(e,(0,i.default)(n)):n&&r.classList.add(n),o)o.hasOwnProperty(a)&&(r[a]=o[a]);return r}},{key:"text",value:function(t){return document.createTextNode(t)}},{key:"svg",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:14,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:14,o=document.createElementNS("http://www.w3.org/2000/svg","svg");return o.classList.add("icon","icon--"+t),o.setAttribute("width",e+"px"),o.setAttribute("height",n+"px"),o.innerHTML=''),o}},{key:"append",value:function(t,e){Array.isArray(e)?e.forEach(function(e){return t.appendChild(e)}):t.appendChild(e)}},{key:"prepend",value:function(t,e){Array.isArray(e)?(e=e.reverse()).forEach(function(e){return t.prepend(e)}):t.prepend(e)}},{key:"swap",value:function(t,e){var n=document.createElement("div"),o=t.parentNode;o.insertBefore(n,t),o.insertBefore(t,e),o.insertBefore(e,n),o.removeChild(n)}},{key:"find",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:document,e=arguments.length>1?arguments[1]:void 0;return t.querySelector(e)}},{key:"get",value:function(t){return document.getElementById(t)}},{key:"findAll",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:document,e=arguments.length>1?arguments[1]:void 0;return t.querySelectorAll(e)}},{key:"getDeepestNode",value:function(e){var n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],o=n?"lastChild":"firstChild",r=n?"previousSibling":"nextSibling";if(e&&e.nodeType===Node.ELEMENT_NODE&&e[o]){var i=e[o];if(t.isSingleTag(i)&&!t.isNativeInput(i)&&!t.isLineBreakTag(i))if(i[r])i=i[r];else{if(!i.parentNode[r])return i.parentNode;i=i.parentNode[r]}return this.getDeepestNode(i,n)}return e}},{key:"isElement",value:function(t){return t&&"object"===(0,r.default)(t)&&t.nodeType&&t.nodeType===Node.ELEMENT_NODE}},{key:"isFragment",value:function(t){return t&&"object"===(0,r.default)(t)&&t.nodeType&&t.nodeType===Node.DOCUMENT_FRAGMENT_NODE}},{key:"isContentEditable",value:function(t){return"true"===t.contentEditable}},{key:"isNativeInput",value:function(t){return!(!t||!t.tagName)&&["INPUT","TEXTAREA"].includes(t.tagName)}},{key:"canSetCaret",value:function(e){var n=!0;if(t.isNativeInput(e)){var o=e;switch(o.type){case"file":case"checkbox":case"radio":case"hidden":case"submit":case"button":case"image":case"reset":n=!1}}else n=t.isContentEditable(e);return n}},{key:"isNodeEmpty",value:function(t){return!(this.isSingleTag(t)&&!this.isLineBreakTag(t))&&0===(this.isElement(t)&&this.isNativeInput(t)?t.value:t.textContent.replace("​","")).trim().length}},{key:"isLeaf",value:function(t){return!!t&&0===t.childNodes.length}},{key:"isEmpty",value:function(t){var e=this,n=[],o=[];if(!t)return!0;if(!t.childNodes.length)return this.isNodeEmpty(t);for(n.push(t.firstChild);n.length>0;)if(t=n.shift()){for(this.isLeaf(t)?o.push(t):n.push(t.firstChild);t&&t.nextSibling;)(t=t.nextSibling)&&n.push(t);if(t&&!this.isNodeEmpty(t))return!1}return o.every(function(t){return e.isNodeEmpty(t)})}},{key:"isHTMLString",value:function(e){var n=t.make("div");return n.innerHTML=e,n.childElementCount>0}},{key:"getContentLength",value:function(e){return t.isNativeInput(e)?e.value.length:e.nodeType===Node.TEXT_NODE?e.length:e.textContent.length}},{key:"containsOnlyInlineElements",value:function(e){var n;return"string"==typeof e?(n=document.createElement("div")).innerHTML=e:n=e,Array.from(n.children).every(function e(n){return!t.blockElements.includes(n.tagName.toLowerCase())&&Array.from(n.children).every(e)})}},{key:"getDeepestBlockElements",value:function(e){return t.containsOnlyInlineElements(e)?[e]:Array.from(e.children).reduce(function(e,n){return[].concat((0,i.default)(e),(0,i.default)(t.getDeepestBlockElements(n)))},[])}},{key:"blockElements",get:function(){return["address","article","aside","blockquote","canvas","div","dl","dt","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","li","main","nav","noscript","ol","output","p","pre","ruby","section","table","tr","tfoot","ul","video"]}}]),t}();o.default=u,u.displayName="Dom",t.exports=e.default})?o.apply(e,r):o)||(t.exports=i)},function(t,e,n){var o=n(11),r=n(99),i=n(38),a=Object.defineProperty;e.f=n(15)?Object.defineProperty:function(t,e,n){if(o(t),e=i(e,!0),o(n),r)try{return a(t,e,n)}catch(t){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(t[e]=n.value),t}},function(t,e,n){t.exports=!n(8)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(t,e){var n=t.exports={version:"2.5.7"};"number"==typeof __e&&(__e=n)},function(t,e,n){var o=n(35),r=Math.min;t.exports=function(t){return t>0?r(o(t),9007199254740991):0}},function(t,e,n){var o,r,i;r=[e,n(338),n(48),n(29),n(30),n(1),n(2),n(13)],void 0===(i="function"==typeof(o=function(o,r,i,a,s,c,u,l){"use strict";var f=n(3);Object.defineProperty(o,"__esModule",{value:!0}),o.default=void 0,r=f(r),i=f(i),a=f(a),s=f(s),c=f(c),u=f(u),l=f(l);var d=function(){function t(){(0,c.default)(this,t)}var e;return(0,u.default)(t,null,[{key:"log",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"log",n=arguments.length>2?arguments[2]:void 0,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"color: inherit";if("console"in window&&window.console[e]){var r="Editor.js ".concat("2.12.3"),i="line-height: 1em;\n color: #006FEA;\n display: inline-block;\n font-size: 11px;\n line-height: 1em;\n background-color: #fff;\n padding: 4px 9px;\n border-radius: 30px;\n border: 1px solid rgba(56, 138, 229, 0.16);\n margin: 4px 5px 4px 0;";try{["time","timeEnd"].includes(e)?console[e]("( ".concat(r," ) ").concat(t)):n?console[e]("%c".concat(r,"%c ").concat(t," %o"),i,o,n):console[e]("%c".concat(r,"%c ").concat(t),i,o)}catch(t){}}}},{key:"sequence",value:(e=(0,s.default)(a.default.mark(function t(e){var n,o,r,i,c=arguments;return a.default.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return i=function(){return(i=(0,s.default)(a.default.mark(function t(e,n,o){return a.default.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.prev=0,t.next=3,e.function(e.data);case 3:return t.next=5,n(void 0!==e.data?e.data:{});case 5:t.next=10;break;case 7:t.prev=7,t.t0=t.catch(0),o(void 0!==e.data?e.data:{});case 10:case"end":return t.stop()}},t,null,[[0,7]])}))).apply(this,arguments)},r=function(t,e,n){return i.apply(this,arguments)},n=c.length>1&&void 0!==c[1]?c[1]:function(){},o=c.length>2&&void 0!==c[2]?c[2]:function(){},t.next=6,e.reduce(function(){var t=(0,s.default)(a.default.mark(function t(e,i){return a.default.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,e;case 2:return t.abrupt("return",r(i,n,o));case 3:case"end":return t.stop()}},t)}));return function(e,n){return t.apply(this,arguments)}}(),Promise.resolve());case 6:return t.abrupt("return",t.sent);case 7:case"end":return t.stop()}},t)})),function(t){return e.apply(this,arguments)})},{key:"array",value:function(t){return Array.prototype.slice.call(t)}},{key:"isFunction",value:function(t){return"function"==typeof t}},{key:"isClass",value:function(t){return"function"==typeof t&&/^\s*class\s+/.test(t.toString())}},{key:"isEmpty",value:function(t){return!t||0===Object.keys(t).length&&t.constructor===Object}},{key:"isPromise",value:function(t){return Promise.resolve(t)===t}},{key:"delay",value:function(t,e){return function(){var n=this,o=arguments;window.setTimeout(function(){return t.apply(n,o)},e)}}},{key:"getFileExtension",value:function(t){return t.name.split(".").pop()}},{key:"isValidMimeType",value:function(t){return/^[-\w]+\/([-+\w]+|\*)$/.test(t)}},{key:"debounce",value:function(t,e,n){var o,r=this,i=arguments;return function(){var a=r,s=i,c=n&&!o;window.clearTimeout(o),o=window.setTimeout(function(){o=null,n||t.apply(a,s)},e),c&&t.apply(a,s)}}},{key:"copyTextToClipboard",value:function(t){var e=l.default.make("div","codex-editor-clipboard",{innerHTML:t});document.body.appendChild(e);var n=window.getSelection(),o=document.createRange();o.selectNode(e),window.getSelection().removeAllRanges(),n.addRange(o),document.execCommand("copy"),document.body.removeChild(e)}},{key:"getUserOS",value:function(){var t={win:!1,mac:!1,x11:!1,linux:!1},e=Object.keys(t).find(function(t){return-1!==navigator.appVersion.toLowerCase().indexOf(t)});return e?(t[e]=!0,t):t}},{key:"capitalize",value:function(t){return t[0].toUpperCase()+t.slice(1)}},{key:"deepMerge",value:function(e){for(var n=function(t){return t&&"object"===(0,i.default)(t)&&!Array.isArray(t)},o=arguments.length,a=new Array(o>1?o-1:0),s=1;s"+r+""};t.exports=function(t,e){var n={};n[t]=e(s),o(o.P+o.F*r(function(){var e=""[t]('"');return e!==e.toLowerCase()||e.split('"').length>3}),"String",n)}},function(t,e){var n={}.hasOwnProperty;t.exports=function(t,e){return n.call(t,e)}},function(t,e,n){var o=n(14),r=n(40);t.exports=n(15)?function(t,e,n){return o.f(t,e,r(1,n))}:function(t,e,n){return t[e]=n,t}},function(t,e,n){var o=n(56),r=n(34);t.exports=function(t){return o(r(t))}},function(t,e,n){var o=n(34);t.exports=function(t){return Object(o(t))}},function(t,e,n){"use strict";var o=n(8);t.exports=function(t,e){return!!t&&o(function(){e?t.call(null,function(){},1):t.call(null)})}},function(t,e,n){var o=n(57),r=n(40),i=n(23),a=n(38),s=n(21),c=n(99),u=Object.getOwnPropertyDescriptor;e.f=n(15)?u:function(t,e){if(t=i(t),e=a(e,!0),c)try{return u(t,e)}catch(t){}if(s(t,e))return r(!o.f.call(t,e),t[e])}},function(t,e,n){var o=n(0),r=n(16),i=n(8);t.exports=function(t,e){var n=(r.Object||{})[t]||Object[t],a={};a[t]=e(n),o(o.S+o.F*i(function(){n(1)}),"Object",a)}},function(t,e,n){var o=n(31),r=n(56),i=n(24),a=n(17),s=n(254);t.exports=function(t,e){var n=1==t,c=2==t,u=3==t,l=4==t,f=6==t,d=5==t||f,p=e||s;return function(e,s,h){for(var v,g,y=i(e),b=r(y),m=o(s,h,3),k=a(b.length),x=0,w=n?p(e,k):c?p(e,0):void 0;k>x;x++)if((d||x in b)&&(g=m(v=b[x],x,y),t))if(n)w[x]=g;else if(g)switch(t){case 3:return!0;case 5:return v;case 6:return x;case 2:w.push(v)}else if(l)return!1;return f?-1:u||l?l:w}}},function(t,e,n){t.exports=n(334)},function(t,e){function n(t,e,n,o,r,i,a){try{var s=t[i](a),c=s.value}catch(t){return void n(t)}s.done?e(c):Promise.resolve(c).then(o,r)}t.exports=function(t){return function(){var e=this,o=arguments;return new Promise(function(r,i){var a=t.apply(e,o);function s(t){n(a,r,i,s,c,"next",t)}function c(t){n(a,r,i,s,c,"throw",t)}s(void 0)})}}},function(t,e,n){var o=n(32);t.exports=function(t,e,n){if(o(t),void 0===e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 2:return function(n,o){return t.call(e,n,o)};case 3:return function(n,o,r){return t.call(e,n,o,r)}}return function(){return t.apply(e,arguments)}}},function(t,e){t.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).slice(8,-1)}},function(t,e){t.exports=function(t){if(null==t)throw TypeError("Can't call method on "+t);return t}},function(t,e){var n=Math.ceil,o=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?o:n)(t)}},function(t,e,n){"use strict";if(n(15)){var o=n(42),r=n(9),i=n(8),a=n(0),s=n(69),c=n(96),u=n(31),l=n(53),f=n(40),d=n(22),p=n(54),h=n(35),v=n(17),g=n(124),y=n(44),b=n(38),m=n(21),k=n(61),x=n(10),w=n(24),S=n(89),E=n(45),T=n(47),_=n(46).f,B=n(91),C=n(41),O=n(12),I=n(28),N=n(59),M=n(66),L=n(93),A=n(50),P=n(63),R=n(52),j=n(92),F=n(116),D=n(14),U=n(26),H=D.f,z=U.f,W=r.RangeError,G=r.TypeError,V=r.Uint8Array,X=Array.prototype,Y=c.ArrayBuffer,K=c.DataView,Z=I(0),q=I(2),J=I(3),$=I(4),Q=I(5),tt=I(6),et=N(!0),nt=N(!1),ot=L.values,rt=L.keys,it=L.entries,at=X.lastIndexOf,st=X.reduce,ct=X.reduceRight,ut=X.join,lt=X.sort,ft=X.slice,dt=X.toString,pt=X.toLocaleString,ht=O("iterator"),vt=O("toStringTag"),gt=C("typed_constructor"),yt=C("def_constructor"),bt=s.CONSTR,mt=s.TYPED,kt=s.VIEW,xt=I(1,function(t,e){return _t(M(t,t[yt]),e)}),wt=i(function(){return 1===new V(new Uint16Array([1]).buffer)[0]}),St=!!V&&!!V.prototype.set&&i(function(){new V(1).set({})}),Et=function(t,e){var n=h(t);if(n<0||n%e)throw W("Wrong offset!");return n},Tt=function(t){if(x(t)&&mt in t)return t;throw G(t+" is not a typed array!")},_t=function(t,e){if(!(x(t)&> in t))throw G("It is not a typed array constructor!");return new t(e)},Bt=function(t,e){return Ct(M(t,t[yt]),e)},Ct=function(t,e){for(var n=0,o=e.length,r=_t(t,o);o>n;)r[n]=e[n++];return r},Ot=function(t,e,n){H(t,e,{get:function(){return this._d[n]}})},It=function(t){var e,n,o,r,i,a,s=w(t),c=arguments.length,l=c>1?arguments[1]:void 0,f=void 0!==l,d=B(s);if(null!=d&&!S(d)){for(a=d.call(s),o=[],e=0;!(i=a.next()).done;e++)o.push(i.value);s=o}for(f&&c>2&&(l=u(l,arguments[2],2)),e=0,n=v(s.length),r=_t(this,n);n>e;e++)r[e]=f?l(s[e],e):s[e];return r},Nt=function(){for(var t=0,e=arguments.length,n=_t(this,e);e>t;)n[t]=arguments[t++];return n},Mt=!!V&&i(function(){pt.call(new V(1))}),Lt=function(){return pt.apply(Mt?ft.call(Tt(this)):Tt(this),arguments)},At={copyWithin:function(t,e){return F.call(Tt(this),t,e,arguments.length>2?arguments[2]:void 0)},every:function(t){return $(Tt(this),t,arguments.length>1?arguments[1]:void 0)},fill:function(t){return j.apply(Tt(this),arguments)},filter:function(t){return Bt(this,q(Tt(this),t,arguments.length>1?arguments[1]:void 0))},find:function(t){return Q(Tt(this),t,arguments.length>1?arguments[1]:void 0)},findIndex:function(t){return tt(Tt(this),t,arguments.length>1?arguments[1]:void 0)},forEach:function(t){Z(Tt(this),t,arguments.length>1?arguments[1]:void 0)},indexOf:function(t){return nt(Tt(this),t,arguments.length>1?arguments[1]:void 0)},includes:function(t){return et(Tt(this),t,arguments.length>1?arguments[1]:void 0)},join:function(t){return ut.apply(Tt(this),arguments)},lastIndexOf:function(t){return at.apply(Tt(this),arguments)},map:function(t){return xt(Tt(this),t,arguments.length>1?arguments[1]:void 0)},reduce:function(t){return st.apply(Tt(this),arguments)},reduceRight:function(t){return ct.apply(Tt(this),arguments)},reverse:function(){for(var t,e=Tt(this).length,n=Math.floor(e/2),o=0;o1?arguments[1]:void 0)},sort:function(t){return lt.call(Tt(this),t)},subarray:function(t,e){var n=Tt(this),o=n.length,r=y(t,o);return new(M(n,n[yt]))(n.buffer,n.byteOffset+r*n.BYTES_PER_ELEMENT,v((void 0===e?o:y(e,o))-r))}},Pt=function(t,e){return Bt(this,ft.call(Tt(this),t,e))},Rt=function(t){Tt(this);var e=Et(arguments[1],1),n=this.length,o=w(t),r=v(o.length),i=0;if(r+e>n)throw W("Wrong length!");for(;i255?255:255&o),r.v[p](n*e+r.o,o,wt)}(this,n,t)},enumerable:!0})};m?(h=n(function(t,n,o,r){l(t,h,u,"_d");var i,a,s,c,f=0,p=0;if(x(n)){if(!(n instanceof Y||"ArrayBuffer"==(c=k(n))||"SharedArrayBuffer"==c))return mt in n?Ct(h,n):It.call(h,n);i=n,p=Et(o,e);var y=n.byteLength;if(void 0===r){if(y%e)throw W("Wrong length!");if((a=y-p)<0)throw W("Wrong length!")}else if((a=v(r)*e)+p>y)throw W("Wrong length!");s=a/e}else s=g(n),i=new Y(a=s*e);for(d(t,"_d",{b:i,o:p,l:a,e:s,v:new K(i)});f2&&void 0!==arguments[2]?arguments[2]:10,o=window.getSelection(),r=null;if(!o||!o.anchorNode||!o.focusNode)return null;var i=[o.anchorNode,o.focusNode];return i.forEach(function(o){for(var i=n;i>0&&o.parentNode&&(o.tagName!==t||(r=o,e&&o.classList&&!o.classList.contains(e)&&(r=null),!r));)o=o.parentNode,i--}),r}},{key:"expandToTag",value:function(t){var e=window.getSelection();e.removeAllRanges();var n=document.createRange();n.selectNodeContents(t),e.addRange(n)}}],[{key:"get",value:function(){return window.getSelection()}},{key:"CSS",get:function(){return{editorWrapper:"codex-editor",editorZone:"codex-editor__redactor"}}},{key:"anchorNode",get:function(){var t=window.getSelection();return t?t.anchorNode:null}},{key:"anchorOffset",get:function(){var t=window.getSelection();return t?t.anchorOffset:null}},{key:"isCollapsed",get:function(){var t=window.getSelection();return t?t.isCollapsed:null}},{key:"isAtEditor",get:function(){var e=t.get(),n=e.anchorNode||e.focusNode;n&&n.nodeType===Node.TEXT_NODE&&(n=n.parentNode);var o=null;return n&&(o=n.closest(".".concat(t.CSS.editorZone))),o&&o.nodeType===Node.ELEMENT_NODE}},{key:"range",get:function(){var t=window.getSelection();return t&&t.rangeCount?t.getRangeAt(0):null}},{key:"rect",get:function(){var t,e=document.selection,n={x:0,y:0,width:0,height:0};if(e&&"Control"!==e.type)return t=(e=e).createRange(),n.x=t.boundingLeft,n.y=t.boundingTop,n.width=t.boundingWidth,n.height=t.boundingHeight,n;if(!window.getSelection)return a.default.log("Method window.getSelection is not supported","warn"),n;if(null===(e=window.getSelection()).rangeCount||isNaN(e.rangeCount))return a.default.log("Method SelectionUtils.rangeCount is not supported","warn"),n;if((t=e.getRangeAt(0).cloneRange()).getBoundingClientRect&&(n=t.getBoundingClientRect()),0===n.x&&0===n.y){var o=document.createElement("span");if(o.getBoundingClientRect){o.appendChild(document.createTextNode("​")),t.insertNode(o),n=o.getBoundingClientRect();var r=o.parentNode;r.removeChild(o),r.normalize()}}return n}},{key:"text",get:function(){return window.getSelection?window.getSelection().toString():""}}]),t}();o.default=c,c.displayName="SelectionUtils",t.exports=e.default})?o.apply(e,r):o)||(t.exports=i)},function(t,e,n){var o=n(10);t.exports=function(t,e){if(!o(t))return t;var n,r;if(e&&"function"==typeof(n=t.toString)&&!o(r=n.call(t)))return r;if("function"==typeof(n=t.valueOf)&&!o(r=n.call(t)))return r;if(!e&&"function"==typeof(n=t.toString)&&!o(r=n.call(t)))return r;throw TypeError("Can't convert object to primitive value")}},function(t,e,n){var o=n(41)("meta"),r=n(10),i=n(21),a=n(14).f,s=0,c=Object.isExtensible||function(){return!0},u=!n(8)(function(){return c(Object.preventExtensions({}))}),l=function(t){a(t,o,{value:{i:"O"+ ++s,w:{}}})},f=t.exports={KEY:o,NEED:!1,fastKey:function(t,e){if(!r(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!i(t,o)){if(!c(t))return"F";if(!e)return"E";l(t)}return t[o].i},getWeak:function(t,e){if(!i(t,o)){if(!c(t))return!0;if(!e)return!1;l(t)}return t[o].w},onFreeze:function(t){return u&&f.NEED&&c(t)&&!i(t,o)&&l(t),t}}},function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e){var n=0,o=Math.random();t.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++n+o).toString(36))}},function(t,e){t.exports=!1},function(t,e,n){var o=n(101),r=n(76);t.exports=Object.keys||function(t){return o(t,r)}},function(t,e,n){var o=n(35),r=Math.max,i=Math.min;t.exports=function(t,e){return(t=o(t))<0?r(t+e,0):i(t,e)}},function(t,e,n){var o=n(11),r=n(102),i=n(76),a=n(75)("IE_PROTO"),s=function(){},c=function(){var t,e=n(72)("iframe"),o=i.length;for(e.style.display="none",n(78).appendChild(e),e.src="javascript:",(t=e.contentWindow.document).open(),t.write(" @@ -52,11 +52,11 @@ Copy [editorjs.js](../dist/editor.js) file to your project and load it. ## Load Tools -Each Block at the Editor.js represented by [Tools](tools.md). There are simple external scripts with own logic. Probably you want to use several Block Tools that should be connected. +Each Block at the Editor.js represented by [Tools](tools.md). There are simple external scripts with their own logic. You'll probably want to use several Block Tools that should be connected. -For example check out our [Header](https://github.com/editor-js/header) Tool that represents heading blocks. +For example, check out our [Header](https://github.com/editor-js/header) Tool that represents heading blocks. -You can install Header Tool via the same ways as an Editor (Node.js, CDN, local file). +You can install the Header Tool via the same ways as an Editor (Node.js, CDN, local file). Check [Editor.js's community](https://github.com/editor-js/) to see Tools examples. @@ -68,8 +68,8 @@ Check [Editor.js's community](https://github.com/editor-js/) to see Tools exampl ## Create Editor instance -Create an instance of Editor.js and pass [Configuration Object](../src/types-internal/editor-config.ts). -Minimal params is a `holderId`, `tools` list and `initialBlock` marker. +Create an instance of Editor.js and pass [Configuration Object](../src/types-internal/editor-config.ts). +At least the `holderId` option is required. ```html
@@ -115,11 +115,11 @@ var editor = new EditorJS({ ## Ready callback -Editor.js needs a bit time to initialize. It is an asynchronous action so it won't block execution of your main script. +Editor.js needs a bit of time to initialize. It is an asynchronous action so it won't block execution of your main script. -If you need to know when editor instance is ready you can use one of following ways: +If you need to know when the editor instance is ready you can use one of the following ways: -##### Pass `onReady` property to the configuration object. +##### Pass `onReady` property to the configuration object. It must be a function: @@ -136,9 +136,9 @@ var editor = new EditorJS({ #### Use `isReady` promise. -After you create new `EditorJS` object it contains `isReady` property. -It is a Promise object resolved when editor is ready to work and rejected otherwise. -If there is an error during initialization `isReady` promise will be rejected with error message. +After you create a new `EditorJS` object it will contain `isReady` property. +It is a Promise object that resolves when the editor will be ready to work and rejected otherwise. +If there is an error during initialization `isReady` promise will be rejected with an error message. ```javascript var editor = new EditorJS(); @@ -179,7 +179,7 @@ editor.saver.save() ## Features -Also Editor.js provides useful methods to work with Editor's state. +Also, Editor.js provides useful methods to work with Editor's state. ```javascript var editor = new EditorJS({ @@ -189,7 +189,7 @@ var editor = new EditorJS({ * onReady callback */ onReady: () => {console.log('Editor.js is ready to work!')}, - + /** * onChange callback */ diff --git a/docs/releases.md b/docs/releases.md new file mode 100644 index 000000000..675aaac60 --- /dev/null +++ b/docs/releases.md @@ -0,0 +1,100 @@ +# Branches, versions and releases — complete guideline + +## Branches + +The project has two main branches: `master` and `next`. + +Branch `master` contains the latest stable version of the editor. +The latest version published to NPM available by default or by the tag `latest`. + +Branch `next` used for development the next (release candidate) version of the editor. +It may contain bug fixes, improvements or features. This version is available in NPM by `next` tag. + +## Versions + +We use [semantic versioning](https://semver.org) as a main guide for naming updates. + +`..` + +You need to bump the part of version according the changes: + +- `patch` — for bug fixes, docs updates, code style fixes and other changes which do not affect the result project bundle +- `minor` — for new features with no backward compatibility problems. +- `major` — for breaking changes without backward compatibility with the api of the previous version of the project. + +Pre-release versions may contain additional `-rc.*` suffix. + +## Release publishing + +Drafts for new releases are created automatically via [create-a-release-draft.yml](.github/workflows/create-a-release-draft.yml) +workflow when pull request to `next` branch was merged with an updated version in the package.json file. + +There is a [workflow](.github/workflows/publish-package-to-npm.yml) that fired on a new release publishing on GitHub. + +Use target version changelog as a description. + +![](https://capella.pics/57267bab-f2f0-411b-a9d1-69abee6abab5.jpg) + +Then you can publish the release and wait for package publishing via action. + +This package version will be published to NPM with default `latest` tag. + +### Release candidate publishing + +If you want to publish release candidate version, use suffix `-rc.*` for package +version in package.json file and in tag on releases page. Workflow will detect it and mark a release as "pre-release". + +![](https://capella.pics/796de9eb-bbe0-485c-bc8f-9a4cb76641b7.jpg) + +This package version will be published to NPM with `next` tag. + +Stable version: `2.19.0` +Release candidate: `2.19.1-rc.0`, `2.19.1-rc.1`, ... +Next version: `2.19.1` + +## Auto-bump version + +After each PR merge to the `next` branch [bump-version-on-merge-next.yml](.github/workflows/bump-version-on-merge-next.yml) +workflow will check if a package version was updated. If there is no update then it will open a new PR with a next +prerelease version. + +### How it works + +The command for bumping a version will be running in a workflow. + +`yarn version --prerelease --preid rc --no-git-tag-version` + +Prerelease version will be bumped or a new prerelease patch will be created: + +- `2.19.1` -> `2.19.2-rc.0` +- `2.19.2-rc.0` -> `2.19.2-rc.1` + +### Change version + +You can edit version (and PR name of course) if you need to publish not a pre-release version or any other. + +If the next update is planned to raise the minor version (`2.19.1` -> `2.20.0`), then change it before version update merge. + +- `2.19.1` will be bumped to `2.19.2-rc.0` be default, change `2.19.2-rc.0` to `2.20.0-rc.0` + +### Ignore update + +If you do not need to upgrade and publish the update with the merged pull request (docs update or any other non-important changes), +you can close the pull request generated by the workflow. + +## Example pipeline + +Let's imagine that package version is `2.19.0` and you want to add some bug fixes and publish an update as `2.19.1`. + +1. Merge a single update or a few pulls with fixes to the default branch `next`. +2. Workflow [bump-version-on-merge-next.yml](.github/workflows/bump-version-on-merge-next.yml) will bump the version up +to `2.19.1-rc.0` in the package.json and open a new pull request. +3. After bump version PR merge, the workflow [create-a-release-draft.yml](.github/workflows/create-a-release-draft.yml) +will automatically create a draft release on GitHub. +4. Check this new draft release on the releases page. Check tag `v2.19.1-rc.0` and notice "This is pre-release" checkbox +if it should be for a release candidate versions. Then publish that release. +5. [Workflow](.github/workflows/publish-package-to-npm.yml) will automatically push the package to NPM with tag `next`. +6. When you ready to publish a release, remove suffix from version name in package.json (`2.19.1-rc.0` -> `v2.19.1`) +in pull request from workflow [bump-version-on-merge-next.yml](.github/workflows/bump-version-on-merge-next.yml). +Follow steps 3-5 with workflows and publish a new version as `latest` update. +7. Merge branch `next` to `master` and save sources for history. diff --git a/docs/tools-inline.md b/docs/tools-inline.md index 1a7b09b3d..d76e35307 100644 --- a/docs/tools-inline.md +++ b/docs/tools-inline.md @@ -123,3 +123,28 @@ static get sanitize() { ``` Read more about Sanitizer configuration at the [Tools#sanitize](tools.md#sanitize) + +### Specifying a title + +You can pass your Tool's title via `title` static getter. It can be used, for example, in the Tooltip with +icon description that appears by hover. + +![](https://capella.pics/00e7094a-fdb9-429b-8015-9c56f19b4ef5.jpg) + +```ts +export default class BoldInlineTool implements InlineTool { + /** + * Specifies Tool as Inline Toolbar Tool + * + * @return {boolean} + */ + public static isInline = true; + + /** + * Title for hover-tooltip + */ + public static title: string = 'Bold'; + + // ... other methods +} +``` diff --git a/docs/tools.md b/docs/tools.md index 4215d968a..6f782eccc 100644 --- a/docs/tools.md +++ b/docs/tools.md @@ -12,11 +12,12 @@ Each Tool should have an installation guide. Each Tool's instance called with an params object. -| Param | Type | Description | -| ------ | ------------------- | ----------------------------------------------- | -| api | [`IAPI`][iapi-link] | Editor.js's API methods | -| config | `object` | Special configuration params passed in «config» | -| data | `object` | Data to be rendered in this Tool | +| Param | Type | Description | +| ------ | ------------------------------------------------------ | ----------------------------------------------- | +| api | [`IAPI`](../types/index.d.ts) | Editor.js's API methods | +| config | [`ToolConfig`](../types/tools/tool-config.d.ts) | Special configuration params passed in «config» | +| data | [`BlockToolData`](../types/tools/block-tool-data.d.ts) | Data to be rendered in this Tool | +| block | [`BlockAPI`](../types/api/block.d.ts) | Block's API methods | [iapi-link]: ../src/types-internal/api.ts @@ -58,6 +59,8 @@ Options that Tool can specify. All settings should be passed as static propertie | `toolbox` | _Object_ | `undefined` | Pass here `icon` and `title` to display this `Tool` in the Editor's `Toolbox`
`icon` - HTML string with icon for Toolbox
`title` - optional title to display in Toolbox | | `enableLineBreaks` | _Boolean_ | `false` | With this option, Editor.js won't handle Enter keydowns. Can be helpful for Tools like `` where line breaks should be handled by default behaviour. | | `isInline` | _Boolean_ | `false` | Describes Tool as a [Tool for the Inline Toolbar](tools-inline.md) | +| `sanitize` | _Object_ | `undefined` | Config for automatic sanitizing of saved data. See [Sanitize](#sanitize) section. | +| `conversionConfig` | _Object_ | `undefined` | Config allows Tool to specify how it can be converted into/from another Tool. See [Conversion config](#conversion-config) section. | ## User configuration @@ -75,7 +78,7 @@ var editor = new EditorJS({ }, header: Header }, - initialBlock : 'text', + defaultBlock : 'text', }); ``` @@ -86,6 +89,36 @@ There are few options available by Editor.js. | `inlineToolbar` | _Boolean/Array_ | `false` | Pass `true` to enable the Inline Toolbar with all Tools, or pass an array with specified Tools list | | `config` | _Object_ | `null` | User's configuration for Plugin. +## Tool prepare and reset + +If you need to prepare some data for Tool (eg. load external script, create HTML nodes in the document, etc) you can use static prepare method. + +It accepts tools config passed on Editor's initialization as an argument: + +```javascript +class Tool { + static prepare(config) { + loadScript(); + insertNodes(); + ... + } +} +``` + +On Editor destroy you can use an opposite method `reset` to clean up all prepared data: + +```javascript +class Tool { + static reset() { + cleanUpScripts(); + deleteNodes(); + ... + } +} +``` + +Both methods might be async. + ## Paste handling Editor.js handles paste on Blocks and provides API for Tools to process the pasted data. @@ -115,7 +148,7 @@ To handle pasted HTML elements object returned from `pasteConfig` getter should | -- | -- | -- | | `tags` | `String[]` | _Optional_. Should contain all tag names you want to be extracted from pasted data and processed by your `onPaste` method | -For correct work you MUST provide `onPaste` handler at least for `initialBlock` Tool. +For correct work you MUST provide `onPaste` handler at least for `defaultBlock` Tool. > Example @@ -141,7 +174,7 @@ Your Tool can analyze text by RegExp patterns to substitute pasted string with d **Note** Editor will check pattern's full match, so don't forget to handle all available chars in there. -Pattern will be processed only if paste was on `initialBlock` Tool and pasted string length is less than 450 characters. +Pattern will be processed only if paste was on `defaultBlock` Tool and pasted string length is less than 450 characters. > Example @@ -224,7 +257,18 @@ onPaste (event) { } ``` -## Sanitize +### Disable paste handling + +If you need to disable paste handling on your Tool for some reason, you can provide `false` as `pasteConfig` value. +That way paste event won't be processed if fired on your Tool: + +```javascript +static get pasteConfig { + return false; +} +``` + +## Sanitize Editor.js provides [API](sanitizer.md) to clean taint strings. Use it manually at the `save()` method or or pass `sanitizer` config to do it automatically. @@ -341,4 +385,130 @@ static get sanitize() { } ``` +## Conversion config + +Editor.js has a Conversion Toolbar that allows user to convert one Block to another. + +![](https://capella.pics/6c1f708b-a30c-4ffd-a427-5b59a1a472e0.jpg) + +1. You can add ability to your Tool to be converted. Specify «export» property of `conversionConfig`. +2. You can add ability to convert other Tools to your Tool. Specify «import» property of `conversionConfig`. + +Conversion Toolbar will be shown only near Blocks that specified an «export» rule, when user selected almost all block's content. +This Toolbar will contain only Tools that specified an «import» rule. + +Example: + +```js +class Header { + constructor(){ + this.data = { + text: '', + level: 2 + } + } + + /** + * Rules specified how our Tool can be converted to/from other Tool. + */ + static get conversionConfig() { + return { + export: 'text', // this property of tool data will be used as string to pass to other tool + import: 'text' // to this property imported string will be passed + }; + } +} +``` + +### Your Tool -> other Tool + +The «export» field specifies how to represent your Tool's data as a string to pass it to other tool. + +It can be a `String` or a `Function`. + +`String` means a key of your Tool data object that should be used as string to export. + +`Function` is a method that accepts your Tool data and compose a string to export from it. See example below: + +```js +class ListTool { + constructor(){ + this.data = { + items: [ + 'Fisrt item', + 'Second item', + 'Third item' + ], + type: 'ordered' + } + } + + static get conversionConfig() { + return { + export: (data) => { + return data.items.join('.'); // in this example, all list items will be concatenated to an export string + }, + // ... import rule + }; + } +} +``` + +### Other Tool -> your Tool + +The «import» rule specifies how to create your Tool's data object from the string created by original block. + +It can be a `String` or a `Function`. + +`String` means the key in tool data that will be filled by an exported string. +For example, `import: 'text'` means that `constructor` of your block will accept a `data` object with `text` property filled with string composed by original block. + +`Function` allows you to specify own logic, how a string should be converted to your tool data. For example: + +```js +class ListTool { + constructor(data){ + this.data = data || { + items: [], + type: 'unordered' + } + } + + static get conversionConfig() { + return { + // ... export rule + + /** + * In this example, List Tool creates items by splitting original text by a dot symbol. + */ + import: (string) => { + const items = string.split('.'); + + return { + items: items.filter( (text) => text.trim() !== ''), + type: 'unordered' + }; + } + }; + } +} +``` + +## Block Lifecycle hooks + +### `rendered()` + +Called after Block contents is added to the page + +### `updated()` + +Called each time Block contents is updated + +### `removed()` + +Called after Block contents is removed from the page but before Block instance deleted + +### `moved(MoveEvent)` +Called after Block was moved. `MoveEvent` contains `fromIndex` and `toIndex` +respectively. diff --git a/docs/usage.md b/docs/usage.md index edd2a40f5..5bb43c08f 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -40,7 +40,7 @@ Action | Shortcut | Restrictions Also we support shortcuts on the all type of Tools. Specify a shortcut with the Tools configuration. For example: ```js -var editor = EditorJS({ +var editor = new EditorJS({ //... tools: { header: { @@ -63,10 +63,65 @@ If you want to focus Editor after page has been loaded, you can enable autofocus ```js -var editor = EditorJS({ +var editor = new EditorJS({ //... autofocus: true //... }); ``` + +## Holder +The `holder` property supports an id or a reference to dom element. + +```js +var editor = new EditorJS({ + holder: document.querySelector('.editor'), +}) + +var editor2 = new EditorJS({ + holder: 'codex-editor' // like document.getElementById('codex-editor') +}) +``` + + + +## Placeholder + +By default Editor\`s placeholder is empty. + +You can pass your own placeholder via `placeholder` field: + + +```js +var editor = new EditorJS({ + //... + placeholder: 'My awesome placeholder' + //... + }); + +``` + +If you are using your custom `Initial Block`, `placeholder` property is passed in `config` to your Tool constructor. + +## Log level + +You can specify log level for Editor.js console messages via `logLevel` property of configuration: + +```js +var editor = new EditorJS({ + //... + logLevel: 'WARN' + //.. +}) +``` + +Possible values: + +| Value | Description | +| ----- | ---------------------------- | +| `VERBOSE` | Show all messages | +| `INFO` | Show info and debug messages | +| `WARN` | Show errors and warns only | +| `ERROR` | Show errors only | + diff --git a/example/assets/codex2x.png b/example/assets/codex2x.png new file mode 100644 index 000000000..09388d080 Binary files /dev/null and b/example/assets/codex2x.png differ diff --git a/example/assets/demo.css b/example/assets/demo.css index e8a30aaa7..60ed8b7f4 100644 --- a/example/assets/demo.css +++ b/example/assets/demo.css @@ -69,6 +69,12 @@ body { padding: 0 15px; } +.ce-example__content--with-bg { + background: #f4f4f4; + max-width: none; + margin-top: -30px; +} + .ce-example__output { background: #1B202B; overflow-x: auto; @@ -93,7 +99,8 @@ body { max-width: 180px; background: #4A9DF8; padding: 17px 30px; - box-shadow: 0 6px 4px -4px rgba(137, 207, 255, 0.77); + box-shadow: 0 22px 18px -4px rgba(137, 207, 255, 0.77); + transition: all 150ms ease; cursor: pointer; border-radius: 31px; color: #fff; @@ -103,6 +110,8 @@ body { .ce-example__button:hover { background: #3D8DE5; + transform: translateY(2px); + box-shadow: 0 20px 15px -4px rgba(137, 207, 255, 0.77); } .ce-example__output-footer { @@ -117,6 +126,32 @@ body { text-decoration: none; } +.ce-example__statusbar { + position: fixed; + bottom: 10px; + right: 10px; + background: #fff; + border-radius: 8px; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18); + font-size: 12px; + padding: 8px 15px; + z-index: 1; +} + +.ce-example__statusbar-button { + display: inline-flex; + margin-left: 10px; + background: #4A9DF8; + padding: 6px 12px; + box-shadow: 0 7px 8px -4px rgba(137, 207, 255, 0.77); + transition: all 150ms ease; + cursor: pointer; + border-radius: 31px; + color: #fff; + font-family: 'PT Mono', Menlo, Monaco, Consolas, Courier New, monospace; + text-align: center; +} + @media all and (max-width: 730px){ .ce-example__header, .ce-example__content{ @@ -158,3 +193,16 @@ body { .ce-example h4.ce-header { font-size: 18px; } + +.ce-example-multiple { + display: grid; + grid-template-columns: calc(50% - 15px) calc(50% - 15px); + gap: 30px; + padding: 30px; +} + +.ce-example-multiple > div { + background: #fff; + border-radius: 7px; + padding: 30px; +} diff --git a/example/example-dev.html b/example/example-dev.html index 14b3a8b45..84553b66d 100644 --- a/example/example-dev.html +++ b/example/example-dev.html @@ -28,12 +28,24 @@
-
+
+ No core bundle file found. Run yarn build +
+
No submodules found. Run yarn pull_tools
editor.save()
+
+ Readonly: + + Off + +
+ toggle +
+

@@ -53,7 +65,7 @@
    Read more in Tool's README file. For example:
    https://github.com/editor-js/header#installation
    -->
-  
+  
   
   
   
@@ -70,24 +82,32 @@
   
 
   
-  
+  
 
   
   
 
diff --git a/example/example-i18n.html b/example/example-i18n.html
new file mode 100644
index 000000000..b07a67227
--- /dev/null
+++ b/example/example-i18n.html
@@ -0,0 +1,418 @@
+
+
+
+
+  
+  Editor.js 🤩🧦🤨 example
+  
+  
+  
+  
+
+
+
+ +
+
+
+ No core bundle file found. Run yarn build +
+ +
+ editor.save() +
+
+
+

+
+    
+  
+
+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/example-multiple.html b/example/example-multiple.html new file mode 100644 index 000000000..154704203 --- /dev/null +++ b/example/example-multiple.html @@ -0,0 +1,76 @@ + + + + + + + Editor.js 🤩🧦🤨 example: Multiple instances + + + + +
+ +
+
+ No core bundle file found. Run yarn build +
+
+
+
+
+
+
+ +
+
+ + + + + + + + + diff --git a/example/example-rtl.html b/example/example-rtl.html new file mode 100644 index 000000000..cb1c2ba1e --- /dev/null +++ b/example/example-rtl.html @@ -0,0 +1,238 @@ + + + + + + Editor.js RTL example + + + + + + +
+ +
+
+
+ No core bundle file found. Run yarn build +
+
+ No submodules found. Run yarn pull_tools +
+
+ editor.save() +
+
+
+

+
+    
+  
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/example.html b/example/example.html index 337be897c..7de5baeb7 100644 --- a/example/example.html +++ b/example/example.html @@ -26,6 +26,16 @@
editor.save()
+ +
+ Readonly: + + Off + +
+ toggle +
+

@@ -38,12 +48,12 @@
 
   
   
   
   
@@ -61,24 +71,32 @@
   
 
   
-  
+  
 
   
   
 
diff --git a/example/tools/checklist b/example/tools/checklist
index df6dcedb9..197d5d53e 160000
--- a/example/tools/checklist
+++ b/example/tools/checklist
@@ -1 +1 @@
-Subproject commit df6dcedb92ef586901b04cf72946aced9e36e58d
+Subproject commit 197d5d53e0c7d869d76afc4eabae566d391e6d0e
diff --git a/example/tools/code b/example/tools/code
index 62425d7eb..83d2d9d31 160000
--- a/example/tools/code
+++ b/example/tools/code
@@ -1 +1 @@
-Subproject commit 62425d7eb6378425b8103e2b84b131f0a489eaaf
+Subproject commit 83d2d9d3136d48ab67b52bc034370c9a26c82c8c
diff --git a/example/tools/delimiter b/example/tools/delimiter
index 6819831b7..1f2ec8c70 160000
--- a/example/tools/delimiter
+++ b/example/tools/delimiter
@@ -1 +1 @@
-Subproject commit 6819831b7166c1cdfa31df77ab569274d9910aac
+Subproject commit 1f2ec8c709a94c5f4f499bb1aaba7f4930e10484
diff --git a/example/tools/embed b/example/tools/embed
index a99abc4f8..9d3d4b521 160000
--- a/example/tools/embed
+++ b/example/tools/embed
@@ -1 +1 @@
-Subproject commit a99abc4f84c8dc44b86f037f74e971374d28e22f
+Subproject commit 9d3d4b5216dce1a933b1e92b45b7b8c404d889b7
diff --git a/example/tools/header b/example/tools/header
index 3d3f8c2bc..2b21da39b 160000
--- a/example/tools/header
+++ b/example/tools/header
@@ -1 +1 @@
-Subproject commit 3d3f8c2bc80caefbfb3da47ab876d5a0e6ccdf5b
+Subproject commit 2b21da39b57d0abfcd4979444fb0c3d2d435af7d
diff --git a/example/tools/image b/example/tools/image
index a41203838..a983c4e62 160000
--- a/example/tools/image
+++ b/example/tools/image
@@ -1 +1 @@
-Subproject commit a41203838cd7198c63e78844e27b19079b00d0fa
+Subproject commit a983c4e62135c88d6cfd926527e6fc92c304451b
diff --git a/example/tools/inline-code b/example/tools/inline-code
index 522f4bcf5..051b8e9e0 160000
--- a/example/tools/inline-code
+++ b/example/tools/inline-code
@@ -1 +1 @@
-Subproject commit 522f4bcf56776ffb573f462be6a4eb87d6fc9e7b
+Subproject commit 051b8e9e03e2f6bea30875da8253f6c0d858b231
diff --git a/example/tools/link b/example/tools/link
index 470a64c8b..6a5563630 160000
--- a/example/tools/link
+++ b/example/tools/link
@@ -1 +1 @@
-Subproject commit 470a64c8ba8a65f3e291d77bc9e2d53a48591f87
+Subproject commit 6a5563630977f223ebafaa03a7df3bf85797437b
diff --git a/example/tools/list b/example/tools/list
index 964edb412..458a5fe36 160000
--- a/example/tools/list
+++ b/example/tools/list
@@ -1 +1 @@
-Subproject commit 964edb412f9ddfe60c6e71d6ed0c5b86d093185c
+Subproject commit 458a5fe364e33ad5b5913155d665f335ab742e0f
diff --git a/example/tools/marker b/example/tools/marker
index 414c02a28..6708697c1 160000
--- a/example/tools/marker
+++ b/example/tools/marker
@@ -1 +1 @@
-Subproject commit 414c02a28bed932cb396329787c0adadf8a9111f
+Subproject commit 6708697c1af79abbf6650f0f14e1cedc45eb5213
diff --git a/example/tools/quote b/example/tools/quote
index 7f2e71470..07881fc10 160000
--- a/example/tools/quote
+++ b/example/tools/quote
@@ -1 +1 @@
-Subproject commit 7f2e71470910291ba3ebd2fc013fbef33d054aa3
+Subproject commit 07881fc1020fde79ab9468f740227a99935abb2a
diff --git a/example/tools/raw b/example/tools/raw
index e0ace3a0b..3f40a9cfd 160000
--- a/example/tools/raw
+++ b/example/tools/raw
@@ -1 +1 @@
-Subproject commit e0ace3a0be6561f103b693596618095dffdfb34d
+Subproject commit 3f40a9cfdb0086c94ee2c7295a96d69c9b266dec
diff --git a/example/tools/simple-image b/example/tools/simple-image
index 26889a137..1883b28d8 160000
--- a/example/tools/simple-image
+++ b/example/tools/simple-image
@@ -1 +1 @@
-Subproject commit 26889a13713a2dd477124196b32e9817e6f5caae
+Subproject commit 1883b28d8aac863d3907c21d5fda231c8e6f799a
diff --git a/example/tools/table b/example/tools/table
index a2647e64f..5c1a73a80 160000
--- a/example/tools/table
+++ b/example/tools/table
@@ -1 +1 @@
-Subproject commit a2647e64feb5a744aa6cd51a5e08ca76b6cbfe6b
+Subproject commit 5c1a73a8022c18ac1c15ee8d0134caae029bfbe9
diff --git a/example/tools/warning b/example/tools/warning
index d65ead448..c0507d910 160000
--- a/example/tools/warning
+++ b/example/tools/warning
@@ -1 +1 @@
-Subproject commit d65ead448d74d0e6adc42f14cefb9e7a5aad8320
+Subproject commit c0507d91014f9b4fdb514f0499348d7619e3e1a2
diff --git a/package.json b/package.json
index a5e603031..9ce5b010f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@editorjs/editorjs",
-  "version": "2.12.3",
+  "version": "2.19.2",
   "description": "Editor.js — Native JS, based on API and Open Source",
   "main": "dist/editor.js",
   "types": "./types/index.d.ts",
@@ -12,14 +12,19 @@
     "editorjs"
   ],
   "scripts": {
-    "build": "rimraf dist/* && yarn svg && yarn build:prod",
-    "build:win": "rimraf dist && yarn svg:win && yarn build:prod",
-    "build:dev": "webpack --mode development --progress --display-error-details --display-entrypoints --watch",
-    "build:prod": "webpack --mode production",
-    "svg:win": "if not exist dist md dist && yarn svg",
+    "clear": "rimraf dist && mkdirp dist",
+    "build": "yarn clear && yarn svg && yarn build:webpack:prod",
+    "build:dev": "yarn clear && yarn svg && yarn build:webpack:dev",
+    "build:webpack:dev": "webpack --mode development --progress --display-error-details --display-entrypoints --watch",
+    "build:webpack:prod": "webpack --mode production",
+    "lint": "eslint src/ --ext .ts && yarn lint:tests",
+    "lint:errors": "eslint src/ --ext .ts --quiet",
+    "lint:fix": "eslint src/ --ext .ts --fix",
+    "lint:tests": "eslint test/ --ext .ts",
     "svg": "svg-sprite-generate -d src/assets/ -o dist/sprite.svg",
     "pull_tools": "git submodule update --init --recursive",
-    "checkout_tools": "git submodule foreach git pull origin master"
+    "checkout_tools": "git submodule foreach git pull origin master",
+    "test:e2e": "cypress run"
   },
   "author": "CodeX",
   "license": "Apache-2.0",
@@ -28,46 +33,53 @@
     "url": "git+https://github.com/codex-team/editor.js.git"
   },
   "devDependencies": {
-    "@babel/core": "^7.3.4",
-    "@babel/plugin-transform-runtime": "^7.3.4",
-    "@babel/polyfill": "^7.2.5",
-    "@babel/preset-env": "^7.3.4",
-    "@babel/register": "^7.0.0",
-    "@babel/runtime": "^7.3.4",
-    "@codexteam/shortcuts": "^1.0.0",
-    "@types/webpack": "^4.4.25",
-    "@types/webpack-env": "^1.13.9",
-    "babel-loader": "^8.0.5",
+    "@babel/core": "^7.9.0",
+    "@babel/plugin-transform-runtime": "^7.9.0",
+    "@babel/polyfill": "^7.8.7",
+    "@babel/preset-env": "^7.9.5",
+    "@babel/register": "^7.9.0",
+    "@babel/runtime": "^7.9.2",
+    "@codexteam/shortcuts": "^1.1.1",
+    "@types/webpack": "^4.41.12",
+    "@types/webpack-env": "^1.15.2",
+    "babel-loader": "^8.1.0",
     "babel-plugin-add-module-exports": "^1.0.0",
     "babel-plugin-class-display-name": "^2.1.0",
-    "codex-notifier": "^1.1.1",
-    "css-loader": "^2.1.1",
+    "core-js": "3.6.5",
+    "css-loader": "^3.5.3",
     "cssnano": "^4.1.10",
-    "eslint": "^5.15.1",
-    "eslint-loader": "^2.1.2",
+    "cypress": "^5.5.0",
+    "eslint": "^6.8.0",
+    "eslint-config-codex": "^1.3.3",
+    "eslint-loader": "^4.0.2",
+    "eslint-plugin-cypress": "^2.11.2",
     "extract-text-webpack-plugin": "^3.0.2",
     "html-janitor": "^2.0.4",
-    "license-webpack-plugin": "^2.1.1",
+    "license-webpack-plugin": "^2.1.4",
+    "mkdirp": "^1.0.4",
     "postcss-apply": "^0.12.0",
     "postcss-import": "^12.0.1",
     "postcss-loader": "^3.0.0",
     "postcss-nested": "^4.1.2",
     "postcss-nested-ancestors": "^2.0.0",
     "postcss-preset-env": "^6.6.0",
-    "raw-loader": "^1.0.0",
-    "rimraf": "^2.6.3",
-    "stylelint": "^9.10.1",
+    "raw-loader": "^4.0.1",
+    "rimraf": "^3.0.2",
+    "stylelint": "^13.3.3",
     "svg-sprite-generator": "^0.0.7",
-    "terser-webpack-plugin": "^1.2.3",
-    "ts-loader": "^5.3.3",
-    "tslint": "^5.14.0",
-    "tslint-loader": "^3.5.4",
-    "typescript": "^3.3.3333",
-    "webpack": "^4.29.6",
-    "webpack-cli": "^3.2.3"
+    "terser-webpack-plugin": "^2.3.6",
+    "ts-loader": "^7.0.1",
+    "tslint": "^6.1.1",
+    "typescript": "3.8.3",
+    "webpack": "^4.43.0",
+    "webpack-cli": "^3.3.11"
   },
   "collective": {
     "type": "opencollective",
     "url": "https://opencollective.com/editorjs"
+  },
+  "dependencies": {
+    "codex-notifier": "^1.1.2",
+    "codex-tooltip": "^1.0.1"
   }
 }
diff --git a/src/assets/bold.svg b/src/assets/bold.svg
index f10a3d6d6..1cbd3b96e 100644
--- a/src/assets/bold.svg
+++ b/src/assets/bold.svg
@@ -1,3 +1 @@
-
-  
-
+
diff --git a/src/assets/dots.svg b/src/assets/dots.svg
index 661f880d0..926bbd806 100644
--- a/src/assets/dots.svg
+++ b/src/assets/dots.svg
@@ -1,7 +1,6 @@
-
-  
-    
-    
-    
-  
+
+  
+  
+  
+  
 
diff --git a/src/assets/italic.svg b/src/assets/italic.svg
index 0c23b1ffc..94c777cbe 100644
--- a/src/assets/italic.svg
+++ b/src/assets/italic.svg
@@ -1,3 +1,3 @@
-
-  
+
+    
 
diff --git a/src/assets/link.svg b/src/assets/link.svg
index 7a6068f47..fee4a2785 100644
--- a/src/assets/link.svg
+++ b/src/assets/link.svg
@@ -1,3 +1,3 @@
-
-    
+
+  
 
diff --git a/src/assets/toggler-down.svg b/src/assets/toggler-down.svg
new file mode 100644
index 000000000..86570a926
--- /dev/null
+++ b/src/assets/toggler-down.svg
@@ -0,0 +1,3 @@
+
+  
+
diff --git a/src/assets/unlink.svg b/src/assets/unlink.svg
index 780c3812d..5dea3d820 100644
--- a/src/assets/unlink.svg
+++ b/src/assets/unlink.svg
@@ -1,3 +1,3 @@
-
-    
+
+  
 
diff --git a/src/codex.ts b/src/codex.ts
index 80440de98..29dc4b8f3 100644
--- a/src/codex.ts
+++ b/src/codex.ts
@@ -1,7 +1,6 @@
 'use strict';
-import {EditorConfig} from '../types';
 
-declare const VERSION: string;
+import { EditorConfig } from '../types';
 
 /**
  * Apply polyfills
@@ -10,14 +9,18 @@ import '@babel/register';
 
 import 'components/polyfills';
 import Core from './components/core';
+import * as _ from './components/utils';
+
+declare const VERSION: string;
 
 /**
  * Editor.js
  *
  * Short Description (눈_눈;)
- * @version 2.0
  *
- * @licence Apache-2.0
+ * @version 2.18.0
+ *
+ * @license Apache-2.0
  * @author CodeX-Team 
  */
 export default class EditorJS {
@@ -33,25 +36,24 @@ export default class EditorJS {
   public destroy: () => void;
 
   /** Editor version */
-  static get version(): string {
+  public static get version(): string {
     return VERSION;
   }
 
   /**
-   * @constructor
-   *
-   * @param {EditorConfig|String|undefined} [configuration] - user configuration
+   * @param {EditorConfig|string|undefined} [configuration] - user configuration
    */
-  public constructor(configuration?: EditorConfig|string) {
+  constructor(configuration?: EditorConfig|string) {
     /**
      * Set default onReady function
      */
-    let onReady = () => {};
+    // eslint-disable-next-line @typescript-eslint/no-empty-function
+    let onReady = (): void => {};
 
     /**
      * If `onReady` was passed in `configuration` then redefine onReady function
      */
-    if (typeof configuration === 'object' && typeof configuration.onReady === 'function') {
+    if (_.isObject(configuration) && _.isFunction(configuration.onReady)) {
       onReady = configuration.onReady;
     }
 
@@ -63,6 +65,7 @@ export default class EditorJS {
     /**
      * We need to export isReady promise in the constructor
      * as it can be used before other API methods are exported
+     *
      * @type {Promise}
      */
     this.isReady = editor.isReady.then(() => {
@@ -74,18 +77,23 @@ export default class EditorJS {
   /**
    * Export external API methods
    *
-   * @param editor
+   * @param {Core} editor — Editor's instance
    */
   public exportAPI(editor: Core): void {
     const fieldsToExport = [ 'configuration' ];
-    const destroy = () => {
-      editor.moduleInstances.Listeners.removeAll();
-      editor.moduleInstances.UI.destroy();
-      editor.moduleInstances.ModificationsObserver.destroy();
+    const destroy = (): void => {
+      Object.values(editor.moduleInstances)
+        .forEach((moduleInstance) => {
+          if (_.isFunction(moduleInstance.destroy)) {
+            moduleInstance.destroy();
+          }
+          moduleInstance.listeners.removeAll();
+        });
+
       editor = null;
 
       for (const field in this) {
-        if (this.hasOwnProperty(field)) {
+        if (Object.prototype.hasOwnProperty.call(this, field)) {
           delete this[field];
         }
       }
diff --git a/src/components/__module.ts b/src/components/__module.ts
index ad5a30433..877ecd885 100644
--- a/src/components/__module.ts
+++ b/src/components/__module.ts
@@ -1,6 +1,14 @@
-import {EditorModules} from '../types-internal/editor-modules';
-import {EditorConfig} from '../../types';
-import {ModuleConfig} from '../types-internal/module-config';
+import { EditorModules } from '../types-internal/editor-modules';
+import { EditorConfig } from '../../types';
+import { ModuleConfig } from '../types-internal/module-config';
+import Listeners from './utils/listeners';
+import EventsDispatcher from './utils/events';
+
+/**
+ * The type  of the Module generic.
+ * It describes the structure of nodes used in modules.
+ */
+export type ModuleNodes = object;
 
 /**
  * @abstract
@@ -8,40 +16,121 @@ import {ModuleConfig} from '../types-internal/module-config';
  * @classdesc  All modules inherits from this class.
  *
  * @typedef {Module} Module
- * @property {Object} config - Editor user settings
+ * @property {object} config - Editor user settings
  * @property {EditorModules} Editor - List of Editor modules
  */
-export default class Module {
+export default class Module {
+  /**
+   * Each module can provide some UI elements that will be stored in this property
+   */
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  public nodes: T = {} as any;
 
   /**
    * Editor modules list
+   *
    * @type {EditorModules}
    */
   protected Editor: EditorModules;
 
   /**
    * Editor configuration object
+   *
    * @type {EditorConfig}
    */
   protected config: EditorConfig;
 
   /**
-   * @constructor
-   * @param {EditorConfig}
+   * Editor event dispatcher class
+   */
+  protected eventsDispatcher: EventsDispatcher;
+
+  /**
+   * Util for bind/unbind DOM event listeners
    */
-  constructor({config}: ModuleConfig) {
+  protected listeners: Listeners = new Listeners();
+
+  /**
+   * This object provides methods to push into set of listeners that being dropped when read-only mode is enabled
+   */
+  protected readOnlyMutableListeners = {
+    /**
+     * Assigns event listener on DOM element and pushes into special array that might be removed
+     *
+     * @param {EventTarget} element - DOM Element
+     * @param {string} eventType - Event name
+     * @param {Function} handler - Event handler
+     * @param {boolean|AddEventListenerOptions} options - Listening options
+     */
+    on: (
+      element: EventTarget,
+      eventType: string,
+      handler: (event: Event) => void,
+      options: boolean | AddEventListenerOptions = false
+    ): void => {
+      this.mutableListenerIds.push(
+        this.listeners.on(element, eventType, handler, options)
+      );
+    },
+
+    /**
+     * Clears all mutable listeners
+     */
+    clearAll: (): void => {
+      for (const id of this.mutableListenerIds) {
+        this.listeners.offById(id);
+      }
+
+      this.mutableListenerIds = [];
+    },
+  };
+
+  /**
+   * The set of listener identifiers which will be dropped in read-only mode
+   */
+  private mutableListenerIds: string[] = [];
+
+  /**
+   * @class
+   *
+   * @param {EditorConfig} config - Editor's config
+   * @param {EventsDispatcher} eventsDispatcher - Editor's event dispatcher
+   */
+  constructor({ config, eventsDispatcher }: ModuleConfig) {
     if (new.target === Module) {
       throw new TypeError('Constructors for abstract class Module are not allowed.');
     }
 
     this.config = config;
+    this.eventsDispatcher = eventsDispatcher;
   }
 
   /**
    * Editor modules setter
-   * @param {EditorModules} Editor
+   *
+   * @param {EditorModules} Editor - Editor's Modules
    */
-  set state(Editor: EditorModules) {
+  public set state(Editor: EditorModules) {
     this.Editor = Editor;
   }
+
+  /**
+   * Remove memorized nodes
+   */
+  public removeAllNodes(): void {
+    for (const key in this.nodes) {
+      const node = this.nodes[key];
+
+      if (node instanceof HTMLElement) {
+        node.remove();
+      }
+    }
+  }
+
+  /**
+   * Returns true if current direction is RTL (Right-To-Left)
+   */
+  protected get isRtl(): boolean {
+    return this.config.i18n.direction === 'rtl';
+  }
 }
diff --git a/src/components/block-tunes/block-tune-delete.ts b/src/components/block-tunes/block-tune-delete.ts
index 8a268562d..87a8cf858 100644
--- a/src/components/block-tunes/block-tune-delete.ts
+++ b/src/components/block-tunes/block-tune-delete.ts
@@ -4,23 +4,24 @@
  *
  * @copyright  2018
  */
-import {API, BlockTune} from '../../../types';
+import { API, BlockTune } from '../../../types';
 import $ from '../dom';
 
+/**
+ *
+ */
 export default class DeleteTune implements BlockTune {
-
   /**
    * Property that contains Editor.js API methods
-   * @see {docs/api.md}
+   *
+   * @see {@link docs/api.md}
    */
   private readonly api: API;
 
   /**
    * Styles
-   * @type {{wrapper: string}}
    */
   private CSS = {
-    wrapper: 'ass',
     button: 'ce-settings__button',
     buttonDelete: 'ce-settings__button--delete',
     buttonConfirm: 'ce-settings__button--confirm',
@@ -34,7 +35,7 @@ export default class DeleteTune implements BlockTune {
   /**
    * set false confirmation state
    */
-  private resetConfirmation: () => void;
+  private readonly resetConfirmation: () => void;
 
   /**
    * Tune nodes
@@ -46,33 +47,40 @@ export default class DeleteTune implements BlockTune {
   /**
    * DeleteTune constructor
    *
-   * @param {{api: API}} api
+   * @param {API} api - Editor's API
    */
-  constructor({api}) {
+  constructor({ api }) {
     this.api = api;
 
-    this.resetConfirmation = () => {
+    this.resetConfirmation = (): void => {
       this.setConfirmation(false);
     };
   }
 
   /**
    * Create "Delete" button and add click event listener
-   * @returns [Element}
+   *
+   * @returns {HTMLElement}
    */
-  public render() {
+  public render(): HTMLElement {
     this.nodes.button = $.make('div', [this.CSS.button, this.CSS.buttonDelete], {});
     this.nodes.button.appendChild($.svg('cross', 12, 12));
     this.api.listeners.on(this.nodes.button, 'click', (event: MouseEvent) => this.handleClick(event), false);
+
+    /**
+     * Enable tooltip module
+     */
+    this.api.tooltip.onHover(this.nodes.button, this.api.i18n.t('Delete'));
+
     return this.nodes.button;
   }
 
   /**
    * Delete block conditions passed
-   * @param {MouseEvent} event
+   *
+   * @param {MouseEvent} event - click event
    */
   public handleClick(event: MouseEvent): void {
-
     /**
      * if block is not waiting the confirmation, subscribe on block-settings-closing event to reset
      * otherwise delete block
@@ -86,17 +94,15 @@ export default class DeleteTune implements BlockTune {
        * then reset confirmation state
        */
       this.api.events.on('block-settings-closed', this.resetConfirmation);
-
     } else {
-
       /**
        * Unsubscribe from block-settings closing event
        */
       this.api.events.off('block-settings-closed', this.resetConfirmation);
 
       this.api.blocks.delete();
-
       this.api.toolbar.close();
+      this.api.tooltip.hide();
 
       /**
        * Prevent firing ui~documentClicked that can drop currentBlock pointer
@@ -107,10 +113,11 @@ export default class DeleteTune implements BlockTune {
 
   /**
    * change tune state
+   *
+   * @param {boolean} state - delete confirmation state
    */
-  private setConfirmation(state): void {
+  private setConfirmation(state: boolean): void {
     this.needConfirmation = state;
     this.nodes.button.classList.add(this.CSS.buttonConfirm);
   }
-
 }
diff --git a/src/components/block-tunes/block-tune-move-down.ts b/src/components/block-tunes/block-tune-move-down.ts
index 762c8e5bd..f095f6dbf 100644
--- a/src/components/block-tunes/block-tune-move-down.ts
+++ b/src/components/block-tunes/block-tune-move-down.ts
@@ -6,17 +6,22 @@
  */
 
 import $ from '../dom';
-import {API, BlockTune} from '../../../types';
+import { API, BlockTune } from '../../../types';
 
+/**
+ *
+ */
 export default class MoveDownTune implements BlockTune {
   /**
    * Property that contains Editor.js API methods
-   * @see {api.md}
+   *
+   * @see {@link docs/api.md}
    */
   private readonly api: API;
 
   /**
    * Styles
+   *
    * @type {{wrapper: string}}
    */
   private CSS = {
@@ -28,47 +33,58 @@ export default class MoveDownTune implements BlockTune {
   /**
    * MoveDownTune constructor
    *
-   * @param {{api: API}} api
+   * @param {API} api — Editor's API
    */
-  public constructor({api}) {
+  constructor({ api }) {
     this.api = api;
   }
 
   /**
    * Return 'move down' button
+   *
+   * @returns {HTMLElement}
    */
-  public render() {
+  public render(): HTMLElement {
     const moveDownButton = $.make('div', [this.CSS.button, this.CSS.wrapper], {});
+
     moveDownButton.appendChild($.svg('arrow-down', 14, 14));
     this.api.listeners.on(
       moveDownButton,
       'click',
       (event) => this.handleClick(event as MouseEvent, moveDownButton),
-      false,
+      false
     );
+
+    /**
+     * Enable tooltip module on button
+     */
+    this.api.tooltip.onHover(moveDownButton, this.api.i18n.t('Move down'));
+
     return moveDownButton;
   }
 
   /**
    * Handle clicks on 'move down' button
-   * @param {MouseEvent} event
-   * @param {HTMLElement} button
+   *
+   * @param {MouseEvent} event - click event
+   * @param {HTMLElement} button - clicked button
    */
-  public handleClick(event: MouseEvent, button: HTMLElement) {
-
+  public handleClick(event: MouseEvent, button: HTMLElement): void {
     const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
+    const nextBlock = this.api.blocks.getBlockByIndex(currentBlockIndex + 1);
 
     // If Block is last do nothing
-    if (currentBlockIndex === this.api.blocks.getBlocksCount() - 1) {
+    if (!nextBlock) {
       button.classList.add(this.CSS.animation);
 
-      window.setTimeout( () => {
+      window.setTimeout(() => {
         button.classList.remove(this.CSS.animation);
       }, 500);
+
       return;
     }
 
-    const nextBlockElement = this.api.blocks.getBlockByIndex(currentBlockIndex + 1);
+    const nextBlockElement = nextBlock.holder;
     const nextBlockCoords = nextBlockElement.getBoundingClientRect();
 
     let scrollOffset = Math.abs(window.innerHeight - nextBlockElement.offsetHeight);
@@ -78,15 +94,15 @@ export default class MoveDownTune implements BlockTune {
      * Increment scroll by next block's height to save element onscreen-position
      */
     if (nextBlockCoords.top < window.innerHeight) {
-
       scrollOffset = window.scrollY + nextBlockElement.offsetHeight;
-
     }
 
     window.scrollTo(0, scrollOffset);
 
     /** Change blocks positions */
-    this.api.blocks.swap(currentBlockIndex, currentBlockIndex + 1);
+    this.api.blocks.move(currentBlockIndex + 1);
 
+    /** Hide the Tooltip */
+    this.api.tooltip.hide();
   }
 }
diff --git a/src/components/block-tunes/block-tune-move-up.ts b/src/components/block-tunes/block-tune-move-up.ts
index f45db64a5..0005af916 100644
--- a/src/components/block-tunes/block-tune-move-up.ts
+++ b/src/components/block-tunes/block-tune-move-up.ts
@@ -5,18 +5,22 @@
  * @copyright  2018
  */
 import $ from '../dom';
-import {API, BlockTune} from '../../../types';
+import { API, BlockTune } from '../../../types';
 
+/**
+ *
+ */
 export default class MoveUpTune implements BlockTune {
-
   /**
    * Property that contains Editor.js API methods
-   * @see {api.md}
+   *
+   * @see {@link docs/api.md}
    */
   private readonly api: API;
 
   /**
    * Styles
+   *
    * @type {{wrapper: string}}
    */
   private CSS = {
@@ -28,48 +32,59 @@ export default class MoveUpTune implements BlockTune {
   /**
    * MoveUpTune constructor
    *
-   * @param {{api: API}} api
+   * @param {API} api - Editor's API
    */
-  public constructor({api}) {
+  constructor({ api }) {
     this.api = api;
   }
 
   /**
    * Create "MoveUp" button and add click event listener
-   * @returns [HTMLElement}
+   *
+   * @returns {HTMLElement}
    */
   public render(): HTMLElement {
     const moveUpButton = $.make('div', [this.CSS.button, this.CSS.wrapper], {});
+
     moveUpButton.appendChild($.svg('arrow-up', 14, 14));
     this.api.listeners.on(
       moveUpButton,
       'click',
       (event) => this.handleClick(event as MouseEvent, moveUpButton),
-      false,
-      );
+      false
+    );
+
+    /**
+     * Enable tooltip module on button
+     */
+    this.api.tooltip.onHover(moveUpButton, this.api.i18n.t('Move up'));
+
     return moveUpButton;
   }
 
   /**
    * Move current block up
-   * @param {MouseEvent} event
-   * @param {HTMLElement} button
+   *
+   * @param {MouseEvent} event - click event
+   * @param {HTMLElement} button - clicked button
    */
   public handleClick(event: MouseEvent, button: HTMLElement): void {
-
     const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
+    const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex);
+    const previousBlock = this.api.blocks.getBlockByIndex(currentBlockIndex - 1);
 
-    if (currentBlockIndex === 0) {
+    if (currentBlockIndex === 0 || !currentBlock || !previousBlock) {
       button.classList.add(this.CSS.animation);
 
-      window.setTimeout( () => {
+      window.setTimeout(() => {
         button.classList.remove(this.CSS.animation);
       }, 500);
+
       return;
     }
 
-    const currentBlockElement = this.api.blocks.getBlockByIndex(currentBlockIndex);
-    const previousBlockElement = this.api.blocks.getBlockByIndex(currentBlockIndex - 1);
+    const currentBlockElement = currentBlock.holder;
+    const previousBlockElement = previousBlock.holder;
 
     /**
      * Here is two cases:
@@ -80,7 +95,7 @@ export default class MoveUpTune implements BlockTune {
      *      than we scroll window to the difference between this offsets.
      */
     const currentBlockCoords = currentBlockElement.getBoundingClientRect(),
-      previousBlockCoords = previousBlockElement.getBoundingClientRect();
+        previousBlockCoords = previousBlockElement.getBoundingClientRect();
 
     let scrollUpOffset;
 
@@ -93,6 +108,9 @@ export default class MoveUpTune implements BlockTune {
     window.scrollBy(0, -1 * scrollUpOffset);
 
     /** Change blocks positions */
-    this.api.blocks.swap(currentBlockIndex, currentBlockIndex - 1);
+    this.api.blocks.move(currentBlockIndex - 1);
+
+    /** Hide the Tooltip */
+    this.api.tooltip.hide();
   }
 }
diff --git a/src/components/block.ts b/src/components/block.ts
deleted file mode 100644
index edcddb955..000000000
--- a/src/components/block.ts
+++ /dev/null
@@ -1,500 +0,0 @@
-import {
-  API,
-  BlockTool,
-  BlockToolConstructable,
-  BlockToolData,
-  BlockTune,
-  BlockTuneConstructable,
-  SanitizerConfig,
-  ToolConfig,
-} from '../../types';
-
-import {SavedData} from '../types-internal/block-data';
-import $ from './dom';
-import _ from './utils';
-
-/**
- * @class Block
- * @classdesc This class describes editor`s block, including block`s HTMLElement, data and tool
- *
- * @property {BlockTool} tool — current block tool (Paragraph, for example)
- * @property {Object} CSS — block`s css classes
- *
- */
-
-/** Import default tunes */
-import MoveUpTune from './block-tunes/block-tune-move-up';
-import DeleteTune from './block-tunes/block-tune-delete';
-import MoveDownTune from './block-tunes/block-tune-move-down';
-import SelectionUtils from './selection';
-
-/**
- * @classdesc Abstract Block class that contains Block information, Tool name and Tool class instance
- *
- * @property tool - Tool instance
- * @property html - Returns HTML content of plugin
- * @property holder - Div element that wraps block content with Tool's content. Has `ce-block` CSS class
- * @property pluginsContent - HTML content that returns by Tool's render function
- */
-export default class Block {
-
-  /**
-   * CSS classes for the Block
-   * @return {{wrapper: string, content: string}}
-   */
-  static get CSS() {
-    return {
-      wrapper: 'ce-block',
-      wrapperStretched: 'ce-block--stretched',
-      content: 'ce-block__content',
-      focused: 'ce-block--focused',
-      selected: 'ce-block--selected',
-      dropTarget: 'ce-block--drop-target',
-    };
-  }
-
-  /**
-   * Find and return all editable elements (contenteditables and native inputs) in the Tool HTML
-   *
-   * @returns {HTMLElement[]}
-   */
-  get inputs(): HTMLElement[] {
-    const content = this.holder;
-    const allowedInputTypes = ['text', 'password', 'email', 'number', 'search', 'tel', 'url'];
-
-    const selector = '[contenteditable], textarea, input:not([type]), '
-      + allowedInputTypes.map((type) => `input[type="${type}"]`).join(', ');
-
-    let inputs = _.array(content.querySelectorAll(selector));
-
-    /**
-     * If contenteditable element contains block elements, treat them as inputs.
-     */
-    inputs = inputs.reduce((result, input) => {
-      if ($.isNativeInput(input) || $.containsOnlyInlineElements(input)) {
-        return [...result, input];
-      }
-
-      return [...result, ...$.getDeepestBlockElements(input)];
-    }, []);
-
-    /**
-     * If inputs amount was changed we need to check if input index is bigger then inputs array length
-     */
-    if (this.inputIndex > inputs.length - 1) {
-      this.inputIndex = inputs.length - 1;
-    }
-
-    return inputs;
-  }
-
-  /**
-   * Return current Tool`s input
-   *
-   * @returns {HTMLElement}
-   */
-  get currentInput(): HTMLElement | Node {
-    return this.inputs[this.inputIndex];
-  }
-
-  /**
-   * Set input index to the passed element
-   *
-   * @param {HTMLElement} element
-   */
-  set currentInput(element: HTMLElement | Node) {
-    const index = this.inputs.findIndex((input) => input === element || input.contains(element));
-
-    if (index !== -1) {
-      this.inputIndex = index;
-    }
-  }
-
-  /**
-   * Return first Tool`s input
-   *
-   * @returns {HTMLElement}
-   */
-  get firstInput(): HTMLElement {
-    return this.inputs[0];
-  }
-
-  /**
-   * Return first Tool`s input
-   *
-   * @returns {HTMLElement}
-   */
-  get lastInput(): HTMLElement {
-    const inputs = this.inputs;
-
-    return inputs[inputs.length - 1];
-  }
-
-  /**
-   * Return next Tool`s input or undefined if it doesn't exist
-   *
-   * @returns {HTMLElement}
-   */
-  get nextInput(): HTMLElement {
-    return this.inputs[this.inputIndex + 1];
-  }
-
-  /**
-   * Return previous Tool`s input or undefined if it doesn't exist
-   *
-   * @returns {HTMLElement}
-   */
-  get previousInput(): HTMLElement {
-    return this.inputs[this.inputIndex - 1];
-  }
-
-  /**
-   * Returns Plugins content
-   * @return {Node}
-   */
-  get pluginsContent(): Node {
-    const pluginsContent = this.holder.querySelector(`.${Block.CSS.content}`);
-
-    if (pluginsContent && pluginsContent.childNodes.length) {
-      return pluginsContent.childNodes[0];
-    }
-
-    return null;
-  }
-
-  /**
-   * Get Block's JSON data
-   * @return {Object}
-   */
-  get data(): BlockToolData {
-    return this.save().then((savedObject) => {
-      if (savedObject && !_.isEmpty(savedObject.data)) {
-        return savedObject.data;
-      } else {
-        return {};
-      }
-    });
-  }
-
-  /**
-   * Returns tool's sanitizer config
-   * @return {object}
-   */
-  get sanitize(): SanitizerConfig {
-    return this.tool.sanitize;
-  }
-
-  /**
-   * is block mergeable
-   * We plugin have merge function then we call it mergable
-   * @return {boolean}
-   */
-  get mergeable(): boolean {
-    return typeof this.tool.merge === 'function';
-  }
-
-  /**
-   * Check block for emptiness
-   * @return {Boolean}
-   */
-  get isEmpty(): boolean {
-    const emptyText = $.isEmpty(this.pluginsContent);
-    const emptyMedia = !this.hasMedia;
-
-    return emptyText && emptyMedia;
-  }
-
-  /**
-   * Check if block has a media content such as images, iframes and other
-   * @return {Boolean}
-   */
-  get hasMedia(): boolean {
-    /**
-     * This tags represents media-content
-     * @type {string[]}
-     */
-    const mediaTags = [
-      'img',
-      'iframe',
-      'video',
-      'audio',
-      'source',
-      'input',
-      'textarea',
-      'twitterwidget',
-    ];
-
-    return !!this.holder.querySelector(mediaTags.join(','));
-  }
-
-  /**
-   * Set focused state
-   * @param {Boolean} state - 'true' to select, 'false' to remove selection
-   */
-  set focused(state: boolean) {
-    this.holder.classList.toggle(Block.CSS.focused, state);
-  }
-
-  /**
-   * Set selected state
-   * We don't need to mark Block as Selected when it is empty
-   * @param {Boolean} state - 'true' to select, 'false' to remove selection
-   */
-  set selected(state: boolean) {
-    if (state) {
-      this.holder.classList.add(Block.CSS.selected);
-    } else {
-      this.holder.classList.remove(Block.CSS.selected);
-    }
-  }
-
-  /**
-   * Returns True if it is Selected
-   * @return {boolean}
-   */
-  get selected(): boolean {
-    return this.holder.classList.contains(Block.CSS.selected);
-  }
-
-  /**
-   * Set stretched state
-   * @param {Boolean} state - 'true' to enable, 'false' to disable stretched statte
-   */
-  set stretched(state: boolean) {
-    this.holder.classList.toggle(Block.CSS.wrapperStretched, state);
-  }
-
-  /**
-   * Block Tool`s name
-   */
-  public name: string;
-
-  /**
-   * Instance of the Tool Block represents
-   */
-  public tool: BlockTool;
-
-  /**
-   * Class blueprint of the ool Block represents
-   */
-  public class: BlockToolConstructable;
-
-  /**
-   * User Tool configuration
-   */
-  public settings: ToolConfig;
-
-  /**
-   * Wrapper for Block`s content
-   */
-  public holder: HTMLDivElement;
-
-  /**
-   * Tunes used by Tool
-   */
-  public tunes: BlockTune[];
-
-  /**
-   * Editor`s API
-   */
-  private readonly api: API;
-
-  /**
-   * Focused input index
-   * @type {number}
-   */
-  private inputIndex = 0;
-
-  /**
-   * Mutation observer to handle DOM mutations
-   * @type {MutationObserver}
-   */
-  private mutationObserver: MutationObserver;
-
-  /**
-   * @constructor
-   * @param {String} toolName - Tool name that passed on initialization
-   * @param {Object} toolInstance — passed Tool`s instance that rendered the Block
-   * @param {Object} toolClass — Tool's class
-   * @param {Object} settings - default settings
-   * @param {Object} apiMethods - Editor API
-   */
-  constructor(
-    toolName: string,
-    toolInstance: BlockTool,
-    toolClass: BlockToolConstructable,
-    settings: ToolConfig,
-    apiMethods: API,
-  ) {
-    this.name = toolName;
-    this.tool = toolInstance;
-    this.class = toolClass;
-    this.settings = settings;
-    this.api = apiMethods;
-    this.holder = this.compose();
-
-    this.mutationObserver = new MutationObserver(this.didMutated);
-
-    /**
-     * @type {BlockTune[]}
-     */
-    this.tunes = this.makeTunes();
-  }
-
-  /**
-   * Calls Tool's method
-   *
-   * Method checks tool property {MethodName}. Fires method with passes params If it is instance of Function
-   *
-   * @param {String} methodName
-   * @param {Object} params
-   */
-  public call(methodName: string, params: object) {
-    /**
-     * call Tool's method with the instance context
-     */
-    if (this.tool[methodName] && this.tool[methodName] instanceof Function) {
-      this.tool[methodName].call(this.tool, params);
-    }
-  }
-
-  /**
-   * Call plugins merge method
-   * @param {Object} data
-   */
-  public async mergeWith(data: BlockToolData): Promise {
-      await this.tool.merge(data);
-  }
-  /**
-   * Extracts data from Block
-   * Groups Tool's save processing time
-   * @return {Object}
-   */
-  public async save(): Promise {
-    const extractedBlock = await this.tool.save(this.pluginsContent as HTMLElement);
-
-    /**
-     * Measuring execution time
-     */
-    const measuringStart = window.performance.now();
-    let measuringEnd;
-
-    return Promise.resolve(extractedBlock)
-      .then((finishedExtraction) => {
-        /** measure promise execution */
-        measuringEnd = window.performance.now();
-
-        return {
-          tool: this.name,
-          data: finishedExtraction,
-          time : measuringEnd - measuringStart,
-        };
-      })
-      .catch((error) => {
-        _.log(`Saving proccess for ${this.name} tool failed due to the ${error}`, 'log', 'red');
-      });
-  }
-
-  /**
-   * Uses Tool's validation method to check the correctness of output data
-   * Tool's validation method is optional
-   *
-   * @description Method returns true|false whether data passed the validation or not
-   *
-   * @param {BlockToolData} data
-   * @returns {Promise} valid
-   */
-  public async validate(data: BlockToolData): Promise {
-    let isValid = true;
-
-    if (this.tool.validate instanceof Function) {
-      isValid = await this.tool.validate(data);
-    }
-
-    return isValid;
-  }
-
-  /**
-   * Make an array with default settings
-   * Each block has default tune instance that have states
-   * @return {BlockTune[]}
-   */
-  public makeTunes(): BlockTune[] {
-    const tunesList = [MoveUpTune, DeleteTune, MoveDownTune];
-
-    // Pluck tunes list and return tune instances with passed Editor API and settings
-    return tunesList.map( (tune: BlockTuneConstructable) => {
-      return new tune({
-        api: this.api,
-        settings: this.settings,
-      });
-    });
-  }
-
-  /**
-   * Enumerates initialized tunes and returns fragment that can be appended to the toolbars area
-   * @return {DocumentFragment}
-   */
-  public renderTunes(): DocumentFragment {
-    const tunesElement = document.createDocumentFragment();
-
-    this.tunes.forEach( (tune) => {
-      $.append(tunesElement, tune.render());
-    });
-
-    return tunesElement;
-  }
-
-  /**
-   * Toggle drop target state
-   * @param {boolean} state
-   */
-  public set dropTarget(state) {
-    this.holder.classList.toggle(Block.CSS.dropTarget, state);
-  }
-
-  /**
-   * Update current input index with selection anchor node
-   */
-  public updateCurrentInput(): void {
-    this.currentInput = SelectionUtils.anchorNode;
-  }
-
-  /**
-   * Is fired when Block will be selected as current
-   */
-  public willSelect(): void {
-    /**
-     * Observe DOM mutations to update Block inputs
-     */
-    this.mutationObserver.observe(this.holder, {childList: true, subtree: true});
-  }
-
-  /**
-   * Is fired when Block will be unselected
-   */
-  public willUnselect() {
-    this.mutationObserver.disconnect();
-  }
-
-  /**
-   * Is fired when DOM mutation has been happened
-   */
-  private didMutated = () => {
-    this.updateCurrentInput();
-  }
-
-  /**
-   * Make default Block wrappers and put Tool`s content there
-   * @returns {HTMLDivElement}
-   */
-  private compose(): HTMLDivElement {
-    const wrapper = $.make('div', Block.CSS.wrapper) as HTMLDivElement,
-      contentNode = $.make('div', Block.CSS.content),
-      pluginsContent  = this.tool.render();
-
-    contentNode.appendChild(pluginsContent);
-    wrapper.appendChild(contentNode);
-    return wrapper;
-  }
-}
diff --git a/src/components/block/api.ts b/src/components/block/api.ts
new file mode 100644
index 000000000..34e23d897
--- /dev/null
+++ b/src/components/block/api.ts
@@ -0,0 +1,116 @@
+import Block from './index';
+import { BlockToolData, ToolConfig } from '../../../types/tools';
+import { SavedData } from '../../../types/data-formats';
+import { BlockAPI as BlockAPIInterface } from '../../../types/api';
+
+/**
+ * Constructs new BlockAPI object
+ *
+ * @class
+ *
+ * @param {Block} block - Block to expose
+ */
+function BlockAPI(
+  block: Block
+): void {
+  const blockAPI: BlockAPIInterface = {
+    /**
+     * Tool name
+     *
+     * @returns {string}
+     */
+    get name(): string {
+      return block.name;
+    },
+
+    /**
+     * Tool config passed on Editor's initialization
+     *
+     * @returns {ToolConfig}
+     */
+    get config(): ToolConfig {
+      return block.config;
+    },
+
+    /**
+     * .ce-block element, that wraps plugin contents
+     *
+     * @returns {HTMLElement}
+     */
+    get holder(): HTMLElement {
+      return block.holder;
+    },
+
+    /**
+     * True if Block content is empty
+     *
+     * @returns {boolean}
+     */
+    get isEmpty(): boolean {
+      return block.isEmpty;
+    },
+
+    /**
+     * True if Block is selected with Cross-Block selection
+     *
+     * @returns {boolean}
+     */
+    get selected(): boolean {
+      return block.selected;
+    },
+
+    /**
+     * Set Block's stretch state
+     *
+     * @param {boolean} state — state to set
+     */
+    set stretched(state: boolean) {
+      block.stretched = state;
+    },
+
+    /**
+     * True if Block is stretched
+     *
+     * @returns {boolean}
+     */
+    get stretched(): boolean {
+      return block.stretched;
+    },
+
+    /**
+     * Call Tool method with errors handler under-the-hood
+     *
+     * @param {string} methodName - method to call
+     * @param {object} param - object with parameters
+     *
+     * @returns {unknown}
+     */
+    call(methodName: string, param?: object): unknown {
+      return block.call(methodName, param);
+    },
+
+    /**
+     * Save Block content
+     *
+     * @returns {Promise}
+     */
+    save(): Promise {
+      return block.save();
+    },
+
+    /**
+     * Validate Block data
+     *
+     * @param {BlockToolData} data - data to validate
+     *
+     * @returns {Promise}
+     */
+    validate(data: BlockToolData): Promise {
+      return block.validate(data);
+    },
+  };
+
+  Object.setPrototypeOf(this, blockAPI);
+}
+
+export default BlockAPI;
diff --git a/src/components/block/index.ts b/src/components/block/index.ts
new file mode 100644
index 000000000..fef141264
--- /dev/null
+++ b/src/components/block/index.ts
@@ -0,0 +1,723 @@
+import {
+  BlockAPI as BlockAPIInterface,
+  BlockTool,
+  BlockToolConstructable,
+  BlockToolData,
+  BlockTune,
+  BlockTuneConstructable,
+  SanitizerConfig,
+  ToolConfig,
+  ToolSettings
+} from '../../../types';
+
+import { SavedData } from '../../../types/data-formats';
+import $ from '../dom';
+import * as _ from '../utils';
+import ApiModules from '../modules/api';
+import BlockAPI from './api';
+import { ToolType } from '../modules/tools';
+
+/** Import default tunes */
+import MoveUpTune from '../block-tunes/block-tune-move-up';
+import DeleteTune from '../block-tunes/block-tune-delete';
+import MoveDownTune from '../block-tunes/block-tune-move-down';
+import SelectionUtils from '../selection';
+
+/**
+ * Interface describes Block class constructor argument
+ */
+interface BlockConstructorOptions {
+  /**
+   * Tool's name
+   */
+  name: string;
+
+  /**
+   * Initial Block data
+   */
+  data: BlockToolData;
+
+  /**
+   * Tool's class or constructor function
+   */
+  Tool: BlockToolConstructable;
+
+  /**
+   * Tool settings from initial config
+   */
+  settings: ToolSettings;
+
+  /**
+   * Editor's API methods
+   */
+  api: ApiModules;
+
+  /**
+   * This flag indicates that the Block should be constructed in the read-only mode.
+   */
+  readOnly: boolean;
+}
+
+/**
+ * @class Block
+ * @classdesc This class describes editor`s block, including block`s HTMLElement, data and tool
+ *
+ * @property {BlockTool} tool — current block tool (Paragraph, for example)
+ * @property {object} CSS — block`s css classes
+ *
+ */
+
+/**
+ * Available Block Tool API methods
+ */
+export enum BlockToolAPI {
+  /**
+   * @todo remove method in 3.0.0
+   * @deprecated — use 'rendered' hook instead
+   */
+  APPEND_CALLBACK = 'appendCallback',
+  RENDERED = 'rendered',
+  MOVED = 'moved',
+  UPDATED = 'updated',
+  REMOVED = 'removed',
+  ON_PASTE = 'onPaste',
+}
+
+/**
+ * @classdesc Abstract Block class that contains Block information, Tool name and Tool class instance
+ *
+ * @property {BlockTool} tool - Tool instance
+ * @property {HTMLElement} holder - Div element that wraps block content with Tool's content. Has `ce-block` CSS class
+ * @property {HTMLElement} pluginsContent - HTML content that returns by Tool's render function
+ */
+export default class Block {
+  /**
+   * CSS classes for the Block
+   *
+   * @returns {{wrapper: string, content: string}}
+   */
+  public static get CSS(): {[name: string]: string} {
+    return {
+      wrapper: 'ce-block',
+      wrapperStretched: 'ce-block--stretched',
+      content: 'ce-block__content',
+      focused: 'ce-block--focused',
+      selected: 'ce-block--selected',
+      dropTarget: 'ce-block--drop-target',
+    };
+  }
+
+  /**
+   * Block Tool`s name
+   */
+  public name: string;
+
+  /**
+   * Instance of the Tool Block represents
+   */
+  public tool: BlockTool;
+
+  /**
+   * Class blueprint of the ool Block represents
+   */
+  public class: BlockToolConstructable;
+
+  /**
+   * User Tool configuration
+   */
+  public settings: ToolConfig;
+
+  /**
+   * Wrapper for Block`s content
+   */
+  public holder: HTMLDivElement;
+
+  /**
+   * Tunes used by Tool
+   */
+  public tunes: BlockTune[];
+
+  /**
+   * Tool's user configuration
+   */
+  public readonly config: ToolConfig;
+
+  /**
+   * Cached inputs
+   *
+   * @type {HTMLElement[]}
+   */
+  private cachedInputs: HTMLElement[] = [];
+
+  /**
+   * Editor`s API module
+   */
+  private readonly api: ApiModules;
+
+  /**
+   * Focused input index
+   *
+   * @type {number}
+   */
+  private inputIndex = 0;
+
+  /**
+   * Mutation observer to handle DOM mutations
+   *
+   * @type {MutationObserver}
+   */
+  private mutationObserver: MutationObserver;
+
+  /**
+   * Debounce Timer
+   *
+   * @type {number}
+   */
+  private readonly modificationDebounceTimer = 450;
+
+  /**
+   * Is fired when DOM mutation has been happened
+   */
+  private didMutated = _.debounce((): void => {
+    /**
+     * Drop cache
+     */
+    this.cachedInputs = [];
+
+    /**
+     * Update current input
+     */
+    this.updateCurrentInput();
+
+    this.call(BlockToolAPI.UPDATED);
+  }, this.modificationDebounceTimer);
+
+  /**
+   * Current block API interface
+   */
+  private readonly blockAPI: BlockAPIInterface;
+
+  /**
+   * @param {object} options - block constructor options
+   * @param {string} options.name - Tool name that passed on initialization
+   * @param {BlockToolData} options.data - Tool's initial data
+   * @param {BlockToolConstructable} options.Tool — Tool's class
+   * @param {ToolSettings} options.settings - default tool's config
+   * @param options.api - Editor API module for pass it to the Block Tunes
+   * @param {boolean} options.readOnly - Read-Only flag
+   */
+  constructor({
+    name,
+    data,
+    Tool,
+    settings,
+    api,
+    readOnly,
+  }: BlockConstructorOptions) {
+    this.name = name;
+    this.class = Tool;
+    this.settings = settings;
+    this.config = settings.config || {};
+    this.api = api;
+    this.blockAPI = new BlockAPI(this);
+
+    this.mutationObserver = new MutationObserver(this.didMutated);
+
+    this.tool = new Tool({
+      data,
+      config: this.config,
+      api: this.api.getMethodsForTool(name, ToolType.Block),
+      block: this.blockAPI,
+      readOnly,
+    });
+
+    this.holder = this.compose();
+    /**
+     * @type {BlockTune[]}
+     */
+    this.tunes = this.makeTunes();
+  }
+
+  /**
+   * Find and return all editable elements (contenteditables and native inputs) in the Tool HTML
+   *
+   * @returns {HTMLElement[]}
+   */
+  public get inputs(): HTMLElement[] {
+    /**
+     * Return from cache if existed
+     */
+    if (this.cachedInputs.length !== 0) {
+      return this.cachedInputs;
+    }
+
+    const inputs = $.findAllInputs(this.holder);
+
+    /**
+     * If inputs amount was changed we need to check if input index is bigger then inputs array length
+     */
+    if (this.inputIndex > inputs.length - 1) {
+      this.inputIndex = inputs.length - 1;
+    }
+
+    /**
+     * Cache inputs
+     */
+    this.cachedInputs = inputs;
+
+    return inputs;
+  }
+
+  /**
+   * Return current Tool`s input
+   *
+   * @returns {HTMLElement}
+   */
+  public get currentInput(): HTMLElement | Node {
+    return this.inputs[this.inputIndex];
+  }
+
+  /**
+   * Set input index to the passed element
+   *
+   * @param {HTMLElement | Node} element - HTML Element to set as current input
+   */
+  public set currentInput(element: HTMLElement | Node) {
+    const index = this.inputs.findIndex((input) => input === element || input.contains(element));
+
+    if (index !== -1) {
+      this.inputIndex = index;
+    }
+  }
+
+  /**
+   * Return first Tool`s input
+   *
+   * @returns {HTMLElement}
+   */
+  public get firstInput(): HTMLElement {
+    return this.inputs[0];
+  }
+
+  /**
+   * Return first Tool`s input
+   *
+   * @returns {HTMLElement}
+   */
+  public get lastInput(): HTMLElement {
+    const inputs = this.inputs;
+
+    return inputs[inputs.length - 1];
+  }
+
+  /**
+   * Return next Tool`s input or undefined if it doesn't exist
+   *
+   * @returns {HTMLElement}
+   */
+  public get nextInput(): HTMLElement {
+    return this.inputs[this.inputIndex + 1];
+  }
+
+  /**
+   * Return previous Tool`s input or undefined if it doesn't exist
+   *
+   * @returns {HTMLElement}
+   */
+  public get previousInput(): HTMLElement {
+    return this.inputs[this.inputIndex - 1];
+  }
+
+  /**
+   * Get Block's JSON data
+   *
+   * @returns {object}
+   */
+  public get data(): Promise {
+    return this.save().then((savedObject) => {
+      if (savedObject && !_.isEmpty(savedObject.data)) {
+        return savedObject.data;
+      } else {
+        return {};
+      }
+    });
+  }
+
+  /**
+   * Returns tool's sanitizer config
+   *
+   * @returns {object}
+   */
+  public get sanitize(): SanitizerConfig {
+    return this.tool.sanitize;
+  }
+
+  /**
+   * is block mergeable
+   * We plugin have merge function then we call it mergable
+   *
+   * @returns {boolean}
+   */
+  public get mergeable(): boolean {
+    return _.isFunction(this.tool.merge);
+  }
+
+  /**
+   * Check block for emptiness
+   *
+   * @returns {boolean}
+   */
+  public get isEmpty(): boolean {
+    const emptyText = $.isEmpty(this.pluginsContent);
+    const emptyMedia = !this.hasMedia;
+
+    return emptyText && emptyMedia;
+  }
+
+  /**
+   * Check if block has a media content such as images, iframes and other
+   *
+   * @returns {boolean}
+   */
+  public get hasMedia(): boolean {
+    /**
+     * This tags represents media-content
+     *
+     * @type {string[]}
+     */
+    const mediaTags = [
+      'img',
+      'iframe',
+      'video',
+      'audio',
+      'source',
+      'input',
+      'textarea',
+      'twitterwidget',
+    ];
+
+    return !!this.holder.querySelector(mediaTags.join(','));
+  }
+
+  /**
+   * Set focused state
+   *
+   * @param {boolean} state - 'true' to select, 'false' to remove selection
+   */
+  public set focused(state: boolean) {
+    this.holder.classList.toggle(Block.CSS.focused, state);
+  }
+
+  /**
+   * Get Block's focused state
+   */
+  public get focused(): boolean {
+    return this.holder.classList.contains(Block.CSS.focused);
+  }
+
+  /**
+   * Set selected state
+   * We don't need to mark Block as Selected when it is empty
+   *
+   * @param {boolean} state - 'true' to select, 'false' to remove selection
+   */
+  public set selected(state: boolean) {
+    if (state) {
+      this.holder.classList.add(Block.CSS.selected);
+    } else {
+      this.holder.classList.remove(Block.CSS.selected);
+    }
+  }
+
+  /**
+   * Returns True if it is Selected
+   *
+   * @returns {boolean}
+   */
+  public get selected(): boolean {
+    return this.holder.classList.contains(Block.CSS.selected);
+  }
+
+  /**
+   * Set stretched state
+   *
+   * @param {boolean} state - 'true' to enable, 'false' to disable stretched statte
+   */
+  public set stretched(state: boolean) {
+    this.holder.classList.toggle(Block.CSS.wrapperStretched, state);
+  }
+
+  /**
+   * Return Block's stretched state
+   *
+   * @returns {boolean}
+   */
+  public get stretched(): boolean {
+    return this.holder.classList.contains(Block.CSS.wrapperStretched);
+  }
+
+  /**
+   * Toggle drop target state
+   *
+   * @param {boolean} state - 'true' if block is drop target, false otherwise
+   */
+  public set dropTarget(state) {
+    this.holder.classList.toggle(Block.CSS.dropTarget, state);
+  }
+
+  /**
+   * Returns Plugins content
+   *
+   * @returns {HTMLElement}
+   */
+  public get pluginsContent(): HTMLElement {
+    const blockContentNodes = this.holder.querySelector(`.${Block.CSS.content}`);
+
+    if (blockContentNodes && blockContentNodes.childNodes.length) {
+      /**
+       * Editors Block content can contain different Nodes from extensions
+       * We use DOM isExtensionNode to ignore such Nodes and return first Block that does not match filtering list
+       */
+      for (let child = blockContentNodes.childNodes.length - 1; child >= 0; child--) {
+        const contentNode = blockContentNodes.childNodes[child];
+
+        if (!$.isExtensionNode(contentNode)) {
+          return contentNode as HTMLElement;
+        }
+      }
+    }
+
+    return null;
+  }
+
+  /**
+   * Calls Tool's method
+   *
+   * Method checks tool property {MethodName}. Fires method with passes params If it is instance of Function
+   *
+   * @param {string} methodName - method to call
+   * @param {object} params - method argument
+   */
+  public call(methodName: string, params?: object): void {
+    /**
+     * call Tool's method with the instance context
+     */
+    if (this.tool[methodName] && this.tool[methodName] instanceof Function) {
+      if (methodName === BlockToolAPI.APPEND_CALLBACK) {
+        _.log(
+          '`appendCallback` hook is deprecated and will be removed in the next major release. ' +
+          'Use `rendered` hook instead',
+          'warn'
+        );
+      }
+
+      try {
+        // eslint-disable-next-line no-useless-call
+        this.tool[methodName].call(this.tool, params);
+      } catch (e) {
+        _.log(`Error during '${methodName}' call: ${e.message}`, 'error');
+      }
+    }
+  }
+
+  /**
+   * Call plugins merge method
+   *
+   * @param {BlockToolData} data - data to merge
+   */
+  public async mergeWith(data: BlockToolData): Promise {
+    await this.tool.merge(data);
+  }
+
+  /**
+   * Extracts data from Block
+   * Groups Tool's save processing time
+   *
+   * @returns {object}
+   */
+  public async save(): Promise {
+    const extractedBlock = await this.tool.save(this.pluginsContent as HTMLElement);
+
+    /**
+     * Measuring execution time
+     */
+    const measuringStart = window.performance.now();
+    let measuringEnd;
+
+    return Promise.resolve(extractedBlock)
+      .then((finishedExtraction) => {
+        /** measure promise execution */
+        measuringEnd = window.performance.now();
+
+        return {
+          tool: this.name,
+          data: finishedExtraction,
+          time: measuringEnd - measuringStart,
+        };
+      })
+      .catch((error) => {
+        _.log(`Saving proccess for ${this.name} tool failed due to the ${error}`, 'log', 'red');
+      });
+  }
+
+  /**
+   * Uses Tool's validation method to check the correctness of output data
+   * Tool's validation method is optional
+   *
+   * @description Method returns true|false whether data passed the validation or not
+   *
+   * @param {BlockToolData} data - data to validate
+   * @returns {Promise} valid
+   */
+  public async validate(data: BlockToolData): Promise {
+    let isValid = true;
+
+    if (this.tool.validate instanceof Function) {
+      isValid = await this.tool.validate(data);
+    }
+
+    return isValid;
+  }
+
+  /**
+   * Make an array with default settings
+   * Each block has default tune instance that have states
+   *
+   * @returns {BlockTune[]}
+   */
+  public makeTunes(): BlockTune[] {
+    const tunesList = [
+      {
+        name: 'moveUp',
+        Tune: MoveUpTune,
+      },
+      {
+        name: 'delete',
+        Tune: DeleteTune,
+      },
+      {
+        name: 'moveDown',
+        Tune: MoveDownTune,
+      },
+    ];
+
+    // Pluck tunes list and return tune instances with passed Editor API and settings
+    return tunesList.map(({ name, Tune }: {name: string; Tune: BlockTuneConstructable}) => {
+      return new Tune({
+        api: this.api.getMethodsForTool(name, ToolType.Tune),
+        settings: this.config,
+      });
+    });
+  }
+
+  /**
+   * Enumerates initialized tunes and returns fragment that can be appended to the toolbars area
+   *
+   * @returns {DocumentFragment}
+   */
+  public renderTunes(): DocumentFragment {
+    const tunesElement = document.createDocumentFragment();
+
+    this.tunes.forEach((tune) => {
+      $.append(tunesElement, tune.render());
+    });
+
+    return tunesElement;
+  }
+
+  /**
+   * Update current input index with selection anchor node
+   */
+  public updateCurrentInput(): void {
+    /**
+     * If activeElement is native input, anchorNode points to its parent.
+     * So if it is native input use it instead of anchorNode
+     *
+     * If anchorNode is undefined, also use activeElement
+     */
+    this.currentInput = $.isNativeInput(document.activeElement) || !SelectionUtils.anchorNode
+      ? document.activeElement
+      : SelectionUtils.anchorNode;
+  }
+
+  /**
+   * Is fired when Block will be selected as current
+   */
+  public willSelect(): void {
+    /**
+     * Observe DOM mutations to update Block inputs
+     */
+    this.mutationObserver.observe(
+      this.holder.firstElementChild,
+      {
+        childList: true,
+        subtree: true,
+        characterData: true,
+        attributes: true,
+      }
+    );
+
+    /**
+     * Mutation observer doesn't track changes in " tags
-   * @return {object}
+   *
+   * @returns {object}
    */
-  static get sanitize(): SanitizerConfig {
+  public static get sanitize(): SanitizerConfig {
     return {
       b: {},
     } as SanitizerConfig;
@@ -56,13 +61,15 @@ export default class BoldInlineTool implements InlineTool {
     this.nodes.button = document.createElement('button') as HTMLButtonElement;
     this.nodes.button.type = 'button';
     this.nodes.button.classList.add(this.CSS.button, this.CSS.buttonModifier);
-    this.nodes.button.appendChild($.svg('bold', 13, 15));
+    this.nodes.button.appendChild($.svg('bold', 12, 14));
+
     return this.nodes.button;
   }
 
   /**
    * Wrap range with  tag
-   * @param {Range} range
+   *
+   * @param {Range} range - range to wrap
    */
   public surround(range: Range): void {
     document.execCommand(this.commandName);
@@ -70,17 +77,23 @@ export default class BoldInlineTool implements InlineTool {
 
   /**
    * Check selection and set activated state to button if there are  tag
-   * @param {Selection} selection
+   *
+   * @param {Selection} selection - selection to check
+   *
+   * @returns {boolean}
    */
   public checkState(selection: Selection): boolean {
     const isActive = document.queryCommandState(this.commandName);
 
     this.nodes.button.classList.toggle(this.CSS.buttonActive, isActive);
+
     return isActive;
   }
 
   /**
    * Set a shortcut
+   *
+   * @returns {boolean}
    */
   public get shortcut(): string {
     return 'CMD+B';
diff --git a/src/components/inline-tools/inline-tool-italic.ts b/src/components/inline-tools/inline-tool-italic.ts
index 5ae07c3ad..da728b81f 100644
--- a/src/components/inline-tools/inline-tool-italic.ts
+++ b/src/components/inline-tools/inline-tool-italic.ts
@@ -1,5 +1,5 @@
 import $ from '../dom';
-import {InlineTool, SanitizerConfig} from '../../../types';
+import { InlineTool, SanitizerConfig } from '../../../types';
 
 /**
  * Italic Tool
@@ -9,20 +9,25 @@ import {InlineTool, SanitizerConfig} from '../../../types';
  * Style selected text with italic
  */
 export default class ItalicInlineTool implements InlineTool {
-
   /**
    * Specifies Tool as Inline Toolbar Tool
    *
-   * @return {boolean}
+   * @returns {boolean}
    */
   public static isInline = true;
 
+  /**
+   * Title for hover-tooltip
+   */
+  public static title = 'Italic';
+
   /**
    * Sanitizer Rule
    * Leave  tags
-   * @return {object}
+   *
+   * @returns {object}
    */
-  static get sanitize(): SanitizerConfig {
+  public static get sanitize(): SanitizerConfig {
     return {
       i: {},
     } as SanitizerConfig;
@@ -56,13 +61,15 @@ export default class ItalicInlineTool implements InlineTool {
     this.nodes.button = document.createElement('button') as HTMLButtonElement;
     this.nodes.button.type = 'button';
     this.nodes.button.classList.add(this.CSS.button, this.CSS.buttonModifier);
-    this.nodes.button.appendChild($.svg('italic', 6, 15));
+    this.nodes.button.appendChild($.svg('italic', 4, 11));
+
     return this.nodes.button;
   }
 
   /**
    * Wrap range with  tag
-   * @param {Range} range
+   *
+   * @param {Range} range - range to wrap
    */
   public surround(range: Range): void {
     document.execCommand(this.commandName);
@@ -70,12 +77,14 @@ export default class ItalicInlineTool implements InlineTool {
 
   /**
    * Check selection and set activated state to button if there are  tag
-   * @param {Selection} selection
+   *
+   * @param {Selection} selection - selection to check
    */
   public checkState(selection: Selection): boolean {
     const isActive = document.queryCommandState(this.commandName);
 
     this.nodes.button.classList.toggle(this.CSS.buttonActive, isActive);
+
     return isActive;
   }
 
diff --git a/src/components/inline-tools/inline-tool-link.ts b/src/components/inline-tools/inline-tool-link.ts
index 9eaf38be6..b55120bb6 100644
--- a/src/components/inline-tools/inline-tool-link.ts
+++ b/src/components/inline-tools/inline-tool-link.ts
@@ -1,9 +1,9 @@
 import SelectionUtils from '../selection';
 
 import $ from '../dom';
-import _ from '../utils';
-import {API, InlineTool, SanitizerConfig} from '../../../types';
-import {Notifier, Toolbar} from '../../../types/api';
+import * as _ from '../utils';
+import { API, InlineTool, SanitizerConfig } from '../../../types';
+import { Notifier, Toolbar, I18n } from '../../../types/api';
 
 /**
  * Link Tool
@@ -13,20 +13,25 @@ import {Notifier, Toolbar} from '../../../types/api';
  * Wrap selected text with  tag
  */
 export default class LinkInlineTool implements InlineTool {
-
   /**
    * Specifies Tool as Inline Toolbar Tool
    *
-   * @return {boolean}
+   * @returns {boolean}
    */
   public static isInline = true;
 
+  /**
+   * Title for hover-tooltip
+   */
+  public static title = 'Link';
+
   /**
    * Sanitizer Rule
    * Leave  tags
-   * @return {object}
+   *
+   * @returns {object}
    */
-  static get sanitize(): SanitizerConfig {
+  public static get sanitize(): SanitizerConfig {
     return {
       a: {
         href: true,
@@ -78,10 +83,15 @@ export default class LinkInlineTool implements InlineTool {
   /**
    * Input opening state
    */
-  private inputOpened: boolean = false;
+  private inputOpened = false;
 
   /**
-   * Available Inline Toolbar methods (open/close)
+   * Available Toolbar methods (open/close)
+   */
+  private toolbar: Toolbar;
+
+  /**
+   * Available inline toolbar methods (open/close)
    */
   private inlineToolbar: Toolbar;
 
@@ -91,11 +101,18 @@ export default class LinkInlineTool implements InlineTool {
   private notifier: Notifier;
 
   /**
-   * @param {{api: API}} - Editor.js API
+   * I18n API
    */
-  constructor({api}) {
-    this.inlineToolbar = api.toolbar;
+  private i18n: I18n;
+
+  /**
+   * @param {API} api - Editor.js API
+   */
+  constructor({ api }) {
+    this.toolbar = api.toolbar;
+    this.inlineToolbar = api.inlineToolbar;
     this.notifier = api.notifier;
+    this.i18n = api.i18n;
     this.selection = new SelectionUtils();
   }
 
@@ -106,8 +123,9 @@ export default class LinkInlineTool implements InlineTool {
     this.nodes.button = document.createElement('button') as HTMLButtonElement;
     this.nodes.button.type = 'button';
     this.nodes.button.classList.add(this.CSS.button, this.CSS.buttonModifier);
-    this.nodes.button.appendChild($.svg('link', 15, 14));
-    this.nodes.button.appendChild($.svg('unlink', 16, 18));
+    this.nodes.button.appendChild($.svg('link', 14, 10));
+    this.nodes.button.appendChild($.svg('unlink', 15, 11));
+
     return this.nodes.button;
   }
 
@@ -116,19 +134,21 @@ export default class LinkInlineTool implements InlineTool {
    */
   public renderActions(): HTMLElement {
     this.nodes.input = document.createElement('input') as HTMLInputElement;
-    this.nodes.input.placeholder = 'Add a link';
+    this.nodes.input.placeholder = this.i18n.t('Add a link');
     this.nodes.input.classList.add(this.CSS.input);
     this.nodes.input.addEventListener('keydown', (event: KeyboardEvent) => {
       if (event.keyCode === this.ENTER_KEY) {
         this.enterPressed(event);
       }
     });
+
     return this.nodes.input;
   }
 
   /**
    * Handle clicks on the Inline Toolbar icon
-   * @param {Range} range
+   *
+   * @param {Range} range - range to wrap with link
    */
   public surround(range: Range): void {
     /**
@@ -156,7 +176,8 @@ export default class LinkInlineTool implements InlineTool {
         this.unlink();
         this.closeActions();
         this.checkState();
-        this.inlineToolbar.close();
+        this.toolbar.close();
+
         return;
       }
     }
@@ -166,7 +187,8 @@ export default class LinkInlineTool implements InlineTool {
 
   /**
    * Check selection and set activated state to button if there are  tag
-   * @param {Selection} selection
+   *
+   * @param {Selection} selection - selection to check
    */
   public checkState(selection?: Selection): boolean {
     const anchorTag = this.selection.findParentTag('A');
@@ -180,6 +202,7 @@ export default class LinkInlineTool implements InlineTool {
        * Fill input value with link href
        */
       const hrefAttr = anchorTag.getAttribute('href');
+
       this.nodes.input.value = hrefAttr !== 'null' ? hrefAttr : '';
 
       this.selection.save();
@@ -205,6 +228,9 @@ export default class LinkInlineTool implements InlineTool {
     return 'CMD+K';
   }
 
+  /**
+   * Show/close link input
+   */
   private toggleActions(): void {
     if (!this.inputOpened) {
       this.openActions(true);
@@ -216,7 +242,7 @@ export default class LinkInlineTool implements InlineTool {
   /**
    * @param {boolean} needFocus - on link creation we need to focus input. On editing - nope.
    */
-  private openActions(needFocus: boolean = false): void {
+  private openActions(needFocus = false): void {
     this.nodes.input.classList.add(this.CSS.inputShowed);
     if (needFocus) {
       this.nodes.input.focus();
@@ -226,13 +252,15 @@ export default class LinkInlineTool implements InlineTool {
 
   /**
    * Close input
+   *
    * @param {boolean} clearSavedSelection — we don't need to clear saved selection
    *                                        on toggle-clicks on the icon of opened Toolbar
    */
-  private closeActions(clearSavedSelection: boolean = true): void {
+  private closeActions(clearSavedSelection = true): void {
     if (this.selection.isFakeBackgroundEnabled) {
       // if actions is broken by other selection We need to save new selection
       const currentSelection = new SelectionUtils();
+
       currentSelection.save();
 
       this.selection.restore();
@@ -252,7 +280,8 @@ export default class LinkInlineTool implements InlineTool {
 
   /**
    * Enter pressed on input
-   * @param {KeyboardEvent} event
+   *
+   * @param {KeyboardEvent} event - enter keydown event
    */
   private enterPressed(event: KeyboardEvent): void {
     let value = this.nodes.input.value || '';
@@ -262,16 +291,18 @@ export default class LinkInlineTool implements InlineTool {
       this.unlink();
       event.preventDefault();
       this.closeActions();
+
+      return;
     }
 
     if (!this.validateURL(value)) {
-
       this.notifier.show({
         message: 'Pasted link is not valid.',
         style: 'error',
       });
 
       _.log('Incorrect Link pasted', 'warn', value);
+
       return;
     }
 
@@ -288,16 +319,15 @@ export default class LinkInlineTool implements InlineTool {
     event.preventDefault();
     event.stopPropagation();
     event.stopImmediatePropagation();
-
-    this.closeActions();
+    this.selection.collapseToEnd();
     this.inlineToolbar.close();
-    this.checkState();
   }
 
   /**
    * Detects if passed string is URL
-   * @param  {string}  str
-   * @return {Boolean}
+   *
+   * @param {string} str - string to validate
+   * @returns {boolean}
    */
   private validateURL(str: string): boolean {
     /**
@@ -310,23 +340,26 @@ export default class LinkInlineTool implements InlineTool {
    * Process link before injection
    * - sanitize
    * - add protocol for links like 'google.com'
+   *
    * @param {string} link - raw user input
    */
   private prepareLink(link: string): string {
     link = link.trim();
     link = this.addProtocol(link);
+
     return link;
   }
 
   /**
    * Add 'http' protocol to the links like 'vc.ru', 'google.com'
-   * @param {String} link
+   *
+   * @param {string} link - string to process
    */
   private addProtocol(link: string): string {
     /**
      * If protocol already exists, do nothing
      */
-    if (/^(\w+):\/\//.test(link)) {
+    if (/^(\w+):(\/\/)?/.test(link)) {
       return link;
     }
 
@@ -336,9 +369,9 @@ export default class LinkInlineTool implements InlineTool {
      *     2) Anchors looks like "#results"
      *     3) Protocol-relative URLs like "//google.com"
      */
-    const isInternal = /^\/[^\/\s]/.test(link),
-      isAnchor = link.substring(0, 1) === '#',
-      isProtocolRelative = /^\/\/[^\/\s]/.test(link);
+    const isInternal = /^\/[^/\s]/.test(link),
+        isAnchor = link.substring(0, 1) === '#',
+        isProtocolRelative = /^\/\/[^/\s]/.test(link);
 
     if (!isInternal && !isAnchor && !isProtocolRelative) {
       link = 'http://' + link;
@@ -349,10 +382,10 @@ export default class LinkInlineTool implements InlineTool {
 
   /**
    * Inserts  tag with "href"
+   *
    * @param {string} link - "href" value
    */
   private insertLink(link: string): void {
-
     /**
      * Edit all link, not selected part
      */
diff --git a/src/components/modules/api/blocks.ts b/src/components/modules/api/blocks.ts
index 130311b48..a65db8b09 100644
--- a/src/components/modules/api/blocks.ts
+++ b/src/components/modules/api/blocks.ts
@@ -1,10 +1,9 @@
+import { BlockAPI as BlockAPIInterface, Blocks } from '../../../../types/api';
+import { BlockToolData, OutputData, ToolConfig } from '../../../../types';
+import * as _ from './../../utils';
+import BlockAPI from '../../block/api';
 import Module from '../../__module';
 
-import {Blocks} from '../../../../types/api';
-import {OutputData} from '../../../../types';
-import Block from '../../block';
-import {ModuleConfig} from '../../../types-internal/module-config';
-
 /**
  * @class BlocksAPI
  * provides with methods working with Block
@@ -12,26 +11,30 @@ import {ModuleConfig} from '../../../types-internal/module-config';
 export default class BlocksAPI extends Module {
   /**
    * Available methods
-   * @return {Blocks}
+   *
+   * @returns {Blocks}
    */
-  get methods(): Blocks {
+  public get methods(): Blocks {
     return {
-      clear: () => this.clear(),
-      render: (data: OutputData) => this.render(data),
-      renderFromHTML: (data: string) => this.renderFromHTML(data),
-      delete: () => this.delete(),
-      swap: (fromIndex: number, toIndex: number) => this.swap(fromIndex, toIndex),
-      getBlockByIndex: (index: number) => this.getBlockByIndex(index),
-      getCurrentBlockIndex: () => this.getCurrentBlockIndex(),
-      getBlocksCount: () => this.getBlocksCount(),
-      stretchBlock: (index: number, status: boolean = true) => this.stretchBlock(index, status),
-      insertNewBlock: () => this.insertNewBlock(),
+      clear: (): void => this.clear(),
+      render: (data: OutputData): Promise => this.render(data),
+      renderFromHTML: (data: string): Promise => this.renderFromHTML(data),
+      delete: (index?: number): void => this.delete(index),
+      swap: (fromIndex: number, toIndex: number): void => this.swap(fromIndex, toIndex),
+      move: (toIndex: number, fromIndex?: number): void => this.move(toIndex, fromIndex),
+      getBlockByIndex: (index: number): BlockAPIInterface | void => this.getBlockByIndex(index),
+      getCurrentBlockIndex: (): number => this.getCurrentBlockIndex(),
+      getBlocksCount: (): number => this.getBlocksCount(),
+      stretchBlock: (index: number, status = true): void => this.stretchBlock(index, status),
+      insertNewBlock: (): void => this.insertNewBlock(),
+      insert: this.insert,
     };
   }
 
   /**
    * Returns Blocks count
-   * @return {number}
+   *
+   * @returns {number}
    */
   public getBlocksCount(): number {
     return this.Editor.BlockManager.blocks.length;
@@ -39,29 +42,44 @@ export default class BlocksAPI extends Module {
 
   /**
    * Returns current block index
-   * @return {number}
+   *
+   * @returns {number}
    */
   public getCurrentBlockIndex(): number {
     return this.Editor.BlockManager.currentBlockIndex;
   }
 
   /**
-   * Returns Block holder by Block index
-   * @param {Number} index
+   * Returns BlockAPI object by Block index
    *
-   * @return {HTMLElement}
+   * @param {number} index - index to get
    */
-  public getBlockByIndex(index: number): HTMLElement {
+  public getBlockByIndex(index: number): BlockAPIInterface | void {
     const block = this.Editor.BlockManager.getBlockByIndex(index);
-    return block.holder;
+
+    if (block === undefined) {
+      _.logLabeled('There is no block at index `' + index + '`', 'warn');
+
+      return;
+    }
+
+    return new BlockAPI(block);
   }
 
   /**
    * Call Block Manager method that swap Blocks
+   *
    * @param {number} fromIndex - position of first Block
    * @param {number} toIndex - position of second Block
+   * @deprecated — use 'move' instead
    */
   public swap(fromIndex: number, toIndex: number): void {
+    _.log(
+      '`blocks.swap()` method is deprecated and will be removed in the next major release. ' +
+      'Use `block.move()` method instead',
+      'info'
+    );
+
     this.Editor.BlockManager.swap(fromIndex, toIndex);
 
     /**
@@ -71,28 +89,49 @@ export default class BlocksAPI extends Module {
     this.Editor.Toolbar.move(false);
   }
 
+  /**
+   * Move block from one index to another
+   *
+   * @param {number} toIndex - index to move to
+   * @param {number} fromIndex - index to move from
+   */
+  public move(toIndex: number, fromIndex?: number): void {
+    this.Editor.BlockManager.move(toIndex, fromIndex);
+
+    /**
+     * Move toolbar
+     * DO not close the settings
+     */
+    this.Editor.Toolbar.move(false);
+  }
+
   /**
    * Deletes Block
-   * @param blockIndex
+   *
+   * @param {number} blockIndex - index of Block to delete
    */
   public delete(blockIndex?: number): void {
-    this.Editor.BlockManager.removeBlock(blockIndex);
+    try {
+      this.Editor.BlockManager.removeBlock(blockIndex);
+    } catch (e) {
+      _.logLabeled(e, 'warn');
+
+      return;
+    }
 
     /**
      * in case of last block deletion
-     * Insert new initial empty block
+     * Insert the new default empty block
      */
     if (this.Editor.BlockManager.blocks.length === 0) {
       this.Editor.BlockManager.insert();
     }
 
     /**
-     * In case of deletion first block we need to set caret to the current Block
+     * After Block deletion currentBlock is updated
      */
-    if (this.Editor.BlockManager.currentBlockIndex === 0) {
-      this.Editor.Caret.setToBlock(this.Editor.BlockManager.currentBlock);
-    } else {
-      this.Editor.Caret.navigatePrevious(true);
+    if (this.Editor.BlockManager.currentBlock) {
+      this.Editor.Caret.setToBlock(this.Editor.BlockManager.currentBlock, this.Editor.Caret.positions.END);
     }
 
     this.Editor.Toolbar.close();
@@ -103,33 +142,47 @@ export default class BlocksAPI extends Module {
    */
   public clear(): void {
     this.Editor.BlockManager.clear(true);
+    this.Editor.InlineToolbar.close();
   }
 
   /**
    * Fills Editor with Blocks data
+   *
    * @param {OutputData} data — Saved Editor data
    */
   public render(data: OutputData): Promise {
     this.Editor.BlockManager.clear();
+
     return this.Editor.Renderer.render(data.blocks);
   }
 
   /**
    * Render passed HTML string
-   * @param {string} data
-   * @return {Promise}
+   *
+   * @param {string} data - HTML string to render
+   * @returns {Promise}
    */
   public renderFromHTML(data: string): Promise {
     this.Editor.BlockManager.clear();
+
     return this.Editor.Paste.processText(data, true);
   }
 
   /**
    * Stretch Block's content
-   * @param {number} index
+   *
+   * @param {number} index - index of Block to stretch
    * @param {boolean} status - true to enable, false to disable
+   *
+   * @deprecated Use BlockAPI interface to stretch Blocks
    */
-  public stretchBlock(index: number, status: boolean = true): void {
+  public stretchBlock(index: number, status = true): void {
+    _.deprecationAssert(
+      true,
+      'blocks.stretchBlock()',
+      'BlockAPI'
+    );
+
     const block = this.Editor.BlockManager.getBlockByIndex(index);
 
     if (!block) {
@@ -139,12 +192,41 @@ export default class BlocksAPI extends Module {
     block.stretched = status;
   }
 
+  /**
+   * Insert new Block
+   *
+   * @param {string} type — Tool name
+   * @param {BlockToolData} data — Tool data to insert
+   * @param {ToolConfig} config — Tool config
+   * @param {number?} index — index where to insert new Block
+   * @param {boolean?} needToFocus - flag to focus inserted Block
+   */
+  public insert = (
+    type: string = this.config.defaultBlock,
+    data: BlockToolData = {},
+    config: ToolConfig = {},
+    index?: number,
+    needToFocus?: boolean
+  ): void => {
+    this.Editor.BlockManager.insert({
+      tool: type,
+      data,
+      index,
+      needToFocus,
+    });
+  }
+
   /**
    * Insert new Block
    * After set caret to this Block
+   *
+   * @todo remove in 3.0.0
+   *
+   * @deprecated with insert() method
    */
-  public insertNewBlock() {
-    const newBlock = this.Editor.BlockManager.insert();
-    this.Editor.Caret.setToBlock(newBlock);
+  public insertNewBlock(): void {
+    _.log('Method blocks.insertNewBlock() is deprecated and it will be removed in the next major release. ' +
+      'Use blocks.insert() instead.', 'warn');
+    this.insert();
   }
 }
diff --git a/src/components/modules/api/caret.ts b/src/components/modules/api/caret.ts
index 5273400f3..63519d24a 100644
--- a/src/components/modules/api/caret.ts
+++ b/src/components/modules/api/caret.ts
@@ -1,5 +1,5 @@
+import { Caret } from '../../../../types/api';
 import Module from '../../__module';
-import {Caret} from '../../../../types/api';
 
 /**
  * @class CaretAPI
@@ -8,9 +8,10 @@ import {Caret} from '../../../../types/api';
 export default class CaretAPI extends Module {
   /**
    * Available methods
-   * @return {Caret}
+   *
+   * @returns {Caret}
    */
-  get methods(): Caret {
+  public get methods(): Caret {
     return {
       setToFirstBlock: this.setToFirstBlock,
       setToLastBlock: this.setToLastBlock,
@@ -27,14 +28,15 @@ export default class CaretAPI extends Module {
    * @param {string} position - position where to set caret
    * @param {number} offset - caret offset
    *
-   * @return {boolean}
+   * @returns {boolean}
    */
-  private setToFirstBlock = (position: string = this.Editor.Caret.positions.DEFAULT, offset: number = 0): boolean => {
+  private setToFirstBlock = (position: string = this.Editor.Caret.positions.DEFAULT, offset = 0): boolean => {
     if (!this.Editor.BlockManager.firstBlock) {
       return false;
     }
 
     this.Editor.Caret.setToBlock(this.Editor.BlockManager.firstBlock, position, offset);
+
     return true;
   }
 
@@ -44,14 +46,15 @@ export default class CaretAPI extends Module {
    * @param {string} position - position where to set caret
    * @param {number} offset - caret offset
    *
-   * @return {boolean}
+   * @returns {boolean}
    */
-  private setToLastBlock = (position: string = this.Editor.Caret.positions.DEFAULT, offset: number = 0): boolean => {
+  private setToLastBlock = (position: string = this.Editor.Caret.positions.DEFAULT, offset = 0): boolean => {
     if (!this.Editor.BlockManager.lastBlock) {
       return false;
     }
 
     this.Editor.Caret.setToBlock(this.Editor.BlockManager.lastBlock, position, offset);
+
     return true;
   }
 
@@ -61,17 +64,18 @@ export default class CaretAPI extends Module {
    * @param {string} position - position where to set caret
    * @param {number} offset - caret offset
    *
-   * @return {boolean}
+   * @returns {boolean}
    */
   private setToPreviousBlock = (
     position: string = this.Editor.Caret.positions.DEFAULT,
-    offset: number = 0,
+    offset = 0
   ): boolean => {
     if (!this.Editor.BlockManager.previousBlock) {
       return false;
     }
 
     this.Editor.Caret.setToBlock(this.Editor.BlockManager.previousBlock, position, offset);
+
     return true;
   }
 
@@ -81,14 +85,15 @@ export default class CaretAPI extends Module {
    * @param {string} position - position where to set caret
    * @param {number} offset - caret offset
    *
-   * @return {boolean}
+   * @returns {boolean}
    */
-  private setToNextBlock = (position: string = this.Editor.Caret.positions.DEFAULT, offset: number = 0): boolean => {
+  private setToNextBlock = (position: string = this.Editor.Caret.positions.DEFAULT, offset = 0): boolean => {
     if (!this.Editor.BlockManager.nextBlock) {
       return false;
     }
 
     this.Editor.Caret.setToBlock(this.Editor.BlockManager.nextBlock, position, offset);
+
     return true;
   }
 
@@ -99,18 +104,19 @@ export default class CaretAPI extends Module {
    * @param {string} position - position where to set caret
    * @param {number} offset - caret offset
    *
-   * @return {boolean}
+   * @returns {boolean}
    */
   private setToBlock = (
     index: number,
     position: string = this.Editor.Caret.positions.DEFAULT,
-    offset: number = 0,
+    offset = 0
   ): boolean => {
     if (!this.Editor.BlockManager.blocks[index]) {
       return false;
     }
 
     this.Editor.Caret.setToBlock(this.Editor.BlockManager.blocks[index], position, offset);
+
     return true;
   }
 
@@ -119,9 +125,9 @@ export default class CaretAPI extends Module {
    *
    * @param {boolean} atEnd - if true, set Caret to the end of the Editor
    *
-   * @return {boolean}
+   * @returns {boolean}
    */
-  private focus = (atEnd: boolean = false) => {
+  private focus = (atEnd = false): boolean => {
     if (atEnd) {
       return this.setToLastBlock(this.Editor.Caret.positions.END);
     }
diff --git a/src/components/modules/api/events.ts b/src/components/modules/api/events.ts
index 4862524de..865b913e9 100644
--- a/src/components/modules/api/events.ts
+++ b/src/components/modules/api/events.ts
@@ -1,5 +1,5 @@
 import Module from '../../__module';
-import {Events} from '../../../../types/api';
+import { Events } from '../../../../types/api';
 
 /**
  * @class EventsAPI
@@ -8,41 +8,44 @@ import {Events} from '../../../../types/api';
 export default class EventsAPI extends Module {
   /**
    * Available methods
-   * @return {Events}
+   *
+   * @returns {Events}
    */
-  get methods(): Events {
+  public get methods(): Events {
     return {
-      emit: (eventName: string, data: object) => this.emit(eventName, data),
-      off: (eventName: string, callback: () => void) => this.off(eventName, callback),
-      on: (eventName: string, callback: () => void) => this.on(eventName, callback),
+      emit: (eventName: string, data: object): void => this.emit(eventName, data),
+      off: (eventName: string, callback: () => void): void => this.off(eventName, callback),
+      on: (eventName: string, callback: () => void): void => this.on(eventName, callback),
     };
   }
 
   /**
    * Subscribe on Events
-   * @param {String} eventName
-   * @param {Function} callback
+   *
+   * @param {string} eventName - event name to subscribe
+   * @param {Function} callback - event handler
    */
   public on(eventName, callback): void {
-    this.Editor.Events.on(eventName, callback);
+    this.eventsDispatcher.on(eventName, callback);
   }
 
   /**
    * Emit event with data
-   * @param {String} eventName
-   * @param {Object} data
+   *
+   * @param {string} eventName - event to emit
+   * @param {object} data - event's data
    */
   public emit(eventName, data): void {
-    this.Editor.Events.emit(eventName, data);
+    this.eventsDispatcher.emit(eventName, data);
   }
 
   /**
    * Unsubscribe from Event
-   * @param {String} eventName
-   * @param {Function} callback
+   *
+   * @param {string} eventName - event to unsubscribe
+   * @param {Function} callback - event handler
    */
   public off(eventName, callback): void {
-    this.Editor.Events.off(eventName, callback);
+    this.eventsDispatcher.off(eventName, callback);
   }
-
 }
diff --git a/src/components/modules/api/i18n.ts b/src/components/modules/api/i18n.ts
new file mode 100644
index 000000000..6f702c608
--- /dev/null
+++ b/src/components/modules/api/i18n.ts
@@ -0,0 +1,55 @@
+import { I18n } from '../../../../types/api';
+import I18nInternal from '../../i18n';
+import { ToolType } from '../tools';
+import { logLabeled } from '../../utils';
+import Module from '../../__module';
+
+/**
+ * Provides methods for working with i18n
+ */
+export default class I18nAPI extends Module {
+  /**
+   * Return namespace section for tool or block tune
+   *
+   * @param toolName - name of tool. Used to provide dictionary only for this tool
+   * @param toolType - 'block' for Block Tool, 'inline' for Inline Tool, 'tune' for Block Tunes
+   */
+  private static getNamespace(toolName: string, toolType: ToolType): string {
+    switch (toolType) {
+      case ToolType.Block:
+      case ToolType.Inline:
+        return `tools.${toolName}`;
+      case ToolType.Tune:
+        return `blockTunes.${toolName}`;
+    }
+  }
+
+  /**
+   * Return I18n API methods with global dictionary access
+   */
+  public get methods(): I18n {
+    return {
+      t: (): string | undefined => {
+        logLabeled('I18n.t() method can be accessed only from Tools', 'warn');
+
+        return undefined;
+      },
+    };
+  }
+
+  /**
+   * Return I18n API methods with tool namespaced dictionary
+   *
+   * @param toolName - name of tool. Used to provide dictionary only for this tool
+   * @param toolType - 'block' for Block Tool, 'inline' for Inline Tool, 'tune' for Block Tunes
+   */
+  public getMethodsForTool(toolName: string, toolType: ToolType): I18n {
+    return Object.assign(
+      this.methods,
+      {
+        t: (dictKey: string): string => {
+          return I18nInternal.t(I18nAPI.getNamespace(toolName, toolType), dictKey);
+        },
+      });
+  }
+}
diff --git a/src/components/modules/api/index.ts b/src/components/modules/api/index.ts
index 803eca765..c765e5a6d 100644
--- a/src/components/modules/api/index.ts
+++ b/src/components/modules/api/index.ts
@@ -1,17 +1,21 @@
 /**
  * @module API
- * @copyright  2018
+ * @copyright  2018
  *
  * Each block has an Editor API instance to use provided public methods
  * if you cant to read more about how API works, please see docs
  */
 import Module from '../../__module';
-import {API as APIInterfaces} from '../../../../types';
+import { API as APIInterfaces } from '../../../../types';
+import { ToolType } from '../tools';
 
 /**
  * @class API
  */
 export default class API extends Module {
+  /**
+   * Editor.js Core API modules
+   */
   public get methods(): APIInterfaces {
     return {
       blocks: this.Editor.BlocksAPI.methods,
@@ -24,6 +28,27 @@ export default class API extends Module {
       selection: this.Editor.SelectionAPI.methods,
       styles: this.Editor.StylesAPI.classes,
       toolbar: this.Editor.ToolbarAPI.methods,
-    } as APIInterfaces;
+      inlineToolbar: this.Editor.InlineToolbarAPI.methods,
+      tooltip: this.Editor.TooltipAPI.methods,
+      i18n: this.Editor.I18nAPI.methods,
+      readOnly: this.Editor.ReadOnlyAPI.methods,
+    };
+  }
+
+  /**
+   * Returns Editor.js Core API methods for passed tool
+   *
+   * @param toolName - how user name tool. It can be used in some API logic,
+   *                   for example in i18n to provide namespaced dictionary
+   *
+   * @param toolType - 'block' for Block Tool, 'inline' for Inline Tool, 'tune' for Block Tunes
+   */
+  public getMethodsForTool(toolName: string, toolType = ToolType.Block): APIInterfaces {
+    return Object.assign(
+      this.methods,
+      {
+        i18n: this.Editor.I18nAPI.getMethodsForTool(toolName, toolType),
+      }
+    ) as APIInterfaces;
   }
 }
diff --git a/src/components/modules/api/inlineToolbar.ts b/src/components/modules/api/inlineToolbar.ts
new file mode 100644
index 000000000..dca74ca90
--- /dev/null
+++ b/src/components/modules/api/inlineToolbar.ts
@@ -0,0 +1,34 @@
+import { InlineToolbar } from '../../../../types/api/inline-toolbar';
+import Module from '../../__module';
+
+/**
+ * @class InlineToolbarAPI
+ * Provides methods for working with the Inline Toolbar
+ */
+export default class InlineToolbarAPI extends Module {
+  /**
+   * Available methods
+   *
+   * @returns {InlineToolbar}
+   */
+  public get methods(): InlineToolbar {
+    return {
+      close: (): void => this.close(),
+      open: (): void => this.open(),
+    };
+  }
+
+  /**
+   * Open Inline Toolbar
+   */
+  public open(): void {
+    this.Editor.InlineToolbar.tryToShow();
+  }
+
+  /**
+   * Close Inline Toolbar
+   */
+  public close(): void {
+    this.Editor.InlineToolbar.close();
+  }
+}
diff --git a/src/components/modules/api/listeners.ts b/src/components/modules/api/listeners.ts
index 375501627..a3b403a3a 100644
--- a/src/components/modules/api/listeners.ts
+++ b/src/components/modules/api/listeners.ts
@@ -1,5 +1,5 @@
+import { Listeners } from '../../../../types/api';
 import Module from '../../__module';
-import {Listeners} from '../../../../types/api';
 
 /**
  * @class ListenersAPI
@@ -8,35 +8,37 @@ import {Listeners} from '../../../../types/api';
 export default class ListenersAPI extends Module {
   /**
    * Available methods
-   * @return {Listeners}
+   *
+   * @returns {Listeners}
    */
-  get methods(): Listeners {
+  public get methods(): Listeners {
     return {
-      on: (element: HTMLElement, eventType, handler, useCapture) => this.on(element, eventType, handler, useCapture),
-      off: (element, eventType, handler) => this.off(element, eventType, handler),
+      on: (element: HTMLElement, eventType, handler, useCapture): void => this.on(element, eventType, handler, useCapture),
+      off: (element, eventType, handler, useCapture): void => this.off(element, eventType, handler, useCapture),
     };
   }
 
   /**
    * adds DOM event listener
    *
-   * @param {HTMLElement} element
-   * @param {string} eventType
-   * @param {() => void} handler
-   * @param {boolean} useCapture
+   * @param {HTMLElement} element - Element to set handler to
+   * @param {string} eventType - event type
+   * @param {() => void} handler - event handler
+   * @param {boolean} useCapture - capture event or not
    */
   public on(element: HTMLElement, eventType: string, handler: () => void, useCapture?: boolean): void {
-    this.Editor.Listeners.on(element, eventType, handler, useCapture);
+    this.listeners.on(element, eventType, handler, useCapture);
   }
 
   /**
    * Removes DOM listener from element
    *
-   * @param element
-   * @param eventType
-   * @param handler
+   * @param {Element} element - Element to remove handler from
+   * @param eventType - event type
+   * @param handler - event handler
+   * @param {boolean} useCapture - capture event or not
    */
-  public off(element, eventType, handler): void {
-    this.Editor.Listeners.off(element, eventType, handler);
+  public off(element: Element, eventType: string, handler: () => void, useCapture?: boolean): void {
+    this.listeners.off(element, eventType, handler, useCapture);
   }
 }
diff --git a/src/components/modules/api/notifier.ts b/src/components/modules/api/notifier.ts
index e91c3f7f1..ce89596a2 100644
--- a/src/components/modules/api/notifier.ts
+++ b/src/components/modules/api/notifier.ts
@@ -1,19 +1,26 @@
+import { Notifier } from '../../../../types/api';
+import { ConfirmNotifierOptions, NotifierOptions, PromptNotifierOptions } from 'codex-notifier';
 import Module from '../../__module';
-import {Notifier} from '../../../../types/api';
-import {ConfirmNotifierOptions, NotifierOptions, PromptNotifierOptions} from 'codex-notifier';
 
+/**
+ *
+ */
 export default class NotifierAPI extends Module {
-
   /**
    * Available methods
    */
-  get methods(): Notifier {
+  public get methods(): Notifier {
     return {
-      show: (options: NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions) => this.show(options),
+      show: (options: NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions): void => this.show(options),
     };
   }
 
-  public show(options: NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions) {
+  /**
+   * Show notification
+   *
+   * @param {NotifierOptions} options - message option
+   */
+  public show(options: NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions): void {
     return this.Editor.Notifier.show(options);
   }
 }
diff --git a/src/components/modules/api/readonly.ts b/src/components/modules/api/readonly.ts
new file mode 100644
index 000000000..7b268c835
--- /dev/null
+++ b/src/components/modules/api/readonly.ts
@@ -0,0 +1,28 @@
+import { ReadOnly } from '../../../../types/api';
+import Module from '../../__module';
+
+/**
+ * @class ReadOnlyAPI
+ * @classdesc ReadOnly API
+ */
+export default class ReadOnlyAPI extends Module {
+  /**
+   * Available methods
+   */
+  public get methods(): ReadOnly {
+    return {
+      toggle: (state): Promise => this.toggle(state),
+    };
+  }
+
+  /**
+   * Set or toggle read-only state
+   *
+   * @param {boolean|undefined} state - set or toggle state
+   *
+   * @returns {boolean} current value
+   */
+  public toggle(state?: boolean): Promise {
+    return this.Editor.ReadOnly.toggle(state);
+  }
+}
diff --git a/src/components/modules/api/sanitizer.ts b/src/components/modules/api/sanitizer.ts
index 6ef9d0f93..01ab2be22 100644
--- a/src/components/modules/api/sanitizer.ts
+++ b/src/components/modules/api/sanitizer.ts
@@ -1,5 +1,6 @@
+import { Sanitizer } from '../../../../types/api';
+import { SanitizerConfig } from '../../../../types/configs';
 import Module from '../../__module';
-import {Sanitizer} from '../../../../types/api';
 
 /**
  * @class SanitizerAPI
@@ -8,16 +9,24 @@ import {Sanitizer} from '../../../../types/api';
 export default class SanitizerAPI extends Module {
   /**
    * Available methods
-   * @return {Sanitizer}
+   *
+   * @returns {Sanitizer}
    */
-  get methods(): Sanitizer {
+  public get methods(): Sanitizer {
     return {
-      clean: (taintString, config) => this.clean(taintString, config),
+      clean: (taintString, config): string => this.clean(taintString, config),
     };
   }
 
-  public clean(taintString, config) {
+  /**
+   * Perform sanitizing of a string
+   *
+   * @param {string} taintString - what to sanitize
+   * @param {SanitizerConfig} config - sanitizer config
+   *
+   * @returns {string}
+   */
+  public clean(taintString: string, config: SanitizerConfig): string {
     return this.Editor.Sanitizer.clean(taintString, config);
   }
-
 }
diff --git a/src/components/modules/api/saver.ts b/src/components/modules/api/saver.ts
index 3680331df..5db9b88ad 100644
--- a/src/components/modules/api/saver.ts
+++ b/src/components/modules/api/saver.ts
@@ -1,6 +1,7 @@
+import { Saver } from '../../../../types/api';
+import { OutputData } from '../../../../types';
+import * as _ from '../../utils';
 import Module from '../../__module';
-import {Saver} from '../../../../types/api';
-import {OutputData} from '../../../../types';
 
 /**
  * @class SaverAPI
@@ -9,18 +10,29 @@ import {OutputData} from '../../../../types';
 export default class SaverAPI extends Module {
   /**
    * Available methods
-   * @return {Saver}
+   *
+   * @returns {Saver}
    */
-  get methods(): Saver {
+  public get methods(): Saver {
     return {
-      save: () => this.save(),
+      save: (): Promise => this.save(),
     };
   }
 
   /**
    * Return Editor's data
+   *
+   * @returns {OutputData}
    */
   public save(): Promise {
+    const errorText = 'Editor\'s content can not be saved in read-only mode';
+
+    if (this.Editor.ReadOnly.isEnabled) {
+      _.logLabeled(errorText, 'warn');
+
+      return Promise.reject(new Error(errorText));
+    }
+
     return this.Editor.Saver.save();
   }
 }
diff --git a/src/components/modules/api/selection.ts b/src/components/modules/api/selection.ts
index df7453c3d..6cd7bcc18 100644
--- a/src/components/modules/api/selection.ts
+++ b/src/components/modules/api/selection.ts
@@ -1,6 +1,6 @@
-import Module from '../../__module';
 import SelectionUtils from '../../selection';
-import {Selection as SelectionAPIInterface} from '../../../../types/api';
+import { Selection as SelectionAPIInterface } from '../../../../types/api';
+import Module from '../../__module';
 
 /**
  * @class SelectionAPI
@@ -9,31 +9,34 @@ import {Selection as SelectionAPIInterface} from '../../../../types/api';
 export default class SelectionAPI extends Module {
   /**
    * Available methods
-   * @return {SelectionAPIInterface}
+   *
+   * @returns {SelectionAPIInterface}
    */
-  get methods(): SelectionAPIInterface {
+  public get methods(): SelectionAPIInterface {
     return {
-      findParentTag: (tagName: string, className?: string) => this.findParentTag(tagName, className),
-      expandToTag: (node: HTMLElement) => this.expandToTag(node),
+      findParentTag: (tagName: string, className?: string): HTMLElement | null => this.findParentTag(tagName, className),
+      expandToTag: (node: HTMLElement): void => this.expandToTag(node),
     };
   }
 
   /**
    * Looks ahead from selection and find passed tag with class name
+   *
    * @param {string} tagName - tag to find
    * @param {string} className - tag's class name
-   * @return {HTMLElement|null}
+   *
+   * @returns {HTMLElement|null}
    */
-  public findParentTag(tagName: string, className?: string): HTMLElement|null {
+  public findParentTag(tagName: string, className?: string): HTMLElement | null {
     return new SelectionUtils().findParentTag(tagName, className);
   }
 
   /**
    * Expand selection to passed tag
+   *
    * @param {HTMLElement} node - tag that should contain selection
    */
   public expandToTag(node: HTMLElement): void {
     new SelectionUtils().expandToTag(node);
   }
-
 }
diff --git a/src/components/modules/api/styles.ts b/src/components/modules/api/styles.ts
index 7beb81278..aced02a55 100644
--- a/src/components/modules/api/styles.ts
+++ b/src/components/modules/api/styles.ts
@@ -1,11 +1,14 @@
+import { Styles } from '../../../../types/api';
 import Module from '../../__module';
-import {Styles} from '../../../../types/api';
 
 /**
  *
  */
 export default class StylesAPI extends Module {
-  get classes(): Styles {
+  /**
+   * Exported classes
+   */
+  public get classes(): Styles {
     return {
       /**
        * Base Block styles
diff --git a/src/components/modules/api/toolbar.ts b/src/components/modules/api/toolbar.ts
index b7cec59de..9cbb8de6e 100644
--- a/src/components/modules/api/toolbar.ts
+++ b/src/components/modules/api/toolbar.ts
@@ -1,19 +1,21 @@
+import { Toolbar } from '../../../../types/api';
 import Module from '../../__module';
-import {Toolbar} from '../../../../types/api';
-
+import * as _ from './../../utils';
 /**
  * @class ToolbarAPI
- * provides with methods working with Toolbar
+ * Provides methods for working with the Toolbar
  */
 export default class ToolbarAPI extends Module {
   /**
    * Available methods
-   * @return {Toolbar}
+   *
+   * @returns {Toolbar}
    */
-  get methods(): Toolbar {
+  public get methods(): Toolbar {
     return {
-      close: () => this.close(),
-      open: () => this.open(),
+      close: (): void => this.close(),
+      open: (): void => this.open(),
+      toggleBlockSettings: (openingState?: boolean): void => this.toggleBlockSettings(openingState),
     };
   }
 
@@ -31,4 +33,34 @@ export default class ToolbarAPI extends Module {
     this.Editor.Toolbar.close();
   }
 
+  /**
+   * Toggles Block Setting of the current block
+   *
+   * @param {boolean} openingState —  opening state of Block Setting
+   */
+  public toggleBlockSettings(openingState?: boolean): void {
+    if (this.Editor.BlockManager.currentBlockIndex === -1) {
+      _.logLabeled('Could\'t toggle the Toolbar because there is no block selected ', 'warn');
+
+      return;
+    }
+
+    /** Check that opening state is set or not */
+    const canOpenBlockSettings = openingState ?? !this.Editor.BlockSettings.opened;
+
+    /** Check if state same as current state */
+    if (openingState === this.Editor.BlockSettings.opened) {
+      return;
+    }
+
+    if (canOpenBlockSettings) {
+      if (!this.Editor.Toolbar.opened) {
+        this.Editor.Toolbar.open(true, false);
+        this.Editor.Toolbar.plusButton.hide();
+      }
+      this.Editor.BlockSettings.open();
+    } else {
+      this.Editor.BlockSettings.close();
+    }
+  }
 }
diff --git a/src/components/modules/api/tooltip.ts b/src/components/modules/api/tooltip.ts
new file mode 100644
index 000000000..4094f4e81
--- /dev/null
+++ b/src/components/modules/api/tooltip.ts
@@ -0,0 +1,55 @@
+import { Tooltip } from '../../../../types/api';
+import { TooltipContent, TooltipOptions } from 'codex-tooltip';
+import Module from '../../__module';
+
+/**
+ * @class TooltipAPI
+ * @classdesc Tooltip API
+ */
+export default class TooltipAPI extends Module {
+  /**
+   * Available methods
+   */
+  public get methods(): Tooltip {
+    return {
+      show: (element: HTMLElement,
+        content: TooltipContent,
+        options?: TooltipOptions
+      ): void => this.show(element, content, options),
+      hide: (): void => this.hide(),
+      onHover: (element: HTMLElement,
+        content: TooltipContent,
+        options?: TooltipOptions
+      ): void => this.onHover(element, content, options),
+    };
+  }
+
+  /**
+   * Method show tooltip on element with passed HTML content
+   *
+   * @param {HTMLElement} element - element on which tooltip should be shown
+   * @param {TooltipContent} content - tooltip content
+   * @param {TooltipOptions} options - tooltip options
+   */
+  public show(element: HTMLElement, content: TooltipContent, options?: TooltipOptions): void {
+    this.Editor.Tooltip.show(element, content, options);
+  }
+
+  /**
+   * Method hides tooltip on HTML page
+   */
+  public hide(): void {
+    this.Editor.Tooltip.hide();
+  }
+
+  /**
+   * Decorator for showing Tooltip by mouseenter/mouseleave
+   *
+   * @param {HTMLElement} element - element on which tooltip should be shown
+   * @param {TooltipContent} content - tooltip content
+   * @param {TooltipOptions} options - tooltip options
+   */
+  public onHover(element: HTMLElement, content: TooltipContent, options?: TooltipOptions): void {
+    this.Editor.Tooltip.onHover(element, content, options);
+  }
+}
diff --git a/src/components/modules/blockEvents.ts b/src/components/modules/blockEvents.ts
index 1e62e44dd..a2b8d6616 100644
--- a/src/components/modules/blockEvents.ts
+++ b/src/components/modules/blockEvents.ts
@@ -2,11 +2,17 @@
  * Contains keyboard and mouse events binded on each Block by Block Manager
  */
 import Module from '../__module';
-import _ from '../utils';
+import * as _ from '../utils';
+import SelectionUtils from '../selection';
+import Flipper from '../flipper';
 
+/**
+ *
+ */
 export default class BlockEvents extends Module {
   /**
    * All keydowns on Block
+   *
    * @param {KeyboardEvent} event - keydown
    */
   public keydown(event: KeyboardEvent): void {
@@ -40,21 +46,15 @@ export default class BlockEvents extends Module {
       case _.keyCodes.TAB:
         this.tabPressed(event);
         break;
-
-      case _.keyCodes.ESC:
-        this.escapePressed(event);
-        break;
-      default:
-        this.defaultHandler();
-        break;
     }
   }
 
   /**
    * Fires on keydown before event processing
+   *
    * @param {KeyboardEvent} event - keydown
    */
-  public beforeKeydownProcessing(event): void {
+  public beforeKeydownProcessing(event: KeyboardEvent): void {
     /**
      * Do not close Toolbox on Tabs or on Enter with opened Toolbox
      */
@@ -62,96 +62,90 @@ export default class BlockEvents extends Module {
       return;
     }
 
-    this.Editor.Toolbar.close();
-
-    const cmdKey = event.ctrlKey || event.metaKey;
-    const altKey = event.altKey;
-    const shiftKey = event.shiftKey;
-
-    /** clear selecton when it is not CMD, SHIFT, ALT keys */
-    if (cmdKey || altKey || shiftKey) {
-      return;
-    }
-
     /**
-     * Clear all highlightings
+     * When user type something:
+     *  - close Toolbar
+     *  - close Conversion Toolbar
+     *  - clear block highlighting
      */
-    this.Editor.BlockManager.clearFocused();
+    if (_.isPrintableKey(event.keyCode)) {
+      this.Editor.Toolbar.close();
+      this.Editor.ConversionToolbar.close();
 
-    if (event.keyCode !== _.keyCodes.ENTER && event.keyCode !== _.keyCodes.BACKSPACE) {
       /**
-       * Clear selection and restore caret before navigation
+       * Allow to use shortcuts with selected blocks
+       *
+       * @type {boolean}
        */
-      this.Editor.BlockSelection.clearSelection(true);
+      const isShortcut = event.ctrlKey || event.metaKey || event.altKey || event.shiftKey;
+
+      if (!isShortcut) {
+        this.Editor.BlockManager.clearFocused();
+        this.Editor.BlockSelection.clearSelection(event);
+      }
     }
   }
 
   /**
    * Key up on Block:
    * - shows Inline Toolbar if something selected
+   * - shows conversion toolbar with 85% of block selection
+   *
+   * @param {KeyboardEvent} event - keyup event
    */
-  public keyup(event): void {
-    this.Editor.InlineToolbar.handleShowingEvent(event);
-  }
+  public keyup(event: KeyboardEvent): void {
+    /**
+     * If shift key was pressed some special shortcut is used (eg. cross block selection via shift + arrows)
+     */
+    if (event.shiftKey) {
+      return;
+    }
 
-  /**
-   * Mouse up on Block:
-   * - shows Inline Toolbar if something selected
-   */
-  public mouseUp(event): void {
-    this.Editor.InlineToolbar.handleShowingEvent(event);
+    /**
+     * Check if editor is empty on each keyup and add special css class to wrapper
+     */
+    this.Editor.UI.checkEmptiness();
   }
 
   /**
    * Open Toolbox to leaf Tools
-   * @param {KeyboardEvent} event
+   *
+   * @param {KeyboardEvent} event - tab keydown event
    */
   public tabPressed(event): void {
-
-    const {currentBlock} = this.Editor.BlockManager;
-
-    /** Prevent Default behaviour */
-    event.preventDefault();
-    event.stopPropagation();
-
-    /** this property defines leaf direction */
-    const shiftKey = event.shiftKey,
-      direction = shiftKey ? 'left' : 'right';
-
     /**
-     * Don't show Plus and Toolbox near not-inital Tools
+     * Clear blocks selection by tab
      */
-    if (!this.Editor.Tools.isInitial(currentBlock.tool)) {
-      return;
-    }
+    this.Editor.BlockSelection.clearSelection(event);
 
-    if (currentBlock.isEmpty) {
-      if (!this.Editor.Toolbar.opened) {
-        this.Editor.Toolbar.open(false , false);
-        this.Editor.Toolbar.plusButton.show();
-      }
+    const { BlockManager, Tools, InlineToolbar, ConversionToolbar } = this.Editor;
+    const currentBlock = BlockManager.currentBlock;
 
-      this.Editor.Toolbox.open();
+    if (!currentBlock) {
+      return;
     }
 
-    if (this.Editor.Toolbox.opened) {
-      this.Editor.Toolbox.leaf(direction);
+    const canOpenToolbox = Tools.isDefault(currentBlock.tool) && currentBlock.isEmpty;
+    const conversionToolbarOpened = !currentBlock.isEmpty && ConversionToolbar.opened;
+    const inlineToolbarOpened = !currentBlock.isEmpty && !SelectionUtils.isCollapsed && InlineToolbar.opened;
+
+    /**
+     * For empty Blocks we show Plus button via Toolbox only for default Blocks
+     */
+    if (canOpenToolbox) {
+      this.activateToolbox();
+    } else if (!conversionToolbarOpened && !inlineToolbarOpened) {
+      this.activateBlockSettings();
     }
   }
 
-  /**
-   * Escape pressed
-   * @param event
-   */
-  public escapePressed(event): void { }
-
   /**
    * Add drop target styles
    *
-   * @param {DragEvent} e
+   * @param {DragEvent} event - drag over event
    */
-  public dragOver(e: DragEvent) {
-    const block = this.Editor.BlockManager.getBlockByChildNode(e.target as Node);
+  public dragOver(event: DragEvent): void {
+    const block = this.Editor.BlockManager.getBlockByChildNode(event.target as Node);
 
     block.dropTarget = true;
   }
@@ -159,10 +153,10 @@ export default class BlockEvents extends Module {
   /**
    * Remove drop target style
    *
-   * @param {DragEvent} e
+   * @param {DragEvent} event - drag leave event
    */
-  public dragLeave(e: DragEvent) {
-    const block = this.Editor.BlockManager.getBlockByChildNode(e.target as Node);
+  public dragLeave(event: DragEvent): void {
+    const block = this.Editor.BlockManager.getBlockByChildNode(event.target as Node);
 
     block.dropTarget = false;
   }
@@ -171,59 +165,48 @@ export default class BlockEvents extends Module {
    * Copying selected blocks
    * Before putting to the clipboard we sanitize all blocks and then copy to the clipboard
    *
-   * @param event
+   * @param {ClipboardEvent} event - clipboard event
    */
-  public handleCommandC(event): void {
+  public handleCommandC(event: ClipboardEvent): Promise {
     const { BlockSelection } = this.Editor;
 
     if (!BlockSelection.anyBlockSelected) {
       return;
     }
 
-    /**
-     * Prevent default copy
-     * Remove "decline sound" on macOS
-     */
-    event.preventDefault();
-
     // Copy Selected Blocks
-    BlockSelection.copySelectedBlocks();
+    return BlockSelection.copySelectedBlocks(event);
   }
 
   /**
    * Copy and Delete selected Blocks
-   * @param event
+   *
+   * @param {ClipboardEvent} event - clipboard event
    */
-  public handleCommandX(event): void {
+  public async handleCommandX(event: ClipboardEvent): Promise {
     const { BlockSelection, BlockManager, Caret } = this.Editor;
 
     if (!BlockSelection.anyBlockSelected) {
       return;
     }
 
-    /**
-     * Copy Blocks before removing
-     *
-     * Prevent default copy
-     * Remove "decline sound" on macOS
-     */
-    event.preventDefault();
-
-    BlockSelection.copySelectedBlocks();
+    await BlockSelection.copySelectedBlocks(event);
 
     const selectionPositionIndex = BlockManager.removeSelectedBlocks();
-    Caret.setToBlock(BlockManager.insertAtIndex(selectionPositionIndex, true), Caret.positions.START);
+
+    Caret.setToBlock(BlockManager.insertDefaultBlockAtIndex(selectionPositionIndex, true), Caret.positions.START);
 
     /** Clear selection */
-    BlockSelection.clearSelection();
+    BlockSelection.clearSelection(event);
   }
 
   /**
    * ENTER pressed on block
+   *
    * @param {KeyboardEvent} event - keydown
    */
   private enter(event: KeyboardEvent): void {
-    const {BlockManager, Tools} = this.Editor;
+    const { BlockManager, Tools, UI } = this.Editor;
     const currentBlock = BlockManager.currentBlock;
     const tool = Tools.available[currentBlock.name];
 
@@ -231,15 +214,15 @@ export default class BlockEvents extends Module {
      * Don't handle Enter keydowns when Tool sets enableLineBreaks to true.
      * Uses for Tools like  where line breaks should be handled by default behaviour.
      */
-    if (tool && tool[this.Editor.Tools.apiSettings.IS_ENABLED_LINE_BREAKS]) {
+    if (tool && tool[Tools.INTERNAL_SETTINGS.IS_ENABLED_LINE_BREAKS]) {
       return;
     }
 
-    if (this.Editor.Toolbox.opened && this.Editor.Toolbox.getActiveTool) {
-      event.preventDefault();
-      event.stopPropagation();
-      event.stopImmediatePropagation();
-      this.Editor.Toolbox.toolButtonActivate(event, this.Editor.Toolbox.getActiveTool);
+    /**
+     * Opened Toolbars uses Flipper with own Enter handling
+     * Allow split block when no one button in Flipper is focused
+     */
+    if (UI.someToolbarOpened && UI.someFlipperButtonFocused) {
       return;
     }
 
@@ -256,7 +239,7 @@ export default class BlockEvents extends Module {
      * If enter has been pressed at the start of the text, just insert paragraph Block above
      */
     if (this.Editor.Caret.isAtStart && !this.Editor.BlockManager.currentBlock.hasMedia) {
-      this.Editor.BlockManager.insertAtIndex(this.Editor.BlockManager.currentBlockIndex);
+      this.Editor.BlockManager.insertDefaultBlockAtIndex(this.Editor.BlockManager.currentBlockIndex);
     } else {
       /**
        * Split the Current Block into two blocks
@@ -270,7 +253,7 @@ export default class BlockEvents extends Module {
     /**
      * If new Block is empty
      */
-    if (this.Editor.Tools.isInitial(newCurrent.tool) && newCurrent.isEmpty) {
+    if (this.Editor.Tools.isDefault(newCurrent.tool) && newCurrent.isEmpty) {
       /**
        * Show Toolbar
        */
@@ -283,12 +266,11 @@ export default class BlockEvents extends Module {
     }
 
     event.preventDefault();
-    event.stopPropagation();
-    event.stopImmediatePropagation();
   }
 
   /**
    * Handle backspace keydown on Block
+   *
    * @param {KeyboardEvent} event - keydown
    */
   private backspace(event: KeyboardEvent): void {
@@ -299,7 +281,7 @@ export default class BlockEvents extends Module {
     /**
      * Check if Block should be removed by current Backspace keydown
      */
-    if (currentBlock.selected || currentBlock.isEmpty && currentBlock.currentInput === currentBlock.firstInput) {
+    if (currentBlock.selected || (currentBlock.isEmpty && currentBlock.currentInput === currentBlock.firstInput)) {
       event.preventDefault();
 
       const index = BlockManager.currentBlockIndex;
@@ -314,14 +296,15 @@ export default class BlockEvents extends Module {
 
       Caret.setToBlock(
         BlockManager.currentBlock,
-        index ? Caret.positions.END : Caret.positions.START,
+        index ? Caret.positions.END : Caret.positions.START
       );
 
       /** Close Toolbar */
       this.Editor.Toolbar.close();
 
       /** Clear selection */
-      BlockSelection.clearSelection();
+      BlockSelection.clearSelection(event);
+
       return;
     }
 
@@ -331,12 +314,15 @@ export default class BlockEvents extends Module {
      *
      * But if caret is at start of the block, we allow to remove it by backspaces
      */
-    if (tool && tool[this.Editor.Tools.apiSettings.IS_ENABLED_LINE_BREAKS] && !Caret.isAtStart) {
+    if (tool && tool[this.Editor.Tools.INTERNAL_SETTINGS.IS_ENABLED_LINE_BREAKS] && !Caret.isAtStart) {
       return;
     }
 
     const isFirstBlock = BlockManager.currentBlockIndex === 0;
-    const canMergeBlocks = Caret.isAtStart && currentBlock.currentInput === currentBlock.firstInput && !isFirstBlock;
+    const canMergeBlocks = Caret.isAtStart &&
+      SelectionUtils.isCollapsed &&
+      currentBlock.currentInput === currentBlock.firstInput &&
+      !isFirstBlock;
 
     if (canMergeBlocks) {
       /**
@@ -354,7 +340,7 @@ export default class BlockEvents extends Module {
   /**
    * Merge current and previous Blocks if they have the same type
    */
-  private mergeBlocks() {
+  private mergeBlocks(): void {
     const { BlockManager, Caret, Toolbar } = this.Editor;
     const targetBlock = BlockManager.previousBlock;
     const blockToMerge = BlockManager.currentBlock;
@@ -373,6 +359,7 @@ export default class BlockEvents extends Module {
 
         Caret.setToBlock(BlockManager.currentBlock);
         Toolbar.close();
+
         return;
       }
 
@@ -385,7 +372,7 @@ export default class BlockEvents extends Module {
 
     Caret.createShadow(targetBlock.pluginsContent);
     BlockManager.mergeBlocks(targetBlock, blockToMerge)
-      .then( () => {
+      .then(() => {
         /** Restore caret position after merge */
         Caret.restoreCaret(targetBlock.pluginsContent as HTMLElement);
         targetBlock.pluginsContent.normalize();
@@ -395,9 +382,39 @@ export default class BlockEvents extends Module {
 
   /**
    * Handle right and down keyboard keys
+   *
+   * @param {KeyboardEvent} event - keyboard event
    */
   private arrowRightAndDown(event: KeyboardEvent): void {
-    if (this.Editor.Caret.navigateNext()) {
+    const isFlipperCombination = Flipper.usedKeys.includes(event.keyCode) &&
+      (!event.shiftKey || event.keyCode === _.keyCodes.TAB);
+
+    /**
+     * Arrows might be handled on toolbars by flipper
+     * Check for Flipper.usedKeys to allow navigate by DOWN and disallow by RIGHT
+     */
+    if (this.Editor.UI.someToolbarOpened && isFlipperCombination) {
+      return;
+    }
+
+    /**
+     * Close Toolbar and highlighting when user moves cursor
+     */
+    this.Editor.BlockManager.clearFocused();
+    this.Editor.Toolbar.close();
+
+    const shouldEnableCBS = this.Editor.Caret.isAtEnd || this.Editor.BlockSelection.anyBlockSelected;
+
+    if (event.shiftKey && event.keyCode === _.keyCodes.DOWN && shouldEnableCBS) {
+      this.Editor.CrossBlockSelection.toggleBlockSelectedState();
+
+      return;
+    }
+
+    const navigateNext = event.keyCode === _.keyCodes.DOWN || (event.keyCode === _.keyCodes.RIGHT && !this.isRtl);
+    const isNavigated = navigateNext ? this.Editor.Caret.navigateNext() : this.Editor.Caret.navigatePrevious();
+
+    if (isNavigated) {
       /**
        * Default behaviour moves cursor by 1 character, we need to prevent it
        */
@@ -407,16 +424,55 @@ export default class BlockEvents extends Module {
        * After caret is set, update Block input index
        */
       _.delay(() => {
-        this.Editor.BlockManager.currentBlock.updateCurrentInput();
+        /** Check currentBlock for case when user moves selection out of Editor */
+        if (this.Editor.BlockManager.currentBlock) {
+          this.Editor.BlockManager.currentBlock.updateCurrentInput();
+        }
       }, 20)();
     }
+
+    /**
+     * Clear blocks selection by arrows
+     */
+    this.Editor.BlockSelection.clearSelection(event);
   }
 
   /**
    * Handle left and up keyboard keys
+   *
+   * @param {KeyboardEvent} event - keyboard event
    */
   private arrowLeftAndUp(event: KeyboardEvent): void {
-    if (this.Editor.Caret.navigatePrevious()) {
+    /**
+     * Arrows might be handled on toolbars by flipper
+     * Check for Flipper.usedKeys to allow navigate by UP and disallow by LEFT
+     */
+    if (this.Editor.UI.someToolbarOpened) {
+      if (Flipper.usedKeys.includes(event.keyCode) && (!event.shiftKey || event.keyCode === _.keyCodes.TAB)) {
+        return;
+      }
+
+      this.Editor.UI.closeAllToolbars();
+    }
+
+    /**
+     * Close Toolbar and highlighting when user moves cursor
+     */
+    this.Editor.BlockManager.clearFocused();
+    this.Editor.Toolbar.close();
+
+    const shouldEnableCBS = this.Editor.Caret.isAtStart || this.Editor.BlockSelection.anyBlockSelected;
+
+    if (event.shiftKey && event.keyCode === _.keyCodes.UP && shouldEnableCBS) {
+      this.Editor.CrossBlockSelection.toggleBlockSelectedState(false);
+
+      return;
+    }
+
+    const navigatePrevious = event.keyCode === _.keyCodes.UP || (event.keyCode === _.keyCodes.LEFT && !this.isRtl);
+    const isNavigated = navigatePrevious ? this.Editor.Caret.navigatePrevious() : this.Editor.Caret.navigateNext();
+
+    if (isNavigated) {
       /**
        * Default behaviour moves cursor by 1 character, we need to prevent it
        */
@@ -426,23 +482,74 @@ export default class BlockEvents extends Module {
        * After caret is set, update Block input index
        */
       _.delay(() => {
-        this.Editor.BlockManager.currentBlock.updateCurrentInput();
+        /** Check currentBlock for case when user ends selection out of Editor and then press arrow-key */
+        if (this.Editor.BlockManager.currentBlock) {
+          this.Editor.BlockManager.currentBlock.updateCurrentInput();
+        }
       }, 20)();
     }
+
+    /**
+     * Clear blocks selection by arrows
+     */
+    this.Editor.BlockSelection.clearSelection(event);
   }
 
   /**
-   * Default keydown handler
+   * Cases when we need to close Toolbar
+   *
+   * @param {KeyboardEvent} event - keyboard event
    */
-  private defaultHandler(): void {}
+  private needToolbarClosing(event: KeyboardEvent): boolean {
+    const toolboxItemSelected = (event.keyCode === _.keyCodes.ENTER && this.Editor.Toolbox.opened),
+        blockSettingsItemSelected = (event.keyCode === _.keyCodes.ENTER && this.Editor.BlockSettings.opened),
+        inlineToolbarItemSelected = (event.keyCode === _.keyCodes.ENTER && this.Editor.InlineToolbar.opened),
+        conversionToolbarItemSelected = (event.keyCode === _.keyCodes.ENTER && this.Editor.ConversionToolbar.opened),
+        flippingToolbarItems = event.keyCode === _.keyCodes.TAB;
+
+    /**
+     * Do not close Toolbar in cases:
+     * 1. ShiftKey pressed (or combination with shiftKey)
+     * 2. When Toolbar is opened and Tab leafs its Tools
+     * 3. When Toolbar's component is opened and some its item selected
+     */
+    return !(event.shiftKey ||
+      flippingToolbarItems ||
+      toolboxItemSelected ||
+      blockSettingsItemSelected ||
+      inlineToolbarItemSelected ||
+      conversionToolbarItemSelected
+    );
+  }
 
   /**
-   * Cases when we need to close Toolbar
+   * If Toolbox is not open, then just open it and show plus button
    */
-  private needToolbarClosing(event) {
-    const toolboxItemSelected = (event.keyCode === _.keyCodes.ENTER && this.Editor.Toolbox.opened),
-      flippingToolboxItems = event.keyCode === _.keyCodes.TAB;
+  private activateToolbox(): void {
+    if (!this.Editor.Toolbar.opened) {
+      this.Editor.Toolbar.open(false, false);
+      this.Editor.Toolbar.plusButton.show();
+    }
+
+    this.Editor.Toolbox.open();
+  }
 
-    return !(event.shiftKey || flippingToolboxItems || toolboxItemSelected);
+  /**
+   * Open Toolbar and show BlockSettings before flipping Tools
+   */
+  private activateBlockSettings(): void {
+    if (!this.Editor.Toolbar.opened) {
+      this.Editor.BlockManager.currentBlock.focused = true;
+      this.Editor.Toolbar.open(true, false);
+      this.Editor.Toolbar.plusButton.hide();
+    }
+
+    /**
+     * If BlockSettings is not open, then open BlockSettings
+     * Next Tab press will leaf Settings Buttons
+     */
+    if (!this.Editor.BlockSettings.opened) {
+      this.Editor.BlockSettings.open();
+    }
   }
 }
diff --git a/src/components/modules/blockManager.ts b/src/components/modules/blockManager.ts
index fcb0456e0..77c1447fd 100644
--- a/src/components/modules/blockManager.ts
+++ b/src/components/modules/blockManager.ts
@@ -6,23 +6,23 @@
  *
  * @version 2.0.0
  */
-import Block from '../block';
+import Block, { BlockToolAPI } from '../block';
 import Module from '../__module';
 import $ from '../dom';
-import _ from '../utils';
+import * as _ from '../utils';
 import Blocks from '../blocks';
-import {BlockTool, BlockToolConstructable, BlockToolData, PasteEvent, ToolConfig} from '../../../types';
+import { BlockToolConstructable, BlockToolData, PasteEvent } from '../../../types';
 
 /**
  * @typedef {BlockManager} BlockManager
- * @property {Number} currentBlockIndex - Index of current working block
+ * @property {number} currentBlockIndex - Index of current working block
  * @property {Proxy} _blocks - Proxy for Blocks instance {@link Blocks}
  */
 export default class BlockManager extends Module {
-
   /**
    * Returns current Block index
-   * @return {number}
+   *
+   * @returns {number}
    */
   public get currentBlockIndex(): number {
     return this._currentBlockIndex;
@@ -30,7 +30,8 @@ export default class BlockManager extends Module {
 
   /**
    * Set current Block index and fire Block lifecycle callbacks
-   * @param newIndex
+   *
+   * @param {number} newIndex - index of Block to set as current
    */
   public set currentBlockIndex(newIndex: number) {
     if (this._blocks[this._currentBlockIndex]) {
@@ -46,7 +47,8 @@ export default class BlockManager extends Module {
 
   /**
    * returns first Block
-   * @return {Block}
+   *
+   * @returns {Block}
    */
   public get firstBlock(): Block {
     return this._blocks[0];
@@ -54,7 +56,8 @@ export default class BlockManager extends Module {
 
   /**
    * returns last Block
-   * @return {Block}
+   *
+   * @returns {Block}
    */
   public get lastBlock(): Block {
     return this._blocks[this._blocks.length - 1];
@@ -63,7 +66,7 @@ export default class BlockManager extends Module {
   /**
    * Get current Block instance
    *
-   * @return {Block}
+   * @returns {Block}
    */
   public get currentBlock(): Block {
     return this._blocks[this.currentBlockIndex];
@@ -71,7 +74,8 @@ export default class BlockManager extends Module {
 
   /**
    * Returns next Block instance
-   * @return {Block|null}
+   *
+   * @returns {Block|null}
    */
   public get nextBlock(): Block {
     const isLastBlock = this.currentBlockIndex === (this._blocks.length - 1);
@@ -107,7 +111,8 @@ export default class BlockManager extends Module {
 
   /**
    * Returns previous Block instance
-   * @return {Block|null}
+   *
+   * @returns {Block|null}
    */
   public get previousBlock(): Block {
     const isFirstBlock = this.currentBlockIndex === 0;
@@ -142,7 +147,7 @@ export default class BlockManager extends Module {
    *
    * @type {number}
    */
-  private _currentBlockIndex: number = -1;
+  private _currentBlockIndex = -1;
 
   /**
    * Proxy for Blocks instance {@link Blocks}
@@ -155,12 +160,9 @@ export default class BlockManager extends Module {
   /**
    * Should be called after Editor.UI preparation
    * Define this._blocks property
-   *
-   * @returns {Promise}
    */
-  public async prepare() {
+  public prepare(): void {
     const blocks = new Blocks(this.Editor.UI.nodes.redactor);
-    const { BlockEvents, Shortcuts } = this.Editor;
 
     /**
      * We need to use Proxy to overload set/get [] operator.
@@ -181,38 +183,58 @@ export default class BlockManager extends Module {
       get: Blocks.get,
     });
 
-    /** Copy shortcut */
-    Shortcuts.add({
-      name: 'CMD+C',
-      handler: (event) => {
-        BlockEvents.handleCommandC(event);
-      },
-    });
+    /** Copy event */
+    this.listeners.on(
+      document,
+      'copy',
+      (e: ClipboardEvent) => this.Editor.BlockEvents.handleCommandC(e)
+    );
+  }
 
-    /** Copy and cut */
-    Shortcuts.add({
-      name: 'CMD+X',
-      handler: (event) => {
-        BlockEvents.handleCommandX(event);
-      },
-    });
+  /**
+   * Toggle read-only state
+   *
+   * If readOnly is true:
+   *  - Unbind event handlers from created Blocks
+   *
+   * if readOnly is false:
+   *  - Bind event handlers to all existing Blocks
+   *
+   * @param {boolean} readOnlyEnabled - "read only" state
+   */
+  public toggleReadOnly(readOnlyEnabled: boolean): void {
+    if (!readOnlyEnabled) {
+      this.enableModuleBindings();
+    } else {
+      this.disableModuleBindings();
+    }
   }
 
   /**
    * Creates Block instance by tool name
    *
-   * @param {String} toolName - tools passed in editor config {@link EditorConfig#tools}
-   * @param {Object} data - constructor params
-   * @param {Object} settings - block settings
+   * @param {object} options - block creation options
+   * @param {string} options.tool - tools passed in editor config {@link EditorConfig#tools}
+   * @param {BlockToolData} [options.data] - constructor params
    *
-   * @return {Block}
+   * @returns {Block}
    */
-  public composeBlock(toolName: string, data: BlockToolData = {}, settings: ToolConfig = {}): Block {
-    const toolInstance = this.Editor.Tools.construct(toolName, data) as BlockTool;
-    const toolClass = this.Editor.Tools.available[toolName] as BlockToolConstructable;
-    const block = new Block(toolName, toolInstance, toolClass, settings, this.Editor.API.methods);
+  public composeBlock({ tool, data = {} }: {tool: string; data?: BlockToolData}): Block {
+    const readOnly = this.Editor.ReadOnly.isEnabled;
+    const settings = this.Editor.Tools.getToolSettings(tool);
+    const Tool = this.Editor.Tools.available[tool] as BlockToolConstructable;
+    const block = new Block({
+      name: tool,
+      data,
+      Tool,
+      settings,
+      api: this.Editor.API,
+      readOnly,
+    });
 
-    this.bindEvents(block);
+    if (!readOnly) {
+      this.bindBlockEvents(block);
+    }
 
     return block;
   }
@@ -220,64 +242,109 @@ export default class BlockManager extends Module {
   /**
    * Insert new block into _blocks
    *
-   * @param {String} toolName — plugin name, by default method inserts initial block type
-   * @param {Object} data — plugin data
-   * @param {Object} settings - default settings
+   * @param {object} options - insert options
+   * @param {string} options.tool - plugin name, by default method inserts the default block type
+   * @param {object} options.data - plugin data
+   * @param {number} options.index - index where to insert new Block
+   * @param {boolean} options.needToFocus - flag shows if needed to update current Block index
+   * @param {boolean} options.replace - flag shows if block by passed index should be replaced with inserted one
    *
-   * @return {Block}
+   * @returns {Block}
    */
-  public insert(
-    toolName: string = this.config.initialBlock,
-    data: BlockToolData = {},
-    settings: ToolConfig = {},
-  ): Block {
-    // Increment index before construct,
-    // because developers can use API/Blocks/getCurrentInputIndex on the render() method
-    const newIndex = ++this.currentBlockIndex;
-    const block = this.composeBlock(toolName, data, settings);
+  public insert({
+    tool = this.config.defaultBlock,
+    data = {},
+    index,
+    needToFocus = true,
+    replace = false,
+  }: {
+    tool?: string;
+    data?: BlockToolData;
+    index?: number;
+    needToFocus?: boolean;
+    replace?: boolean;
+  } = {}): Block {
+    let newIndex = index;
+
+    if (newIndex === undefined) {
+      newIndex = this.currentBlockIndex + (replace ? 0 : 1);
+    }
+
+    const block = this.composeBlock({
+      tool,
+      data,
+    });
+
+    this._blocks.insert(newIndex, block, replace);
+
+    if (needToFocus) {
+      this.currentBlockIndex = newIndex;
+    } else if (newIndex <= this.currentBlockIndex) {
+      this.currentBlockIndex++;
+    }
 
-    this._blocks[newIndex] = block;
     return block;
   }
 
+  /**
+   * Replace current working block
+   *
+   * @param {object} options - replace options
+   * @param {string} options.tool — plugin name
+   * @param {BlockToolData} options.data — plugin data
+   *
+   * @returns {Block}
+   */
+  public replace({
+    tool = this.config.defaultBlock,
+    data = {},
+  }): Block {
+    return this.insert({
+      tool,
+      data,
+      index: this.currentBlockIndex,
+      replace: true,
+    });
+  }
+
   /**
    * Insert pasted content. Call onPaste callback after insert.
    *
-   * @param {string} toolName
+   * @param {string} toolName - name of Tool to insert
    * @param {PasteEvent} pasteEvent - pasted data
    * @param {boolean} replace - should replace current block
    */
   public paste(
     toolName: string,
     pasteEvent: PasteEvent,
-    replace: boolean = false,
+    replace = false
   ): Block {
-    let block;
-
-    if (replace) {
-      block = this.replace(toolName);
-    } else {
-      block = this.insert(toolName);
-    }
+    const block = this.insert({
+      tool: toolName,
+      replace,
+    });
 
     try {
-      block.call('onPaste', pasteEvent);
+      block.call(BlockToolAPI.ON_PASTE, pasteEvent);
     } catch (e) {
       _.log(`${toolName}: onPaste callback call is failed`, 'error', e);
     }
+
     return block;
   }
 
   /**
-   * Insert new initial block at passed index
+   * Insert new default block at passed index
    *
    * @param {number} index - index where Block should be inserted
    * @param {boolean} needToFocus - if true, updates current Block index
    *
-   * @return {Block} inserted Block
+   * TODO: Remove method and use insert() with index instead (?)
+   *
+   * @returns {Block} inserted Block
    */
-  public insertAtIndex(index: number, needToFocus: boolean = false) {
-    const block = this.composeBlock(this.config.initialBlock, {}, {});
+  public insertDefaultBlockAtIndex(index: number, needToFocus = false): Block {
+    const block = this.composeBlock({ tool: this.config.defaultBlock });
 
     this._blocks[index] = block;
 
@@ -292,7 +359,8 @@ export default class BlockManager extends Module {
 
   /**
    * Always inserts at the end
-   * @return {Block}
+   *
+   * @returns {Block}
    */
   public insertAtEnd(): Block {
     /**
@@ -301,17 +369,18 @@ export default class BlockManager extends Module {
     this.currentBlockIndex = this.blocks.length - 1;
 
     /**
-     * Insert initial typed block
+     * Insert the default typed block
      */
     return this.insert();
   }
 
   /**
    * Merge two blocks
+   *
    * @param {Block} targetBlock - previous block will be append to this block
    * @param {Block} blockToMerge - block that will be merged with target block
    *
-   * @return {Promise} - the sequence that can be continued
+   * @returns {Promise} - the sequence that can be continued
    */
   public async mergeBlocks(targetBlock: Block, blockToMerge: Block): Promise {
     const blockToMergeIndex = this._blocks.indexOf(blockToMerge);
@@ -332,12 +401,18 @@ export default class BlockManager extends Module {
 
   /**
    * Remove block with passed index or remove last
-   * @param {Number|null} index
+   *
+   * @param {number|null} index - index of Block to remove
+   * @throws {Error} if Block to remove is not found
    */
-  public removeBlock(index?: number): void {
-    if (index === undefined) {
-      index = this.currentBlockIndex;
+  public removeBlock(index = this.currentBlockIndex): void {
+    /**
+     * If index is not passed and there is no block selected, show a warning
+     */
+    if (!this.validateIndex(index)) {
+      throw new Error('Can\'t find a Block to remove');
     }
+
     this._blocks.remove(index);
 
     if (this.currentBlockIndex >= index) {
@@ -350,7 +425,6 @@ export default class BlockManager extends Module {
     if (!this.blocks.length) {
       this.currentBlockIndex = -1;
       this.insert();
-      return;
     } else if (index === 0) {
       this.currentBlockIndex = 0;
     }
@@ -359,9 +433,10 @@ export default class BlockManager extends Module {
   /**
    * Remove only selected Blocks
    * and returns first Block index where started removing...
-   * @return number|undefined
+   *
+   * @returns {number|undefined}
    */
-  public removeSelectedBlocks(): number|undefined {
+  public removeSelectedBlocks(): number | undefined {
     let firstSelectedBlockIndex;
 
     /**
@@ -381,7 +456,7 @@ export default class BlockManager extends Module {
 
   /**
    * Attention!
-   * After removing insert new initial typed Block and focus on it
+   * After removing insert the new default typed Block and focus on it
    * Removes all blocks
    */
   public removeAllBlocks(): void {
@@ -399,7 +474,7 @@ export default class BlockManager extends Module {
    * 1. Extract content from Caret position to the Block`s end
    * 2. Insert a new Block below current one with extracted content
    *
-   * @return {Block}
+   * @returns {Block}
    */
   public split(): Block {
     const extractedFragment = this.Editor.Caret.extractFragmentFromCaretPosition();
@@ -416,34 +491,18 @@ export default class BlockManager extends Module {
 
     /**
      * Renew current Block
+     *
      * @type {Block}
      */
-    return this.insert(this.config.initialBlock, data);
+    return this.insert({ data });
   }
 
   /**
-   * Replace current working block
+   * Returns Block by passed index
    *
-   * @param {String} toolName — plugin name
-   * @param {Object} data — plugin data
+   * @param {number} index - index to get
    *
-   * @return {Block}
-   */
-  public replace(
-    toolName: string = this.config.initialBlock,
-    data: BlockToolData = {},
-  ): Block {
-    const block = this.composeBlock(toolName, data);
-
-    this._blocks.insert(this.currentBlockIndex, block, true);
-
-    return block;
-  }
-
-  /**
-   * Returns Block by passed index
-   * @param {Number} index
-   * @return {Block}
+   * @returns {Block}
    */
   public getBlockByIndex(index): Block {
     return this._blocks[index];
@@ -451,17 +510,19 @@ export default class BlockManager extends Module {
 
   /**
    * Get Block instance by html element
-   * @param {Node} element
+   *
+   * @param {Node} element - html element to get Block by
+   *
    * @returns {Block}
    */
   public getBlock(element: HTMLElement): Block {
-    if (!$.isElement(element)) {
+    if (!$.isElement(element) as boolean) {
       element = element.parentNode as HTMLElement;
     }
 
     const nodes = this._blocks.nodes,
-      firstLevelBlock = element.closest(`.${Block.CSS.wrapper}`),
-      index = nodes.indexOf(firstLevelBlock as HTMLElement);
+        firstLevelBlock = element.closest(`.${Block.CSS.wrapper}`),
+        index = nodes.indexOf(firstLevelBlock as HTMLElement);
 
     if (index >= 0) {
       return this._blocks[index];
@@ -479,6 +540,7 @@ export default class BlockManager extends Module {
 
     /**
      * Mark current Block as selected
+     *
      * @type {boolean}
      */
     this.currentBlock.focused = true;
@@ -488,18 +550,19 @@ export default class BlockManager extends Module {
    * Remove selection from all Blocks
    */
   public clearFocused(): void {
-    this.blocks.forEach( (block) => block.focused = false);
+    this.blocks.forEach((block) => {
+      block.focused = false;
+    });
   }
 
   /**
    * 1) Find first-level Block from passed child Node
    * 2) Mark it as current
    *
-   *  @param {Node} childNode - look ahead from this node.
-   *  @param {string} caretPosition - position where to set caret
-   *  @throws Error  - when passed Node is not included at the Block
+   * @param {Node} childNode - look ahead from this node.
+   * @returns {Block | undefined} can return undefined in case when the passed child note is not a part of the current editor instance
    */
-  public setCurrentBlockByChildNode(childNode: Node): Block {
+  public setCurrentBlockByChildNode(childNode: Node): Block | undefined {
     /**
      * If node is Text TextNode
      */
@@ -509,23 +572,44 @@ export default class BlockManager extends Module {
 
     const parentFirstLevelBlock = (childNode as HTMLElement).closest(`.${Block.CSS.wrapper}`);
 
-    if (parentFirstLevelBlock) {
-      /**
-       * Update current Block's index
-       * @type {number}
-       */
-      this.currentBlockIndex = this._blocks.nodes.indexOf(parentFirstLevelBlock as HTMLElement);
-      return this.currentBlock;
-    } else {
-      throw new Error('Can not find a Block from this child Node');
+    if (!parentFirstLevelBlock) {
+      return;
     }
+
+    /**
+     * Support multiple Editor.js instances,
+     * by checking whether the found block belongs to the current instance
+     *
+     * @see {@link Ui#documentTouched}
+     */
+    const editorWrapper = parentFirstLevelBlock.closest(`.${this.Editor.UI.CSS.editorWrapper}`);
+    const isBlockBelongsToCurrentInstance = editorWrapper?.isEqualNode(this.Editor.UI.nodes.wrapper);
+
+    if (!isBlockBelongsToCurrentInstance) {
+      return;
+    }
+
+    /**
+     * Update current Block's index
+     *
+     * @type {number}
+     */
+    this.currentBlockIndex = this._blocks.nodes.indexOf(parentFirstLevelBlock as HTMLElement);
+
+    /**
+     * Update current block active input
+     */
+    this.currentBlock.updateCurrentInput();
+
+    return this.currentBlock;
   }
 
   /**
    * Return block which contents passed node
    *
-   * @param {Node} childNode
-   * @return {Block}
+   * @param {Node} childNode - node to get Block by
+   *
+   * @returns {Block}
    */
   public getBlockByChildNode(childNode: Node): Block {
     /**
@@ -542,8 +626,11 @@ export default class BlockManager extends Module {
 
   /**
    * Swap Blocks Position
-   * @param {Number} fromIndex
-   * @param {Number} toIndex
+   *
+   * @param {number} fromIndex - index of first block
+   * @param {number} toIndex - index of second block
+   *
+   * @deprecated — use 'move' instead
    */
   public swap(fromIndex, toIndex): void {
     /** Move up current Block */
@@ -553,6 +640,33 @@ export default class BlockManager extends Module {
     this.currentBlockIndex = toIndex;
   }
 
+  /**
+   * Move a block to a new index
+   *
+   * @param {number} toIndex - index where to move Block
+   * @param {number} fromIndex - index of Block to move
+   */
+  public move(toIndex, fromIndex = this.currentBlockIndex): void {
+    // make sure indexes are valid and within a valid range
+    if (isNaN(toIndex) || isNaN(fromIndex)) {
+      _.log(`Warning during 'move' call: incorrect indices provided.`, 'warn');
+
+      return;
+    }
+
+    if (!this.validateIndex(toIndex) || !this.validateIndex(fromIndex)) {
+      _.log(`Warning during 'move' call: indices cannot be lower than 0 or greater than the amount of blocks.`, 'warn');
+
+      return;
+    }
+
+    /** Move up current Block */
+    this._blocks.move(toIndex, fromIndex);
+
+    /** Now actual block moved so that current block index changed */
+    this.currentBlockIndex = toIndex;
+  }
+
   /**
    * Sets current Block Index -1 which means unknown
    * and clear highlightings
@@ -564,30 +678,93 @@ export default class BlockManager extends Module {
 
   /**
    * Clears Editor
-   * @param {boolean} needAddInitialBlock - 1) in internal calls (for example, in api.blocks.render)
-   *                                        we don't need to add empty initial block
+   *
+   * @param {boolean} needToAddDefaultBlock - 1) in internal calls (for example, in api.blocks.render)
+   *                                             we don't need to add an empty default block
    *                                        2) in api.blocks.clear we should add empty block
    */
-  public clear(needAddInitialBlock: boolean = false): void {
+  public clear(needToAddDefaultBlock = false): void {
     this._blocks.removeAll();
     this.dropPointer();
 
-    if (needAddInitialBlock) {
-      this.insert(this.config.initialBlock);
+    if (needToAddDefaultBlock) {
+      this.insert();
     }
+
+    /**
+     * Add empty modifier
+     */
+    this.Editor.UI.checkEmptiness();
   }
 
   /**
-   * Bind Events
-   * @param {Object} block
+   * Cleans up all the block tools' resources
+   * This is called when editor is destroyed
    */
-  private bindEvents(block: Block): void {
-    const {BlockEvents, Listeners} = this.Editor;
+  public async destroy(): Promise {
+    await Promise.all(this.blocks.map((block) => {
+      if (_.isFunction(block.tool.destroy)) {
+        return block.tool.destroy();
+      }
+    }));
+  }
+
+  /**
+   * Bind Block events
+   *
+   * @param {Block} block - Block to which event should be bound
+   */
+  private bindBlockEvents(block: Block): void {
+    const { BlockEvents } = this.Editor;
+
+    this.readOnlyMutableListeners.on(block.holder, 'keydown', (event: KeyboardEvent) => {
+      BlockEvents.keydown(event);
+    });
+
+    this.readOnlyMutableListeners.on(block.holder, 'keyup', (event: KeyboardEvent) => {
+      BlockEvents.keyup(event);
+    });
+
+    this.readOnlyMutableListeners.on(block.holder, 'dragover', (event: DragEvent) => {
+      BlockEvents.dragOver(event);
+    });
 
-    Listeners.on(block.holder, 'keydown', (event) => BlockEvents.keydown(event as KeyboardEvent), true);
-    Listeners.on(block.holder, 'mouseup', (event) => BlockEvents.mouseUp(event));
-    Listeners.on(block.holder, 'keyup', (event) => BlockEvents.keyup(event));
-    Listeners.on(block.holder, 'dragover', (event) => BlockEvents.dragOver(event as DragEvent));
-    Listeners.on(block.holder, 'dragleave', (event) => BlockEvents.dragLeave(event as DragEvent));
+    this.readOnlyMutableListeners.on(block.holder, 'dragleave', (event: DragEvent) => {
+      BlockEvents.dragLeave(event);
+    });
+  }
+
+  /**
+   * Disable mutable handlers and bindings
+   */
+  private disableModuleBindings(): void {
+    this.readOnlyMutableListeners.clearAll();
+  }
+
+  /**
+   * Enables all module handlers and bindings for all Blocks
+   */
+  private enableModuleBindings(): void {
+    /** Cut event */
+    this.readOnlyMutableListeners.on(
+      document,
+      'cut',
+      (e: ClipboardEvent) => this.Editor.BlockEvents.handleCommandX(e)
+    );
+
+    this.blocks.forEach((block: Block) => {
+      this.bindBlockEvents(block);
+    });
+  }
+
+  /**
+   * Validates that the given index is not lower than 0 or higher than the amount of blocks
+   *
+   * @param {number} index - index of blocks array to validate
+   *
+   * @returns {boolean}
+   */
+  private validateIndex(index: number): boolean {
+    return !(index < 0 || index >= this._blocks.length);
   }
 }
diff --git a/src/components/modules/blockSelection.ts b/src/components/modules/blockSelection.ts
index 832306695..1c05d2391 100644
--- a/src/components/modules/blockSelection.ts
+++ b/src/components/modules/blockSelection.ts
@@ -6,19 +6,33 @@
  * @version 1.0.0
  */
 import Module from '../__module';
-import _ from '../utils';
+import Block from '../block';
+import * as _ from '../utils';
 import $ from '../dom';
+import Shortcuts from '../utils/shortcuts';
 
 import SelectionUtils from '../selection';
-import Block from '../block';
+import { SanitizerConfig } from '../../../types/configs';
 
+/**
+ *
+ */
 export default class BlockSelection extends Module {
+  /**
+   * Sometimes .anyBlockSelected can be called frequently,
+   * for example at ui@selectionChange (to clear native browser selection in CBS)
+   * We use cache to prevent multiple iterations through all the blocks
+   *
+   * @private
+   */
+  private anyBlockSelectedCache: boolean | null = null;
 
   /**
    * Sanitizer Config
-   * @return {SanitizerConfig}
+   *
+   * @returns {SanitizerConfig}
    */
-  private get sanitizerConfig() {
+  private get sanitizerConfig(): SanitizerConfig {
     return {
       p: {},
       h1: {},
@@ -47,50 +61,81 @@ export default class BlockSelection extends Module {
 
   /**
    * Flag that identifies all Blocks selection
-   * @return {boolean}
+   *
+   * @returns {boolean}
    */
   public get allBlocksSelected(): boolean {
-    const {BlockManager} = this.Editor;
+    const { BlockManager } = this.Editor;
 
     return BlockManager.blocks.every((block) => block.selected === true);
   }
 
   /**
    * Set selected all blocks
-   * @param {boolean} state
+   *
+   * @param {boolean} state - state to set
    */
   public set allBlocksSelected(state: boolean) {
-    const {BlockManager} = this.Editor;
+    const { BlockManager } = this.Editor;
 
-    BlockManager.blocks.forEach((block) => block.selected = state);
+    BlockManager.blocks.forEach((block) => {
+      block.selected = state;
+    });
+
+    this.clearCache();
   }
 
   /**
    * Flag that identifies any Block selection
-   * @return {boolean}
+   *
+   * @returns {boolean}
    */
   public get anyBlockSelected(): boolean {
-    const {BlockManager} = this.Editor;
+    const { BlockManager } = this.Editor;
 
-    return BlockManager.blocks.some((block) => block.selected === true);
+    if (this.anyBlockSelectedCache === null) {
+      this.anyBlockSelectedCache = BlockManager.blocks.some((block) => block.selected === true);
+    }
+
+    return this.anyBlockSelectedCache;
+  }
+
+  /**
+   * Return selected Blocks array
+   *
+   * @returns {Block[]}
+   */
+  public get selectedBlocks(): Block[] {
+    return this.Editor.BlockManager.blocks.filter((block: Block) => block.selected);
   }
 
   /**
    * Flag used to define block selection
    * First CMD+A defines it as true and then second CMD+A selects all Blocks
+   *
    * @type {boolean}
    */
-  private needToSelectAll: boolean = false;
+  private needToSelectAll = false;
 
   /**
    * Flag used to define native input selection
    * In this case we allow double CMD+A to select Block
+   *
    * @type {boolean}
    */
-  private nativeInputSelected: boolean = false;
+  private nativeInputSelected = false;
+
+  /**
+   * Flag identifies any input selection
+   * That means we can select whole Block
+   *
+   * @type {boolean}
+   */
+  private readyToBlockSelection = false;
 
   /**
    * SelectionUtils instance
+   *
    * @type {SelectionUtils}
    */
   private selection: SelectionUtils;
@@ -101,16 +146,30 @@ export default class BlockSelection extends Module {
    * to select all and copy them
    */
   public prepare(): void {
-    const {Shortcuts} = this.Editor;
+    this.selection = new SelectionUtils();
 
-    /** Selection shortcut */
+    /**
+     * CMD/CTRL+A selection shortcut
+     */
     Shortcuts.add({
       name: 'CMD+A',
       handler: (event) => {
-        const {BlockManager} = this.Editor;
+        const { BlockManager, ReadOnly } = this.Editor;
+
+        /**
+         * We use Editor's Block selection on CMD+A ShortCut instead of Browsers
+         */
+        if (ReadOnly.isEnabled) {
+          event.preventDefault();
+          this.selectAllBlocks();
+
+          return;
+        }
+
         /**
          * When one page consist of two or more EditorJS instances
-         * Shortcut module tries to handle all events. Thats why Editor's selection works inside the target Editor, but
+         * Shortcut module tries to handle all events.
+         * Thats why Editor's selection works inside the target Editor, but
          * for others error occurs because nothing to select.
          *
          * Prevent such actions if focus is not inside the Editor
@@ -121,17 +180,32 @@ export default class BlockSelection extends Module {
 
         this.handleCommandA(event);
       },
+      on: this.Editor.UI.nodes.redactor,
     });
+  }
 
-    this.selection = new SelectionUtils();
+  /**
+   * Toggle read-only state
+   *
+   *  - Remove all ranges
+   *  - Unselect all Blocks
+   *
+   * @param {boolean} readOnlyEnabled - "read only" state
+   */
+  public toggleReadOnly(readOnlyEnabled: boolean): void {
+    SelectionUtils.get()
+      .removeAllRanges();
+
+    this.allBlocksSelected = false;
   }
 
   /**
    * Remove selection of Block
+   *
    * @param {number?} index - Block index according to the BlockManager's indexes
    */
-  public unSelectBlockByIndex(index?) {
-    const {BlockManager} = this.Editor;
+  public unSelectBlockByIndex(index?): void {
+    const { BlockManager } = this.Editor;
 
     let block;
 
@@ -142,17 +216,53 @@ export default class BlockSelection extends Module {
     }
 
     block.selected = false;
+
+    this.clearCache();
   }
 
   /**
    * Clear selection from Blocks
+   *
+   * @param {Event} reason - event caused clear of selection
+   * @param {boolean} restoreSelection - if true, restore saved selection
    */
-  public clearSelection(restoreSelection = false) {
+  public clearSelection(reason?: Event, restoreSelection = false): void {
+    const { BlockManager, Caret, RectangleSelection } = this.Editor;
+
     this.needToSelectAll = false;
     this.nativeInputSelected = false;
+    this.readyToBlockSelection = false;
+
+    const isKeyboard = reason && (reason instanceof KeyboardEvent);
+    const isPrintableKey = isKeyboard && _.isPrintableKey((reason as KeyboardEvent).keyCode);
+
+    /**
+     * If reason caused clear of the selection was printable key and any block is selected,
+     * remove selected blocks and insert pressed key
+     */
+    if (this.anyBlockSelected && isKeyboard && isPrintableKey && !SelectionUtils.isSelectionExists) {
+      const indexToInsert = BlockManager.removeSelectedBlocks();
+
+      BlockManager.insertDefaultBlockAtIndex(indexToInsert, true);
+      Caret.setToBlock(BlockManager.currentBlock);
+      _.delay(() => {
+        const eventKey = (reason as KeyboardEvent).key;
+
+        /**
+         * If event.key length >1 that means key is special (e.g. Enter or Dead or Unidentifier).
+         * So we use empty string
+         *
+         * @see https://developer.mozilla.org/ru/docs/Web/API/KeyboardEvent/key
+         */
+        Caret.insertContentAtCaretPosition(eventKey.length > 1 ? '' : eventKey);
+      }, 20)();
+    }
+
+    this.Editor.CrossBlockSelection.clear(reason);
 
-    if (!this.anyBlockSelected || this.Editor.RectangleSelection.isRectActivated()) {
+    if (!this.anyBlockSelected || RectangleSelection.isRectActivated()) {
       this.Editor.RectangleSelection.clearSelection();
+
       return;
     }
 
@@ -170,32 +280,48 @@ export default class BlockSelection extends Module {
 
   /**
    * Reduce each Block and copy its content
+   *
+   * @param {ClipboardEvent} e - copy/cut event
+   *
+   * @returns {Promise}
    */
-  public copySelectedBlocks(): void {
-    const {BlockManager, Sanitizer} = this.Editor;
+  public async copySelectedBlocks(e: ClipboardEvent): Promise {
+    /**
+     * Prevent default copy
+     */
+    e.preventDefault();
+
     const fakeClipboard = $.make('div');
 
-    BlockManager.blocks.filter((block) => block.selected)
-      .forEach((block) => {
-        /**
-         * Make 

tag that holds clean HTML - */ - const cleanHTML = Sanitizer.clean(block.holder.innerHTML, this.sanitizerConfig); - const fragment = $.make('p'); + this.selectedBlocks.forEach((block) => { + /** + * Make

tag that holds clean HTML + */ + const cleanHTML = this.Editor.Sanitizer.clean(block.holder.innerHTML, this.sanitizerConfig); + const fragment = $.make('p'); + + fragment.innerHTML = cleanHTML; + fakeClipboard.appendChild(fragment); + }); + + const savedData = await Promise.all(this.selectedBlocks.map((block) => block.save())); - fragment.innerHTML = cleanHTML; - fakeClipboard.appendChild(fragment); - }); + const textPlain = Array.from(fakeClipboard.childNodes).map((node) => node.textContent) + .join('\n\n'); + const textHTML = fakeClipboard.innerHTML; - _.copyTextToClipboard(fakeClipboard.innerHTML); + e.clipboardData.setData('text/plain', textPlain); + e.clipboardData.setData('text/html', textHTML); + e.clipboardData.setData(this.Editor.Paste.MIME_TYPE, JSON.stringify(savedData)); } /** * select Block + * * @param {number?} index - Block index according to the BlockManager's indexes */ - public selectBlockByIndex(index?) { - const {BlockManager} = this.Editor; + public selectBlockByIndex(index?): void { + const { BlockManager } = this.Editor; /** * Remove previous focused Block's state @@ -216,31 +342,96 @@ export default class BlockSelection extends Module { .removeAllRanges(); block.selected = true; + + this.clearCache(); + + /** close InlineToolbar when we selected any Block */ + this.Editor.InlineToolbar.close(); } /** - * First CMD+A Selects current focused blocks, - * and consequent second CMD+A keypress selects all blocks + * Clear anyBlockSelected cache + */ + public clearCache(): void { + this.anyBlockSelectedCache = null; + } + + /** + * Module destruction + * De-registers Shortcut CMD+A + */ + public destroy(): void { + /** Selection shortcut */ + Shortcuts.remove(this.Editor.UI.nodes.redactor, 'CMD+A'); + } + + /** + * First CMD+A selects all input content by native behaviour, + * next CMD+A keypress selects all blocks * - * @param {keydown} event + * @param {KeyboardEvent} event - keyboard event */ - private handleCommandA(event): void { + private handleCommandA(event: KeyboardEvent): void { this.Editor.RectangleSelection.clearSelection(); /** allow default selection on native inputs */ - if ($.isNativeInput(event.target) && !this.nativeInputSelected) { - this.nativeInputSelected = true; + if ($.isNativeInput(event.target) && !this.readyToBlockSelection) { + this.readyToBlockSelection = true; + + return; + } + + const workingBlock = this.Editor.BlockManager.getBlock(event.target as HTMLElement); + const inputs = workingBlock.inputs; + + /** + * If Block has more than one editable element allow native selection + * Second cmd+a will select whole Block + */ + if (inputs.length > 1 && !this.readyToBlockSelection) { + this.readyToBlockSelection = true; + return; } - /** Prevent default selection */ - event.preventDefault(); + if (inputs.length === 1 && !this.needToSelectAll) { + this.needToSelectAll = true; + + return; + } if (this.needToSelectAll) { + /** + * Prevent default selection + */ + event.preventDefault(); + this.selectAllBlocks(); + + /** + * Disable any selection after all Blocks selected + */ this.needToSelectAll = false; - } else { + this.readyToBlockSelection = false; + + /** + * Close ConversionToolbar when all Blocks selected + */ + this.Editor.ConversionToolbar.close(); + } else if (this.readyToBlockSelection) { + /** + * prevent default selection when we use custom selection + */ + event.preventDefault(); + + /** + * select working Block + */ this.selectBlockByIndex(); + + /** + * Enable all Blocks selection if current Block is selected + */ this.needToSelectAll = true; } } @@ -249,7 +440,22 @@ export default class BlockSelection extends Module { * Select All Blocks * Each Block has selected setter that makes Block copyable */ - private selectAllBlocks() { + private selectAllBlocks(): void { + /** + * Save selection + * Will be restored when closeSelection fired + */ + this.selection.save(); + + /** + * Remove Ranges from Selection + */ + SelectionUtils.get() + .removeAllRanges(); + this.allBlocksSelected = true; + + /** close InlineToolbar if we selected all Blocks */ + this.Editor.InlineToolbar.close(); } } diff --git a/src/components/modules/caret.ts b/src/components/modules/caret.ts index 2615c9f7e..2f38dc7ce 100644 --- a/src/components/modules/caret.ts +++ b/src/components/modules/caret.ts @@ -13,20 +13,19 @@ import Selection from '../selection'; import Module from '../__module'; import Block from '../block'; import $ from '../dom'; -import _ from '../utils'; +import * as _ from '../utils'; /** * @typedef {Caret} Caret */ export default class Caret extends Module { - /** * Allowed caret positions in input * * @static * @returns {{START: string, END: string, DEFAULT: string}} */ - public get positions(): {START: string, END: string, DEFAULT: string} { + public get positions(): {START: string; END: string; DEFAULT: string} { return { START: 'start', END: 'end', @@ -45,31 +44,32 @@ export default class Caret extends Module { /** * Get's deepest first node and checks if offset is zero - * @return {boolean} + * + * @returns {boolean} */ public get isAtStart(): boolean { - /** - * Don't handle ranges - */ - if (!Selection.isCollapsed) { - return false; - } - const selection = Selection.get(); const firstNode = $.getDeepestNode(this.Editor.BlockManager.currentBlock.currentInput); - let anchorNode = selection.anchorNode; + let focusNode = selection.focusNode; /** In case lastNode is native input */ if ($.isNativeInput(firstNode)) { return (firstNode as HTMLInputElement).selectionEnd === 0; } + /** Case when selection have been cleared programmatically, for example after CBS */ + if (!selection.anchorNode) { + return false; + } + /** * Workaround case when caret in the text like " |Hello!" * selection.anchorOffset is 1, but real caret visible position is 0 + * * @type {number} */ - let firstLetterPosition = anchorNode.textContent.search(/\S/); + + let firstLetterPosition = focusNode.textContent.search(/\S/); if (firstLetterPosition === -1) { // empty text firstLetterPosition = 0; @@ -82,16 +82,17 @@ export default class Caret extends Module { * In this case, anchor node has ELEMENT_NODE node type. * Anchor offset shows amount of children between start of the element and caret position. * - * So we use child with anchorOffset index as new anchorNode. + * So we use child with focusOffset index as new anchorNode. */ - let anchorOffset = selection.anchorOffset; - if (anchorNode.nodeType !== Node.TEXT_NODE && anchorNode.childNodes.length) { - if (anchorNode.childNodes[anchorOffset]) { - anchorNode = anchorNode.childNodes[anchorOffset]; - anchorOffset = 0; + let focusOffset = selection.focusOffset; + + if (focusNode.nodeType !== Node.TEXT_NODE && focusNode.childNodes.length) { + if (focusNode.childNodes[focusOffset]) { + focusNode = focusNode.childNodes[focusOffset]; + focusOffset = 0; } else { - anchorNode = anchorNode.childNodes[anchorOffset - 1]; - anchorOffset = anchorNode.textContent.length; + focusNode = focusNode.childNodes[focusOffset - 1]; + focusOffset = focusNode.textContent.length; } } @@ -99,14 +100,29 @@ export default class Caret extends Module { * In case of *

*

<-- first (and deepest) node is - * |adaddad <-- anchor node + * |adaddad <-- focus node *
*/ if ($.isLineBreakTag(firstNode as HTMLElement) || $.isEmpty(firstNode)) { - const leftSiblings = this.getHigherLevelSiblings(anchorNode as HTMLElement, 'left'); - const nothingAtLeft = leftSiblings.every((node, i) => $.isEmpty(node)); + const leftSiblings = this.getHigherLevelSiblings(focusNode as HTMLElement, 'left'); + const nothingAtLeft = leftSiblings.every((node) => { + /** + * Workaround case when block starts with several
's (created by SHIFT+ENTER) + * + * @see https://github.com/codex-team/editor.js/issues/726 + * We need to allow to delete such linebreaks, so in this case caret IS NOT AT START + */ + const regularLineBreak = $.isLineBreakTag(node); + /** + * Workaround SHIFT+ENTER in Safari, that creates

instead of
+ */ + const lineBreakInSafari = node.children.length === 1 && $.isLineBreakTag(node.children[0] as HTMLElement); + const isLineBreak = regularLineBreak || lineBreakInSafari; + + return $.isEmpty(node) && !isLineBreak; + }); - if (nothingAtLeft && anchorOffset === firstLetterPosition) { + if (nothingAtLeft && focusOffset === firstLetterPosition) { return true; } } @@ -115,23 +131,17 @@ export default class Caret extends Module { * We use <= comparison for case: * "| Hello" <--- selection.anchorOffset is 0, but firstLetterPosition is 1 */ - return firstNode === null || anchorNode === firstNode && anchorOffset <= firstLetterPosition; + return firstNode === null || (focusNode === firstNode && focusOffset <= firstLetterPosition); } /** * Get's deepest last node and checks if offset is last node text length - * @return {boolean} + * + * @returns {boolean} */ public get isAtEnd(): boolean { - /** - * Don't handle ranges - */ - if (!Selection.isCollapsed) { - return false; - } - const selection = Selection.get(); - let anchorNode = selection.anchorNode; + let focusNode = selection.focusNode; const lastNode = $.getDeepestNode(this.Editor.BlockManager.currentBlock.currentInput, true); @@ -140,6 +150,11 @@ export default class Caret extends Module { return (lastNode as HTMLInputElement).selectionEnd === (lastNode as HTMLInputElement).value.length; } + /** Case when selection have been cleared programmatically, for example after CBS */ + if (!selection.focusNode) { + return false; + } + /** * If caret was set by external code, it might be set to text node wrapper. *
hello|
<---- Selection references to
instead of text node @@ -147,16 +162,17 @@ export default class Caret extends Module { * In this case, anchor node has ELEMENT_NODE node type. * Anchor offset shows amount of children between start of the element and caret position. * - * So we use child with anchorOffset - 1 as new anchorNode. + * So we use child with anchofocusOffset - 1 as new focusNode. */ - let anchorOffset = selection.anchorOffset; - if (anchorNode.nodeType !== Node.TEXT_NODE && anchorNode.childNodes.length) { - if (anchorNode.childNodes[anchorOffset - 1]) { - anchorNode = anchorNode.childNodes[anchorOffset - 1]; - anchorOffset = anchorNode.textContent.length; + let focusOffset = selection.focusOffset; + + if (focusNode.nodeType !== Node.TEXT_NODE && focusNode.childNodes.length) { + if (focusNode.childNodes[focusOffset - 1]) { + focusNode = focusNode.childNodes[focusOffset - 1]; + focusOffset = focusNode.textContent.length; } else { - anchorNode = anchorNode.childNodes[0]; - anchorOffset = 0; + focusNode = focusNode.childNodes[0]; + focusOffset = 0; } } @@ -168,12 +184,17 @@ export default class Caret extends Module { *
*/ if ($.isLineBreakTag(lastNode as HTMLElement) || $.isEmpty(lastNode)) { - const rightSiblings = this.getHigherLevelSiblings(anchorNode as HTMLElement, 'right'); + const rightSiblings = this.getHigherLevelSiblings(focusNode as HTMLElement, 'right'); const nothingAtRight = rightSiblings.every((node, i) => { - return i === 0 && $.isLineBreakTag(node as HTMLElement) || $.isEmpty(node); + /** + * If last right sibling is BR isEmpty returns false, but there actually nothing at right + */ + const isLastBR = i === rightSiblings.length - 1 && $.isLineBreakTag(node as HTMLElement); + + return isLastBR || ($.isEmpty(node) && !$.isLineBreakTag(node)); }); - if (nothingAtRight && anchorOffset === anchorNode.textContent.length) { + if (nothingAtRight && focusOffset === focusNode.textContent.length) { return true; } } @@ -190,7 +211,7 @@ export default class Caret extends Module { * We use >= comparison for case: * "Hello |" <--- selection.anchorOffset is 7, but rightTrimmedText is 6 */ - return anchorNode === lastNode && anchorOffset >= rightTrimmedText.length; + return focusNode === lastNode && focusOffset >= rightTrimmedText.length; } /** @@ -200,12 +221,12 @@ export default class Caret extends Module { * - last found text node: sets at the end of the node. Also, you can customize the behaviour * * @param {Block} block - Block class - * @param {String} position - position where to set caret. + * @param {string} position - position where to set caret. * If default - leave default behaviour and apply offset if it's passed - * @param {Number} offset - caret offset regarding to the text node + * @param {number} offset - caret offset regarding to the text node */ - public setToBlock(block: Block, position: string = this.positions.DEFAULT, offset: number = 0): void { - const {BlockManager} = this.Editor; + public setToBlock(block: Block, position: string = this.positions.DEFAULT, offset = 0): void { + const { BlockManager } = this.Editor; let element; switch (position) { @@ -239,7 +260,7 @@ export default class Caret extends Module { /** * @todo try to fix via Promises or use querySelectorAll to not to use timeout */ - _.delay( () => { + _.delay(() => { this.set(nodeToSet as HTMLElement, offset); }, 20)(); @@ -251,12 +272,12 @@ export default class Caret extends Module { * Set caret to the current input of current Block. * * @param {HTMLElement} input - input where caret should be set - * @param {String} position - position of the caret. + * @param {string} position - position of the caret. * If default - leave default behaviour and apply offset if it's passed * @param {number} offset - caret offset regarding to the text node */ - public setToInput(input: HTMLElement, position: string = this.positions.DEFAULT, offset: number = 0): void { - const {currentBlock} = this.Editor.BlockManager; + public setToInput(input: HTMLElement, position: string = this.positions.DEFAULT, offset = 0): void { + const { currentBlock } = this.Editor.BlockManager; const nodeToSet = $.getDeepestNode(input); switch (position) { @@ -265,9 +286,7 @@ export default class Caret extends Module { break; case this.positions.END: - const contentLength = $.getContentLength(nodeToSet); - - this.set(nodeToSet as HTMLElement, contentLength); + this.set(nodeToSet as HTMLElement, $.getContentLength(nodeToSet)); break; default: @@ -281,39 +300,24 @@ export default class Caret extends Module { /** * Creates Document Range and sets caret to the element with offset + * * @param {HTMLElement} element - target node. - * @param {Number} offset - offset + * @param {number} offset - offset */ - public set(element: HTMLElement, offset: number = 0): void { - const range = document.createRange(), - selection = Selection.get(); - - /** if found deepest node is native input */ - if ($.isNativeInput(element)) { - if (!$.canSetCaret(element)) { - return; - } - - element.focus(); - (element as HTMLInputElement).selectionStart = (element as HTMLInputElement).selectionEnd = offset; - return; - } - - range.setStart(element, offset); - range.setEnd(element, offset); - - selection.removeAllRanges(); - selection.addRange(range); + public set(element: HTMLElement, offset = 0): void { + const { top, bottom } = Selection.setCursor(element, offset); /** If new cursor position is not visible, scroll to it */ - const {top, bottom} = element.nodeType === Node.ELEMENT_NODE - ? element.getBoundingClientRect() - : range.getBoundingClientRect(); - const {innerHeight} = window; + const { innerHeight } = window; - if (top < 0) { window.scrollBy(0, top); } - if (bottom > innerHeight) { window.scrollBy(0, bottom - innerHeight); } + if (top < 0) { + window.scrollBy(0, top); + } + if (bottom > innerHeight) { + window.scrollBy(0, bottom - innerHeight); + } } + /** * Set Caret to the last Block * If last block is not empty, append another empty block @@ -326,10 +330,10 @@ export default class Caret extends Module { } /** - * If last block is empty and it is an initialBlock, set to that. + * If last block is empty and it is an defaultBlock, set to that. * Otherwise, append new empty block and set to that */ - if (this.Editor.Tools.isInitial(lastBlock.tool) && lastBlock.isEmpty) { + if (this.Editor.Tools.isDefault(lastBlock.tool) && lastBlock.isEmpty) { this.setToBlock(lastBlock); } else { const newBlock = this.Editor.BlockManager.insertAtEnd(); @@ -351,11 +355,30 @@ export default class Caret extends Module { selectRange.deleteContents(); if (currentBlockInput) { - const range = selectRange.cloneRange(); + if ($.isNativeInput(currentBlockInput)) { + /** + * If input is native text input we need to use it's value + * Text before the caret stays in the input, + * while text after the caret is returned as a fragment to be inserted after the block. + */ + const input = currentBlockInput as HTMLInputElement | HTMLTextAreaElement; + const newFragment = document.createDocumentFragment(); + + const inputRemainingText = input.value.substring(0, input.selectionStart); + const fragmentText = input.value.substring(input.selectionStart); + + newFragment.textContent = fragmentText; + input.value = inputRemainingText; + + return newFragment; + } else { + const range = selectRange.cloneRange(); + + range.selectNodeContents(currentBlockInput); + range.setStart(selectRange.endContainer, selectRange.endOffset); - range.selectNodeContents(currentBlockInput); - range.setStart(selectRange.endContainer, selectRange.endOffset); - return range.extractContents(); + return range.extractContents(); + } } } } @@ -365,22 +388,42 @@ export default class Caret extends Module { * Before moving caret, we should check if caret position is at the end of Plugins node * Using {@link Dom#getDeepestNode} to get a last node and match with current selection * - * @param {Boolean} force - force navigation even if caret is not at the end - * - * @return {Boolean} + * @returns {boolean} */ - public navigateNext(force: boolean = false): boolean { - const {currentBlock, nextContentfulBlock} = this.Editor.BlockManager; - const {nextInput} = currentBlock; + public navigateNext(): boolean { + const { BlockManager, Tools } = this.Editor; + const { currentBlock, nextContentfulBlock } = BlockManager; + const { nextInput } = currentBlock; + const isAtEnd = this.isAtEnd; + + let nextBlock = nextContentfulBlock; + + if (!nextBlock && !nextInput) { + /** + * This code allows to exit from the last non-initial tool: + * https://github.com/codex-team/editor.js/issues/1103 + */ + + /** + * 1. If there is a last block and it is default, do nothing + * 2. If there is a last block and it is non-default --> and caret not at the end <--, do nothing + * (https://github.com/codex-team/editor.js/issues/1414) + */ + if (Tools.isDefault(currentBlock.tool) || !isAtEnd) { + return false; + } - if (!nextContentfulBlock && !nextInput) { - return false; + /** + * If there is no nextBlock, but currentBlock is not default, + * insert new default block at the end and navigate to it + */ + nextBlock = BlockManager.insertAtEnd(); } - if (force || this.isAtEnd) { + if (isAtEnd) { /** If next Tool`s input exists, focus on it. Otherwise set caret to the next Block */ if (!nextInput) { - this.setToBlock(nextContentfulBlock, this.positions.START); + this.setToBlock(nextBlock, this.positions.START); } else { this.setToInput(nextInput, this.positions.START); } @@ -396,30 +439,29 @@ export default class Caret extends Module { * Before moving caret, we should check if caret position is start of the Plugins node * Using {@link Dom#getDeepestNode} to get a last node and match with current selection * - * @param {Boolean} force - force navigation even if caret is not at the start - * - * @return {Boolean} + * @returns {boolean} */ - public navigatePrevious(force: boolean = false): boolean { - const {currentBlock, previousContentfulBlock} = this.Editor.BlockManager; + public navigatePrevious(): boolean { + const { currentBlock, previousContentfulBlock } = this.Editor.BlockManager; if (!currentBlock) { return false; } - const {previousInput} = currentBlock; + const { previousInput } = currentBlock; if (!previousContentfulBlock && !previousInput) { return false; } - if (force || this.isAtStart) { + if (this.isAtStart) { /** If previous Tool`s input exists, focus on it. Otherwise set caret to the previous Block */ if (!previousInput) { - this.setToBlock( previousContentfulBlock, this.positions.END ); + this.setToBlock(previousContentfulBlock, this.positions.END); } else { this.setToInput(previousInput, this.positions.END); } + return true; } @@ -428,18 +470,20 @@ export default class Caret extends Module { /** * Inserts shadow element after passed element where caret can be placed - * @param {Node} element + * + * @param {Element} element - element after which shadow caret should be inserted */ - public createShadow(element): void { + public createShadow(element: Element): void { const shadowCaret = document.createElement('span'); shadowCaret.classList.add(Caret.CSS.shadowCaret); - element.insertAdjacentElement('beforeEnd', shadowCaret); + element.insertAdjacentElement('beforeend', shadowCaret); } /** * Restores caret position - * @param {HTMLElement} element + * + * @param {HTMLElement} element - element where caret should be restored */ public restoreCaret(element: HTMLElement): void { const shadowCaret = element.querySelector(`.${Caret.CSS.shadowCaret}`); @@ -483,6 +527,13 @@ export default class Caret extends Module { Array.from(wrapper.childNodes).forEach((child: Node) => fragment.appendChild(child)); + /** + * If there is no child node, append empty one + */ + if (fragment.childNodes.length === 0) { + fragment.appendChild(new Text('')); + } + const lastChild = fragment.lastChild; range.deleteContents(); @@ -503,18 +554,21 @@ export default class Caret extends Module { * * @example *
* - * @return {Element[]} + * @param {HTMLElement} from - element from which siblings should be searched + * @param {'left' | 'right'} direction - direction of search + * + * @returns {HTMLElement[]} */ - private getHigherLevelSiblings(from: HTMLElement, direction?: string): HTMLElement[] { + private getHigherLevelSiblings(from: HTMLElement, direction?: 'left' | 'right'): HTMLElement[] { let current = from; const siblings = []; diff --git a/src/components/modules/crossBlockSelection.ts b/src/components/modules/crossBlockSelection.ts new file mode 100644 index 000000000..fa8c4962a --- /dev/null +++ b/src/components/modules/crossBlockSelection.ts @@ -0,0 +1,258 @@ +import Module from '../__module'; +import Block from '../block'; +import SelectionUtils from '../selection'; +import * as _ from '../utils'; + +/** + * + */ +export default class CrossBlockSelection extends Module { + /** + * Block where selection is started + */ + private firstSelectedBlock: Block; + + /** + * Last selected Block + */ + private lastSelectedBlock: Block; + + /** + * Module preparation + * + * @returns {Promise} + */ + public async prepare(): Promise { + this.listeners.on(document, 'mousedown', (event: MouseEvent) => { + this.enableCrossBlockSelection(event); + }); + } + + /** + * Sets up listeners + * + * @param {MouseEvent} event - mouse down event + */ + public watchSelection(event: MouseEvent): void { + if (event.button !== _.mouseButtons.LEFT) { + return; + } + + const { BlockManager } = this.Editor; + + this.firstSelectedBlock = BlockManager.getBlock(event.target as HTMLElement); + this.lastSelectedBlock = this.firstSelectedBlock; + + this.listeners.on(document, 'mouseover', this.onMouseOver); + this.listeners.on(document, 'mouseup', this.onMouseUp); + } + + /** + * return boolean is cross block selection started + */ + public get isCrossBlockSelectionStarted(): boolean { + return !!this.firstSelectedBlock && + !!this.lastSelectedBlock; + } + + /** + * Change selection state of the next Block + * Used for CBS via Shift + arrow keys + * + * @param {boolean} next - if true, toggle next block. Previous otherwise + */ + public toggleBlockSelectedState(next = true): void { + const { BlockManager, BlockSelection } = this.Editor; + + if (!this.lastSelectedBlock) { + this.lastSelectedBlock = this.firstSelectedBlock = BlockManager.currentBlock; + } + + if (this.firstSelectedBlock === this.lastSelectedBlock) { + this.firstSelectedBlock.selected = true; + + BlockSelection.clearCache(); + SelectionUtils.get().removeAllRanges(); + } + + const nextBlockIndex = BlockManager.blocks.indexOf(this.lastSelectedBlock) + (next ? 1 : -1); + const nextBlock = BlockManager.blocks[nextBlockIndex]; + + if (!nextBlock) { + return; + } + + if (this.lastSelectedBlock.selected !== nextBlock.selected) { + nextBlock.selected = true; + + BlockSelection.clearCache(); + } else { + this.lastSelectedBlock.selected = false; + + BlockSelection.clearCache(); + } + + this.lastSelectedBlock = nextBlock; + + /** close InlineToolbar when Blocks selected */ + this.Editor.InlineToolbar.close(); + + nextBlock.holder.scrollIntoView({ + block: 'nearest', + }); + } + + /** + * Clear saved state + * + * @param {Event} reason - event caused clear of selection + */ + public clear(reason?: Event): void { + const { BlockManager, BlockSelection, Caret } = this.Editor; + const fIndex = BlockManager.blocks.indexOf(this.firstSelectedBlock); + const lIndex = BlockManager.blocks.indexOf(this.lastSelectedBlock); + + if (BlockSelection.anyBlockSelected && fIndex > -1 && lIndex > -1) { + if (reason && reason instanceof KeyboardEvent) { + /** + * Set caret depending on pressed key if pressed key is an arrow. + */ + switch (reason.keyCode) { + case _.keyCodes.DOWN: + case _.keyCodes.RIGHT: + Caret.setToBlock(BlockManager.blocks[Math.max(fIndex, lIndex)], Caret.positions.END); + break; + + case _.keyCodes.UP: + case _.keyCodes.LEFT: + Caret.setToBlock(BlockManager.blocks[Math.min(fIndex, lIndex)], Caret.positions.START); + break; + default: + Caret.setToBlock(BlockManager.blocks[Math.max(fIndex, lIndex)], Caret.positions.END); + } + } else { + /** + * By default set caret at the end of the last selected block + */ + Caret.setToBlock(BlockManager.blocks[Math.max(fIndex, lIndex)], Caret.positions.END); + } + } + + this.firstSelectedBlock = this.lastSelectedBlock = null; + } + + /** + * Enables Cross Block Selection + * + * @param {MouseEvent} event - mouse down event + */ + private enableCrossBlockSelection(event: MouseEvent): void { + const { UI } = this.Editor; + + /** + * Each mouse down on must disable selectAll state + */ + if (!SelectionUtils.isCollapsed) { + this.Editor.BlockSelection.clearSelection(event); + } + + /** + * If mouse down is performed inside the editor, we should watch CBS + */ + if (UI.nodes.redactor.contains(event.target as Node)) { + this.watchSelection(event); + } else { + /** + * Otherwise, clear selection + */ + this.Editor.BlockSelection.clearSelection(event); + } + } + + /** + * Mouse up event handler. + * Removes the listeners + */ + private onMouseUp = (): void => { + this.listeners.off(document, 'mouseover', this.onMouseOver); + this.listeners.off(document, 'mouseup', this.onMouseUp); + } + + /** + * Mouse over event handler + * Gets target and related blocks and change selected state for blocks in between + * + * @param {MouseEvent} event - mouse over event + */ + private onMouseOver = (event: MouseEvent): void => { + const { BlockManager, BlockSelection } = this.Editor; + + const relatedBlock = BlockManager.getBlockByChildNode(event.relatedTarget as Node) || this.lastSelectedBlock; + const targetBlock = BlockManager.getBlockByChildNode(event.target as Node); + + if (!relatedBlock || !targetBlock) { + return; + } + + if (targetBlock === relatedBlock) { + return; + } + + if (relatedBlock === this.firstSelectedBlock) { + SelectionUtils.get().removeAllRanges(); + + relatedBlock.selected = true; + targetBlock.selected = true; + + BlockSelection.clearCache(); + + return; + } + + if (targetBlock === this.firstSelectedBlock) { + relatedBlock.selected = false; + targetBlock.selected = false; + + BlockSelection.clearCache(); + + return; + } + + this.Editor.InlineToolbar.close(); + + this.toggleBlocksSelectedState(relatedBlock, targetBlock); + this.lastSelectedBlock = targetBlock; + } + + /** + * Change blocks selection state between passed two blocks. + * + * @param {Block} firstBlock - first block in range + * @param {Block} lastBlock - last block in range + */ + private toggleBlocksSelectedState(firstBlock: Block, lastBlock: Block): void { + const { BlockManager, BlockSelection } = this.Editor; + const fIndex = BlockManager.blocks.indexOf(firstBlock); + const lIndex = BlockManager.blocks.indexOf(lastBlock); + + /** + * If first and last block have the different selection state + * it means we should't toggle selection of the first selected block. + * In the other case we shouldn't toggle the last selected block. + */ + const shouldntSelectFirstBlock = firstBlock.selected !== lastBlock.selected; + + for (let i = Math.min(fIndex, lIndex); i <= Math.max(fIndex, lIndex); i++) { + const block = BlockManager.blocks[i]; + + if ( + block !== this.firstSelectedBlock && + block !== (shouldntSelectFirstBlock ? firstBlock : lastBlock) + ) { + BlockManager.blocks[i].selected = !BlockManager.blocks[i].selected; + + BlockSelection.clearCache(); + } + } + } +} diff --git a/src/components/modules/dragNDrop.ts b/src/components/modules/dragNDrop.ts index b6875d0e7..f1b3d3936 100644 --- a/src/components/modules/dragNDrop.ts +++ b/src/components/modules/dragNDrop.ts @@ -1,51 +1,72 @@ import SelectionUtils from '../selection'; import Module from '../__module'; +/** + * + */ export default class DragNDrop extends Module { - /** * If drag has been started at editor, we save it * - * @type Boolean + * @type {boolean} * @private */ private isStartedAtEditor = false; /** - * Bind events + * Toggle read-only state * - * @private + * if state is true: + * - disable all drag-n-drop event handlers + * + * if state is false: + * - restore drag-n-drop event handlers + * + * @param {boolean} readOnlyEnabled - "read only" state */ - public prepare(): void { - this.bindEvents(); + public toggleReadOnly(readOnlyEnabled: boolean): void { + if (readOnlyEnabled) { + this.disableModuleBindings(); + } else { + this.enableModuleBindings(); + } } /** * Add drag events listeners to editor zone - * @private */ - private bindEvents(): void { - this.Editor.Listeners.on(this.Editor.UI.nodes.holder, 'drop', this.processDrop, true); - - this.Editor.Listeners.on(this.Editor.UI.nodes.holder, 'dragstart', (dragEvent: DragEvent) => { + private enableModuleBindings(): void { + const { UI } = this.Editor; - if (SelectionUtils.isAtEditor && !SelectionUtils.isCollapsed) { - this.isStartedAtEditor = true; - } + this.readOnlyMutableListeners.on(UI.nodes.holder, 'drop', async (dropEvent: DragEvent) => { + await this.processDrop(dropEvent); + }, true); - this.Editor.InlineToolbar.close(); + this.readOnlyMutableListeners.on(UI.nodes.holder, 'dragstart', () => { + this.processDragStart(); }); - /* Prevent default browser behavior to allow drop on non-contenteditable elements */ - this.Editor.Listeners.on(this.Editor.UI.nodes.holder, 'dragover', (e) => e.preventDefault(), true); + /** + * Prevent default browser behavior to allow drop on non-contenteditable elements + */ + this.readOnlyMutableListeners.on(UI.nodes.holder, 'dragover', (dragEvent: DragEvent) => { + this.processDragOver(dragEvent); + }, true); + } + + /** + * Unbind drag-n-drop event handlers + */ + private disableModuleBindings(): void { + this.readOnlyMutableListeners.clearAll(); } /** * Handle drop event * - * @param {DragEvent} dropEvent + * @param {DragEvent} dropEvent - drop event */ - private processDrop = async (dropEvent: DragEvent): Promise => { + private async processDrop(dropEvent: DragEvent): Promise { const { BlockManager, Caret, @@ -54,7 +75,9 @@ export default class DragNDrop extends Module { dropEvent.preventDefault(); - BlockManager.blocks.forEach((block) => block.dropTarget = false); + BlockManager.blocks.forEach((block) => { + block.dropTarget = false; + }); if (SelectionUtils.isAtEditor && !SelectionUtils.isCollapsed && this.isStartedAtEditor) { document.execCommand('delete'); @@ -64,18 +87,36 @@ export default class DragNDrop extends Module { /** * Try to set current block by drop target. - * If drop target (error will be thrown) is not part of the Block, set last Block as current. + * If drop target is not part of the Block, set last Block as current. */ - try { - const targetBlock = BlockManager.setCurrentBlockByChildNode(dropEvent.target as Node); + const targetBlock = BlockManager.setCurrentBlockByChildNode(dropEvent.target as Node); + if (targetBlock) { this.Editor.Caret.setToBlock(targetBlock, Caret.positions.END); - } catch (e) { - const targetBlock = BlockManager.setCurrentBlockByChildNode(BlockManager.lastBlock.holder); + } else { + const lastBlock = BlockManager.setCurrentBlockByChildNode(BlockManager.lastBlock.holder); - this.Editor.Caret.setToBlock(targetBlock, Caret.positions.END); + this.Editor.Caret.setToBlock(lastBlock, Caret.positions.END); + } + + await Paste.processDataTransfer(dropEvent.dataTransfer, true); + } + + /** + * Handle drag start event + */ + private processDragStart(): void { + if (SelectionUtils.isAtEditor && !SelectionUtils.isCollapsed) { + this.isStartedAtEditor = true; } - Paste.processDataTransfer(dropEvent.dataTransfer, true); + this.Editor.InlineToolbar.close(); + } + + /** + * @param {DragEvent} dragEvent - drag event + */ + private processDragOver(dragEvent: DragEvent): void { + dragEvent.preventDefault(); } } diff --git a/src/components/modules/events.ts b/src/components/modules/events.ts deleted file mode 100644 index df52cf2eb..000000000 --- a/src/components/modules/events.ts +++ /dev/null @@ -1,79 +0,0 @@ -import Module from '../__module'; - -/** - * @module eventDispatcher - * - * Has two important methods: - * - {Function} on - appends subscriber to the event. If event doesn't exist - creates new one - * - {Function} emit - fires all subscribers with data - * - {Function off - unsubsribes callback - * - * @version 1.0.0 - * - * @typedef {Events} Events - * @property {Object} subscribers - all subscribers grouped by event name - */ -export default class Events extends Module { - - /** - * Object with events` names as key and array of callback functions as value - * @type {{}} - */ - private subscribers: {[name: string]: Array<(data?: any) => any>} = {}; - - /** - * Subscribe any event on callback - * - * @param {String} eventName - event name - * @param {Function} callback - subscriber - */ - public on(eventName: string, callback: (data: any) => any) { - if (!(eventName in this.subscribers)) { - this.subscribers[eventName] = []; - } - - // group by events - this.subscribers[eventName].push(callback); - } - - /** - * Emit callbacks with passed data - * - * @param {String} eventName - event name - * @param {Object} data - subscribers get this data when they were fired - */ - public emit(eventName: string, data?: any): void { - if (!this.subscribers[eventName]) { - return; - } - - this.subscribers[eventName].reduce((previousData, currentHandler) => { - const newData = currentHandler(previousData); - - return newData ? newData : previousData; - }, data); - } - - /** - * Unsubsribe callback from event - * - * @param eventName - * @param callback - */ - public off(eventName: string, callback: (data: any) => void): void { - for (let i = 0; i < this.subscribers[eventName].length; i++) { - if (this.subscribers[eventName][i] === callback) { - delete this.subscribers[eventName][i]; - break; - } - } - } - - /** - * Destroyer - * clears subsribers list - */ - public destroy(): void { - this.subscribers = null; - } -} diff --git a/src/components/modules/listeners.ts b/src/components/modules/listeners.ts deleted file mode 100644 index 7d7467d50..000000000 --- a/src/components/modules/listeners.ts +++ /dev/null @@ -1,191 +0,0 @@ -import Module from '../__module'; - -/** - * Event listener information - */ -export interface ListenerData { - /** - * Element where to listen to dispatched events - */ - element: EventTarget; - - /** - * Event to listen - */ - eventType: string; - - /** - * Event handler - * - * @param {Event} event - */ - handler: (event: Event) => void; - - /** - * Should event bubbling be used or not - */ - useCapture: boolean; -} - -/** - * Editor.js Listeners module - * - * @module Listeners - * - * Module-decorator for event listeners assignment - * - * @author Codex Team - * @version 2.0.0 - */ - -/** - * @typedef {Listeners} Listeners - * @property {Array} allListeners - */ -export default class Listeners extends Module { - - /** - * Stores all listeners data to find/remove/process it - * @type {ListenerData[]} - */ - private allListeners: ListenerData[] = []; - - /** - * Assigns event listener on element - * - * @param {EventTarget} element - DOM element that needs to be listened - * @param {String} eventType - event type - * @param {Function} handler - method that will be fired on event - * @param {Boolean} useCapture - use event bubbling - */ - public on( - element: EventTarget, - eventType: string, - handler: (event: Event) => void, - useCapture: boolean = false, - ): void { - const assignedEventData = { - element, - eventType, - handler, - useCapture, - }; - - const alreadyExist = this.findOne(element, eventType, handler); - - if (alreadyExist) { return; } - - this.allListeners.push(assignedEventData); - element.addEventListener(eventType, handler, useCapture); - } - - /** - * Removes event listener from element - * - * @param {EventTarget} element - DOM element that we removing listener - * @param {String} eventType - event type - * @param {Function} handler - remove handler, if element listens several handlers on the same event type - * @param {Boolean} useCapture - use event bubbling - */ - public off( - element: EventTarget, - eventType: string, - handler: (event: Event) => void, - useCapture: boolean = false, - ): void { - const existingListeners = this.findAll(element, eventType, handler); - - existingListeners.forEach((listener, i) => { - const index = this.allListeners.indexOf(existingListeners[i]); - - if (index > 0) { - this.allListeners.splice(index, 1); - } - }); - - element.removeEventListener(eventType, handler, useCapture); - } - - /** - * @param {EventTarget} element - * @param {String} eventType - * @param {Function} handler - * @return {EventTarget|null} - */ - public findOne(element: EventTarget, eventType: string, handler: (event: Event) => void): ListenerData { - const foundListeners = this.findAll(element, eventType, handler); - - return foundListeners.length > 0 ? foundListeners[0] : null; - } - - /** - * @param {EventTarget} element - * @param {String} eventType - * @param {Function} handler - * @return {Array} - */ - public findAll(element: EventTarget, eventType: string, handler: (event: Event) => void): ListenerData[] { - let found; - const foundByEventTargets = element ? this.findByEventTarget(element) : []; - - if (element && eventType && handler) { - found = foundByEventTargets.filter( (event) => event.eventType === eventType && event.handler === handler ); - } else if (element && eventType) { - found = foundByEventTargets.filter( (event) => event.eventType === eventType); - } else { - found = foundByEventTargets; - } - - return found; - } - - /** - * Removes all listeners - */ - public removeAll(): void { - this.allListeners.map( (current) => { - current.element.removeEventListener(current.eventType, current.handler); - }); - - this.allListeners = []; - } - - /** - * Search method: looks for listener by passed element - * @param {EventTarget} element - searching element - * @returns {Array} listeners that found on element - */ - private findByEventTarget(element: EventTarget): ListenerData[] { - return this.allListeners.filter((listener) => { - if (listener.element === element) { - return listener; - } - }); - } - - /** - * Search method: looks for listener by passed event type - * @param {String} eventType - * @return {Array} listeners that found on element - */ - private findByType(eventType: string): ListenerData[] { - return this.allListeners.filter((listener) => { - if (listener.eventType === eventType) { - return listener; - } - }); - } - - /** - * Search method: looks for listener by passed handler - * @param {Function} handler - * @return {Array} listeners that found on element - */ - private findByHandler(handler: (event: Event) => void): ListenerData[] { - return this.allListeners.filter((listener) => { - if (listener.handler === handler) { - return listener; - } - }); - } -} diff --git a/src/components/modules/modificationsObserver.ts b/src/components/modules/modificationsObserver.ts index c291b781c..30f5797c0 100644 --- a/src/components/modules/modificationsObserver.ts +++ b/src/components/modules/modificationsObserver.ts @@ -6,13 +6,16 @@ */ import Module from '../__module'; -import _ from '../utils'; +import * as _ from '../utils'; import Block from '../block'; +/** + * + */ export default class ModificationsObserver extends Module { - /** * Debounce Timer + * * @type {number} */ public static readonly DebounceTimer = 450; @@ -25,44 +28,58 @@ export default class ModificationsObserver extends Module { /** * Allows to temporary disable mutations handling */ - private disabled: boolean; + private disabled = false; /** * Used to prevent several mutation callback execution + * * @type {Function} */ - private mutationDebouncer = _.debounce( () => { - this.checkEmptiness(); - this.config.onChange(); + private mutationDebouncer = _.debounce(() => { + this.updateNativeInputs(); + + if (_.isFunction(this.config.onChange)) { + this.config.onChange(this.Editor.API.methods); + } }, ModificationsObserver.DebounceTimer); + /** + * Array of native inputs in Blocks. + * Changes in native inputs are not handled by modification observer, so we need to set change event listeners on them + */ + private nativeInputs: HTMLElement[] = []; + /** * Clear timeout and set null to mutationDebouncer property */ - public destroy() { + public destroy(): void { this.mutationDebouncer = null; - this.observer.disconnect(); + if (this.observer) { + this.observer.disconnect(); + } this.observer = null; + this.nativeInputs.forEach((input) => this.listeners.off(input, 'input', this.mutationDebouncer)); + this.mutationDebouncer = null; } /** - * Preparation method - * @return {Promise} + * Set read-only state + * + * @param {boolean} readOnlyEnabled - read only flag value */ - public async prepare(): Promise { - /** - * wait till Browser render Editor's Blocks - */ - window.setTimeout( () => { - this.setObserver(); - }, 1000); + public toggleReadOnly(readOnlyEnabled: boolean): void { + if (readOnlyEnabled) { + this.disableModule(); + } else { + this.enableModule(); + } } /** * Allows to disable observer, * for example when Editor wants to stealthy mutate DOM */ - public disable() { + public disable(): void { this.disabled = true; } @@ -70,7 +87,7 @@ export default class ModificationsObserver extends Module { * Enables mutation handling * Should be called after .disable() */ - public enable() { + public enable(): void { this.disabled = false; } @@ -81,7 +98,7 @@ export default class ModificationsObserver extends Module { * so that User can handle outside from API */ private setObserver(): void { - const {UI} = this.Editor; + const { UI } = this.Editor; const observerOptions = { childList: true, attributes: true, @@ -98,10 +115,11 @@ export default class ModificationsObserver extends Module { /** * MutationObserver events handler - * @param mutationList - * @param observer + * + * @param {MutationRecord[]} mutationList - list of mutations + * @param {MutationObserver} observer - observer instance */ - private mutationHandler(mutationList, observer) { + private mutationHandler(mutationList: MutationRecord[], observer: MutationObserver): void { /** * Skip mutations in stealth mode */ @@ -119,20 +137,15 @@ export default class ModificationsObserver extends Module { mutationList.forEach((mutation) => { switch (mutation.type) { case 'childList': - case 'subtree': case 'characterData': - case 'characterDataOldValue': contentMutated = true; break; case 'attributes': - const mutatedTarget = mutation.target as Element; - /** * Changes on Element.ce-block usually is functional */ - if (!mutatedTarget.classList.contains(Block.CSS.wrapper)) { + if (!(mutation.target as Element).classList.contains(Block.CSS.wrapper)) { contentMutated = true; - return; } break; } @@ -145,11 +158,38 @@ export default class ModificationsObserver extends Module { } /** - * Check if Editor is empty and set CSS class to wrapper + * Gets native inputs and set oninput event handler + */ + private updateNativeInputs(): void { + if (this.nativeInputs) { + this.nativeInputs.forEach((input) => { + this.listeners.off(input, 'input'); + }); + } + + this.nativeInputs = Array.from(this.Editor.UI.nodes.redactor.querySelectorAll('textarea, input, select')); + + this.nativeInputs.forEach((input) => this.listeners.on(input, 'input', this.mutationDebouncer)); + } + + /** + * Sets observer and enables it */ - private checkEmptiness(): void { - const {BlockManager, UI} = this.Editor; + private enableModule(): void { + /** + * wait till Browser render Editor's Blocks + */ + window.setTimeout(() => { + this.setObserver(); + this.updateNativeInputs(); + this.enable(); + }, 1000); + } - UI.nodes.wrapper.classList.toggle(UI.CSS.editorEmpty, BlockManager.isEditorEmpty); + /** + * Disables observer + */ + private disableModule(): void { + this.disable(); } } diff --git a/src/components/modules/notifier.ts b/src/components/modules/notifier.ts index ab843a74e..7562a0f12 100644 --- a/src/components/modules/notifier.ts +++ b/src/components/modules/notifier.ts @@ -5,19 +5,18 @@ import Module from '../__module'; * * @see https://github.com/codex-team/js-notifier */ -import notifier, {ConfirmNotifierOptions, NotifierOptions, PromptNotifierOptions} from 'codex-notifier'; +import notifier, { ConfirmNotifierOptions, NotifierOptions, PromptNotifierOptions } from 'codex-notifier'; /** * Notifier module */ export default class Notifier extends Module { - /** * Show web notification * - * @param {NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions} options + * @param {NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions} options - notification options */ - public show(options: NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions) { + public show(options: NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions): void { notifier.show(options); } } diff --git a/src/components/modules/paste.ts b/src/components/modules/paste.ts index ff684bc9e..884cbdba0 100644 --- a/src/components/modules/paste.ts +++ b/src/components/modules/paste.ts @@ -1,14 +1,15 @@ import Module from '../__module'; import $ from '../dom'; -import _ from '../utils'; +import * as _ from '../utils'; import { BlockTool, BlockToolConstructable, PasteConfig, PasteEvent, - PasteEventDetail, + PasteEventDetail } from '../../../types'; import Block from '../block'; +import { SavedData } from '../../../types/data-formats'; /** * Tag substitute object. @@ -16,6 +17,7 @@ import Block from '../block'; interface TagSubstitute { /** * Name of related Tool + * * @type {string} */ tool: string; @@ -27,18 +29,21 @@ interface TagSubstitute { interface PatternSubstitute { /** * Pattern`s key + * * @type {string} */ key: string; /** * Pattern regexp + * * @type {RegExp} */ pattern: RegExp; /** * Name of related Tool + * * @type {string} */ tool: string; @@ -50,12 +55,14 @@ interface PatternSubstitute { interface FilesSubstitution { /** * Array of file extensions Tool can handle + * * @type {string[]} */ extensions: string[]; /** * Array of MIME types Tool can handle + * * @type {string[]} */ mimeTypes: string[]; @@ -63,16 +70,20 @@ interface FilesSubstitution { /** * Processed paste data object. + * + * @interface PasteData */ interface PasteData { /** * Name of related Tool + * * @type {string} */ tool: string; /** * Pasted data. Processed and wrapped to HTML element + * * @type {HTMLElement} */ content: HTMLElement; @@ -84,6 +95,7 @@ interface PasteData { /** * True if content should be inserted as new Block + * * @type {boolean} */ isBlock: boolean; @@ -98,10 +110,12 @@ interface PasteData { * @version 2.0.0 */ export default class Paste extends Module { - /** If string`s length is greater than this number we don't check paste patterns */ public static readonly PATTERN_PROCESSING_MAX_LENGTH = 450; + /** Custom EditorJS mime-type to handle in-editor copy/paste actions */ + public readonly MIME_TYPE = 'application/x-editor-js'; + /** * Tags` substitutions parameters */ @@ -117,24 +131,39 @@ export default class Paste extends Module { /** Files` substitutions parameters */ private toolsFiles: { - [tool: string]: FilesSubstitution, + [tool: string]: FilesSubstitution; } = {}; + /** + * List of tools which do not need a paste handling + */ + private exceptionList: string[] = []; + /** * Set onPaste callback and collect tools` paste configurations - * - * @public */ public async prepare(): Promise { - this.setCallback(); this.processTools(); } + /** + * Set read-only state + * + * @param {boolean} readOnlyEnabled - read only flag value + */ + public toggleReadOnly(readOnlyEnabled: boolean): void { + if (!readOnlyEnabled) { + this.setCallback(); + } else { + this.unsetCallback(); + } + } + /** * Handle pasted or dropped data transfer object * * @param {DataTransfer} dataTransfer - pasted or dropped data transfer object - * @param {boolean} isDragNDrop + * @param {boolean} isDragNDrop - true if data transfer comes from drag'n'drop events */ public async processDataTransfer(dataTransfer: DataTransfer, isDragNDrop = false): Promise { const { Sanitizer } = this.Editor; @@ -144,21 +173,35 @@ export default class Paste extends Module { /** * In Microsoft Edge types is DOMStringList. So 'contains' is used to check if 'Files' type included */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any const includesFiles = types.includes ? types.includes('Files') : (types as any).contains('Files'); if (includesFiles) { await this.processFiles(dataTransfer.files); + return; } + const editorJSData = dataTransfer.getData(this.MIME_TYPE); const plainData = dataTransfer.getData('text/plain'); - let htmlData = dataTransfer.getData('text/html'); + let htmlData = dataTransfer.getData('text/html'); + + /** + * If EditorJS json is passed, insert it + */ + if (editorJSData) { + try { + this.insertEditorJSData(JSON.parse(editorJSData)); + + return; + } catch (e) {} // Do nothing and continue execution as usual if error appears + } /** * If text was drag'n'dropped, wrap content with P tag to insert it as the new Block */ if (isDragNDrop && plainData.trim() && htmlData.trim()) { - htmlData = '

' + ( htmlData.trim() ? htmlData : plainData ) + '

'; + htmlData = '

' + (htmlData.trim() ? htmlData : plainData) + '

'; } /** Add all tags that can be substituted to sanitizer configuration */ @@ -168,7 +211,7 @@ export default class Paste extends Module { return result; }, {}); - const customConfig = Object.assign({}, toolsTags, Sanitizer.getAllInlineToolsConfig(), {br: {}}); + const customConfig = Object.assign({}, toolsTags, Sanitizer.getAllInlineToolsConfig(), { br: {} }); const cleanData = Sanitizer.clean(htmlData, customConfig); @@ -186,8 +229,8 @@ export default class Paste extends Module { * @param {string} data - text to process. Can be HTML or plain. * @param {boolean} isHTML - if passed string is HTML, this parameter should be true */ - public async processText(data: string, isHTML: boolean = false) { - const {Caret, BlockManager, Tools} = this.Editor; + public async processText(data: string, isHTML = false): Promise { + const { Caret, BlockManager, Tools } = this.Editor; const dataToInsert = isHTML ? this.processHTML(data) : this.processPlain(data); if (!dataToInsert.length) { @@ -200,15 +243,16 @@ export default class Paste extends Module { } else { this.processSingleBlock(dataToInsert.pop()); } + return; } - const isCurrentBlockInitial = BlockManager.currentBlock && Tools.isInitial(BlockManager.currentBlock.tool); - const needToReplaceCurrentBlock = isCurrentBlockInitial && BlockManager.currentBlock.isEmpty; + const isCurrentBlockDefault = BlockManager.currentBlock && Tools.isDefault(BlockManager.currentBlock.tool); + const needToReplaceCurrentBlock = isCurrentBlockDefault && BlockManager.currentBlock.isEmpty; - await Promise.all(dataToInsert.map( - async (content, i) => await this.insertBlock(content, i === 0 && needToReplaceCurrentBlock), - )); + dataToInsert.map( + async (content, i) => this.insertBlock(content, i === 0 && needToReplaceCurrentBlock) + ); if (BlockManager.currentBlock) { Caret.setToBlock(BlockManager.currentBlock, Caret.positions.END); @@ -219,9 +263,14 @@ export default class Paste extends Module { * Set onPaste callback handler */ private setCallback(): void { - const {Listeners} = this.Editor; + this.listeners.on(this.Editor.UI.nodes.holder, 'paste', this.handlePasteEvent); + } - Listeners.on(document, 'paste', this.handlePasteEvent); + /** + * Unset onPaste callback handler + */ + private unsetCallback(): void { + this.listeners.off(this.Editor.UI.nodes.holder, 'paste', this.handlePasteEvent); } /** @@ -235,19 +284,23 @@ export default class Paste extends Module { /** * Process paste config for each tool - * - * @param {string} name - * @param {Tool} tool */ private processTool = ([name, tool]: [string, BlockToolConstructable]): void => { try { const toolInstance = new this.Editor.Tools.blockTools[name]({ - api: this.Editor.API.methods, + api: this.Editor.API.getMethodsForTool(name), config: {}, data: {}, + readOnly: false, }) as BlockTool; - if (!toolInstance.onPaste || typeof toolInstance.onPaste !== 'function') { + if (tool.pasteConfig === false) { + this.exceptionList.push(name); + + return; + } + + if (!_.isFunction(toolInstance.onPaste)) { return; } @@ -260,7 +313,7 @@ export default class Paste extends Module { _.log( `Paste handling for «${name}» Tool hasn't been set up because of the error`, 'warn', - e, + e ); } } @@ -275,12 +328,13 @@ export default class Paste extends Module { const tags = toolPasteConfig.tags || []; tags.forEach((tag) => { - if (this.toolsTags.hasOwnProperty(tag)) { + if (Object.prototype.hasOwnProperty.call(this.toolsTags, tag)) { _.log( `Paste handler for «${name}» Tool on «${tag}» tag is skipped ` + `because it is already used by «${this.toolsTags[tag].tool}» Tool.`, - 'warn', + 'warn' ); + return; } @@ -299,9 +353,8 @@ export default class Paste extends Module { * @param {PasteConfig} toolPasteConfig - Tool onPaste configuration */ private getFilesConfig(name: string, toolPasteConfig: PasteConfig): void { - - const {files = {}} = toolPasteConfig; - let {extensions, mimeTypes} = files; + const { files = {} } = toolPasteConfig; + let { extensions, mimeTypes } = files; if (!extensions && !mimeTypes) { return; @@ -321,6 +374,7 @@ export default class Paste extends Module { mimeTypes = mimeTypes.filter((type) => { if (!_.isValidMimeType(type)) { _.log(`MIME type value «${type}» for the «${name}» Tool is not a valid MIME type`, 'warn'); + return false; } @@ -350,7 +404,7 @@ export default class Paste extends Module { if (!(pattern instanceof RegExp)) { _.log( `Pattern ${pattern} for «${name}» Tool is skipped because it should be a Regexp instance.`, - 'warn', + 'warn' ); } @@ -366,6 +420,7 @@ export default class Paste extends Module { * Check if browser behavior suits better * * @param {EventTarget} element - element where content has been pasted + * * @returns {boolean} */ private isNativeBehaviour(element: EventTarget): boolean { @@ -375,18 +430,25 @@ export default class Paste extends Module { /** * Check if Editor should process pasted data and pass data transfer object to handler * - * @param {ClipboardEvent} event + * @param {ClipboardEvent} event - clipboard event */ private handlePasteEvent = async (event: ClipboardEvent): Promise => { - const {BlockManager, Tools, Toolbar} = this.Editor; + const { BlockManager, Toolbar } = this.Editor; /** If target is native input or is not Block, use browser behaviour */ if ( - !BlockManager.currentBlock || this.isNativeBehaviour(event.target) && !event.clipboardData.types.includes('Files') + !BlockManager.currentBlock || (this.isNativeBehaviour(event.target) && !event.clipboardData.types.includes('Files')) ) { return; } + /** + * If Tools is in list of errors, skip processing of paste event + */ + if (BlockManager.currentBlock && this.exceptionList.includes(BlockManager.currentBlock.name)) { + return; + } + event.preventDefault(); this.processDataTransfer(event.clipboardData); @@ -399,39 +461,39 @@ export default class Paste extends Module { * * @param {FileList} items - pasted or dropped items */ - private async processFiles(items: FileList) { - const {BlockManager, Tools} = this.Editor; + private async processFiles(items: FileList): Promise { + const { BlockManager, Tools } = this.Editor; - let dataToInsert: Array<{type: string, event: PasteEvent}>; + let dataToInsert: Array<{type: string; event: PasteEvent}>; dataToInsert = await Promise.all( Array .from(items) - .map((item) => this.processFile(item)), + .map((item) => this.processFile(item)) ); dataToInsert = dataToInsert.filter((data) => !!data); - const isCurrentBlockInitial = Tools.isInitial(BlockManager.currentBlock.tool); - const needToReplaceCurrentBlock = isCurrentBlockInitial && BlockManager.currentBlock.isEmpty; + const isCurrentBlockDefault = Tools.isDefault(BlockManager.currentBlock.tool); + const needToReplaceCurrentBlock = isCurrentBlockDefault && BlockManager.currentBlock.isEmpty; dataToInsert.forEach( (data, i) => { BlockManager.paste(data.type, data.event, i === 0 && needToReplaceCurrentBlock); - }, + } ); } /** * Get information about file and find Tool to handle it * - * @param {File} file + * @param {File} file - file to process */ - private async processFile(file: File) { + private async processFile(file: File): Promise<{event: PasteEvent; type: string}> { const extension = _.getFileExtension(file); const foundConfig = Object .entries(this.toolsFiles) - .find(([toolName, {mimeTypes, extensions}]) => { + .find(([toolName, { mimeTypes, extensions } ]) => { const [fileType, fileSubtype] = file.type.split('/'); const foundExt = extensions.find((ext) => ext.toLowerCase() === extension.toLowerCase()); @@ -448,7 +510,7 @@ export default class Paste extends Module { return; } - const [tool] = foundConfig; + const [ tool ] = foundConfig; const pasteEvent = this.composePasteEvent('file', { file, }); @@ -462,12 +524,13 @@ export default class Paste extends Module { /** * Split HTML string to blocks and return it as array of Block data * - * @param {string} innerHTML + * @param {string} innerHTML - html string to process + * * @returns {PasteData[]} */ private processHTML(innerHTML: string): PasteData[] { - const {Tools, Sanitizer} = this.Editor; - const initialTool = this.config.initialBlock; + const { Tools, Sanitizer } = this.Editor; + const initialTool = this.config.defaultBlock; const wrapper = $.make('DIV'); wrapper.innerHTML = innerHTML; @@ -496,7 +559,7 @@ export default class Paste extends Module { break; } - const {tags} = Tools.blockTools[tool].pasteConfig; + const { tags } = Tools.blockTools[tool].pasteConfig as PasteConfig; const toolTags = tags.reduce((result, tag) => { result[tag.toLowerCase()] = {}; @@ -511,7 +574,12 @@ export default class Paste extends Module { data: content, }); - return {content, isBlock, tool, event}; + return { + content, + isBlock, + tool, + event, + }; }) .filter((data) => !$.isNodeEmpty(data.content) || $.isSingleTag(data.content)); } @@ -519,18 +587,18 @@ export default class Paste extends Module { /** * Split plain text by new line symbols and return it as array of Block data * - * @param {string} plain + * @param {string} plain - string to process + * * @returns {PasteData[]} */ private processPlain(plain: string): PasteData[] { - const {initialBlock} = this.config as {initialBlock: string}, - {Tools} = this.Editor; + const { defaultBlock } = this.config as {defaultBlock: string}; if (!plain) { return []; } - const tool = initialBlock; + const tool = defaultBlock; return plain .split(/\r?\n/) @@ -538,24 +606,29 @@ export default class Paste extends Module { .map((text) => { const content = $.make('div'); - content.innerHTML = text; + content.textContent = text; const event = this.composePasteEvent('tag', { data: content, }); - return {content, tool, isBlock: false, event}; + return { + content, + tool, + isBlock: false, + event, + }; }); } /** * Process paste of single Block tool content * - * @param {PasteData} dataToInsert + * @param {PasteData} dataToInsert - data of Block to inseret */ private async processSingleBlock(dataToInsert: PasteData): Promise { - const {Caret, BlockManager, Tools} = this.Editor; - const {currentBlock} = BlockManager; + const { Caret, BlockManager, Tools } = this.Editor; + const { currentBlock } = BlockManager; /** * If pasted tool isn`t equal current Block or if pasted content contains block elements, insert it as new Block @@ -565,7 +638,8 @@ export default class Paste extends Module { dataToInsert.tool !== currentBlock.name || !$.containsOnlyInlineElements(dataToInsert.content.innerHTML) ) { - this.insertBlock(dataToInsert, currentBlock && Tools.isInitial(currentBlock.tool) && currentBlock.isEmpty); + this.insertBlock(dataToInsert, currentBlock && Tools.isDefault(currentBlock.tool) && currentBlock.isEmpty); + return; } @@ -578,27 +652,26 @@ export default class Paste extends Module { * 2. Insert new block if it is not the same type as current one * 3. Just insert text if there is no substitutions * - * @param {PasteData} dataToInsert + * @param {PasteData} dataToInsert - data of Block to insert */ private async processInlinePaste(dataToInsert: PasteData): Promise { - const {BlockManager, Caret, Sanitizer, Tools} = this.Editor; - const {content, tool} = dataToInsert; + const { BlockManager, Caret, Sanitizer, Tools } = this.Editor; + const { content } = dataToInsert; - const currentBlockIsInitial = BlockManager.currentBlock && Tools.isInitial(BlockManager.currentBlock.tool); + const currentBlockIsDefault = BlockManager.currentBlock && Tools.isDefault(BlockManager.currentBlock.tool); - if (currentBlockIsInitial && content.textContent.length < Paste.PATTERN_PROCESSING_MAX_LENGTH) { + if (currentBlockIsDefault && content.textContent.length < Paste.PATTERN_PROCESSING_MAX_LENGTH) { const blockData = await this.processPattern(content.textContent); if (blockData) { - let insertedBlock; - - const needToReplaceCurrentBlock = BlockManager.currentBlock - && Tools.isInitial(BlockManager.currentBlock.tool) - && BlockManager.currentBlock.isEmpty; + const needToReplaceCurrentBlock = BlockManager.currentBlock && + Tools.isDefault(BlockManager.currentBlock.tool) && + BlockManager.currentBlock.isEmpty; - insertedBlock = BlockManager.paste(blockData.tool, blockData.event, needToReplaceCurrentBlock); + const insertedBlock = BlockManager.paste(blockData.tool, blockData.event, needToReplaceCurrentBlock); Caret.setToBlock(insertedBlock, Caret.positions.END); + return; } } @@ -607,7 +680,11 @@ export default class Paste extends Module { if (BlockManager.currentBlock && BlockManager.currentBlock.currentInput) { const currentToolSanitizeConfig = Sanitizer.getInlineToolsConfig(BlockManager.currentBlock.name); - document.execCommand('insertHTML', false, Sanitizer.clean(content.innerHTML, currentToolSanitizeConfig)); + document.execCommand( + 'insertHTML', + false, + Sanitizer.clean(content.innerHTML, currentToolSanitizeConfig) + ); } else { this.insertBlock(dataToInsert); } @@ -616,11 +693,12 @@ export default class Paste extends Module { /** * Get patterns` matches * - * @param {string} text - * @returns Promise<{data: BlockToolData, tool: string}> + * @param {string} text - text to process + * + * @returns {Promise<{event: PasteEvent, tool: string}>} */ - private async processPattern(text: string): Promise<{event: PasteEvent, tool: string}> { - const pattern = this.toolsPatterns.find((substitute) => { + private async processPattern(text: string): Promise<{event: PasteEvent; tool: string}> { + const pattern = this.toolsPatterns.find((substitute) => { const execResult = substitute.pattern.exec(text); if (!execResult) { @@ -646,19 +724,22 @@ export default class Paste extends Module { } /** + * Insert pasted Block content to Editor * - * @param {PasteData} data - * @param {Boolean} canReplaceCurrentBlock - if true and is current Block is empty, will replace current Block - * @returns {Promise} + * @param {PasteData} data - data to insert + * @param {boolean} canReplaceCurrentBlock - if true and is current Block is empty, will replace current Block + * + * @returns {void} */ - private async insertBlock(data: PasteData, canReplaceCurrentBlock: boolean = false): Promise { - const {BlockManager, Caret} = this.Editor; - const {currentBlock} = BlockManager; + private insertBlock(data: PasteData, canReplaceCurrentBlock = false): void { + const { BlockManager, Caret } = this.Editor; + const { currentBlock } = BlockManager; let block: Block; if (canReplaceCurrentBlock && currentBlock && currentBlock.isEmpty) { block = BlockManager.paste(data.tool, data.event, true); Caret.setToBlock(block, Caret.positions.END); + return; } @@ -667,17 +748,92 @@ export default class Paste extends Module { Caret.setToBlock(block, Caret.positions.END); } + /** + * Insert data passed as application/x-editor-js JSON + * + * @param {Array} blocks — Blocks' data to insert + * + * @returns {void} + */ + private insertEditorJSData(blocks: Array>): void { + const { BlockManager, Caret, Sanitizer, Tools } = this.Editor; + const sanitizedBlocks = Sanitizer.sanitizeBlocks(blocks); + + sanitizedBlocks.forEach(({ tool, data }, i) => { + let needToReplaceCurrentBlock = false; + + if (i === 0) { + const isCurrentBlockDefault = BlockManager.currentBlock && Tools.isDefault(BlockManager.currentBlock.tool); + + needToReplaceCurrentBlock = isCurrentBlockDefault && BlockManager.currentBlock.isEmpty; + } + + const block = BlockManager.insert({ + tool, + data, + replace: needToReplaceCurrentBlock, + }); + + Caret.setToBlock(block, Caret.positions.END); + }); + } + + /** + * Fetch nodes from Element node + * + * @param {Node} node - current node + * @param {Node[]} nodes - processed nodes + * @param {Node} destNode - destination node + * + * @returns {Node[]} + */ + private processElementNode(node: Node, nodes: Node[], destNode: Node): Node[] | void { + const tags = Object.keys(this.toolsTags); + + const element = node as HTMLElement; + + const { tool = '' } = this.toolsTags[element.tagName] || {}; + const toolTags = this.tagsByTool[tool] || []; + + const isSubstitutable = tags.includes(element.tagName); + const isBlockElement = $.blockElements.includes(element.tagName.toLowerCase()); + const containsAnotherToolTags = Array + .from(element.children) + .some( + ({ tagName }) => tags.includes(tagName) && !toolTags.includes(tagName) + ); + + const containsBlockElements = Array.from(element.children).some( + ({ tagName }) => $.blockElements.includes(tagName.toLowerCase()) + ); + + /** Append inline elements to previous fragment */ + if (!isBlockElement && !isSubstitutable && !containsAnotherToolTags) { + destNode.appendChild(element); + + return [...nodes, destNode]; + } + + if ( + (isSubstitutable && !containsAnotherToolTags) || + (isBlockElement && !containsBlockElements && !containsAnotherToolTags) + ) { + return [...nodes, destNode, element]; + } + } + /** * Recursively divide HTML string to two types of nodes: * 1. Block element * 2. Document Fragments contained text and markup tags like a, b, i etc. * - * @param {Node} wrapper + * @param {Node} wrapper - wrapper of paster HTML content + * * @returns {Node[]} */ private getNodes(wrapper: Node): Node[] { - const children = Array.from(wrapper.childNodes), - tags = Object.keys(this.toolsTags); + const children = Array.from(wrapper.childNodes); + let elementNodeProcessingResult: Node[] | void; const reducer = (nodes: Node[], node: Node): Node[] => { if ($.isEmpty(node) && !$.isSingleTag(node as HTMLElement)) { @@ -699,38 +855,10 @@ export default class Paste extends Module { * 2. Check if it contains another block or substitutable elements */ case Node.ELEMENT_NODE: - const element = node as HTMLElement; - - if (element.tagName === 'BR') { - return [...nodes, destNode, new DocumentFragment()]; - } + elementNodeProcessingResult = this.processElementNode(node, nodes, destNode); - const {tool = ''} = this.toolsTags[element.tagName] || {}; - const toolTags = this.tagsByTool[tool] || []; - - const isSubstitutable = tags.includes(element.tagName); - const isBlockElement = $.blockElements.includes(element.tagName.toLowerCase()); - const containsAnotherToolTags = Array - .from(element.children) - .some( - ({tagName}) => tags.includes(tagName) && !toolTags.includes(tagName), - ); - - const containsBlockElements = Array.from(element.children).some( - ({tagName}) => $.blockElements.includes(tagName.toLowerCase()), - ); - - /** Append inline elements to previous fragment */ - if (!isBlockElement && !isSubstitutable && !containsAnotherToolTags) { - destNode.appendChild(element); - return [...nodes, destNode]; - } - - if ( - (isSubstitutable && !containsAnotherToolTags) || - (isBlockElement && !containsBlockElements && !containsAnotherToolTags ) - ) { - return [...nodes, destNode, element]; + if (elementNodeProcessingResult) { + return elementNodeProcessingResult; } break; @@ -739,6 +867,7 @@ export default class Paste extends Module { */ case Node.TEXT_NODE: destNode.appendChild(node); + return [...nodes, destNode]; default: @@ -754,8 +883,8 @@ export default class Paste extends Module { /** * Compose paste event with passed type and detail * - * @param {string} type - * @param {PasteEventDetail} detail + * @param {string} type - event type + * @param {PasteEventDetail} detail - event detail */ private composePasteEvent(type: string, detail: PasteEventDetail): PasteEvent { return new CustomEvent(type, { diff --git a/src/components/modules/readonly.ts b/src/components/modules/readonly.ts new file mode 100644 index 000000000..544d1d7de --- /dev/null +++ b/src/components/modules/readonly.ts @@ -0,0 +1,113 @@ +import Module from '../__module'; +import { CriticalError } from '../errors/critical'; + +/** + * @module ReadOnly + * + * Has one important method: + * - {Function} toggleReadonly - Set read-only mode or toggle current state + * + * @version 1.0.0 + * + * @typedef {ReadOnly} ReadOnly + * @property {boolean} readOnlyEnabled - read-only state + */ +export default class ReadOnly extends Module { + /** + * Array of tools name which don't support read-only mode + */ + private toolsDontSupportReadOnly: string[] = []; + + /** + * Value to track read-only state + * + * @type {boolean} + */ + private readOnlyEnabled = false; + + /** + * Returns state of read only mode + */ + public get isEnabled(): boolean { + return this.readOnlyEnabled; + } + + /** + * Set initial state + */ + public async prepare(): Promise { + const { Tools } = this.Editor; + const { blockTools } = Tools; + const toolsDontSupportReadOnly: string[] = []; + + Object.entries(blockTools).forEach(([name, tool]) => { + if (!Tools.isReadOnlySupported(tool)) { + toolsDontSupportReadOnly.push(name); + } + }); + + this.toolsDontSupportReadOnly = toolsDontSupportReadOnly; + + if (this.config.readOnly && toolsDontSupportReadOnly.length > 0) { + this.throwCriticalError(); + } + + this.toggle(this.config.readOnly); + } + + /** + * Set read-only mode or toggle current state + * Call all Modules `toggleReadOnly` method and re-render Editor + * + * @param {boolean} state - (optional) read-only state or toggle + */ + public async toggle(state = !this.readOnlyEnabled): Promise { + if (state && this.toolsDontSupportReadOnly.length > 0) { + this.throwCriticalError(); + } + + const oldState = this.readOnlyEnabled; + + this.readOnlyEnabled = state; + + for (const name in this.Editor) { + /** + * Verify module has method `toggleReadOnly` method + */ + if (!this.Editor[name].toggleReadOnly) { + continue; + } + + /** + * set or toggle read-only state + */ + this.Editor[name].toggleReadOnly(state); + } + + /** + * If new state equals old one, do not re-render blocks + */ + if (oldState === state) { + return this.readOnlyEnabled; + } + + /** + * Save current Editor Blocks and render again + */ + const savedBlocks = await this.Editor.Saver.save(); + + await this.Editor.BlockManager.clear(); + await this.Editor.Renderer.render(savedBlocks.blocks); + + return this.readOnlyEnabled; + } + + /** + * Throws an error about tools which don't support read-only mode + */ + private throwCriticalError(): never { + throw new CriticalError( + `To enable read-only mode all connected tools should support it. Tools ${this.toolsDontSupportReadOnly.join(', ')} don't support read-only mode.` + ); + } +} diff --git a/src/components/modules/rectangleSelection.ts b/src/components/modules/rectangleSelection.ts index 095ec9b4d..8b2ea1518 100644 --- a/src/components/modules/rectangleSelection.ts +++ b/src/components/modules/rectangleSelection.ts @@ -10,14 +10,17 @@ import $ from '../dom'; import SelectionUtils from '../selection'; import Block from '../block'; -import Timeout = NodeJS.Timeout; +/** + * + */ export default class RectangleSelection extends Module { /** * CSS classes for the Block - * @return {{wrapper: string, content: string}} + * + * @returns {{wrapper: string, content: string}} */ - static get CSS() { + public static get CSS(): {[name: string]: string} { return { overlay: 'codex-editor-overlay', overlayContainer: 'codex-editor-overlay__container', @@ -29,9 +32,10 @@ export default class RectangleSelection extends Module { /** * Using the selection rectangle + * * @type {boolean} */ - private isRectSelectionActivated: boolean = false; + private isRectSelectionActivated = false; /** * Speed of Scrolling @@ -57,12 +61,12 @@ export default class RectangleSelection extends Module { /** * Mouse is clamped */ - private mousedown: boolean = false; + private mousedown = false; /** * Is scrolling now */ - private isScrolling: boolean = false; + private isScrolling = false; /** * Mouse is in scroll zone @@ -72,10 +76,10 @@ export default class RectangleSelection extends Module { /** * Coords of rect */ - private startX: number = 0; - private startY: number = 0; - private mouseX: number = 0; - private mouseY: number = 0; + private startX = 0; + private startY = 0; + private mouseX = 0; + private mouseY = 0; /** * Selected blocks @@ -92,53 +96,53 @@ export default class RectangleSelection extends Module { */ private overlayRectangle: HTMLDivElement; + /** + * Listener identifiers + */ + private listenerIds: string[] = []; + /** * Module Preparation * Creating rect and hang handlers */ public prepare(): void { - const {Listeners} = this.Editor; - const {container} = this.genHTML(); - - Listeners.on(container, 'mousedown', (event: MouseEvent) => { - if (event.button !== this.MAIN_MOUSE_BUTTON) { - return; - } - this.startSelection(event.pageX, event.pageY); - }, false); - - Listeners.on(document.body, 'mousemove', (event: MouseEvent) => { - this.changingRectangle(event); - this.scrollByZones(event.clientY); - }, false); - - Listeners.on(document.body, 'mouseleave', () => { - this.clearSelection(); - this.endSelection(); - }); - - Listeners.on(window, 'scroll', (event) => { - this.changingRectangle(event); - }, false); - - Listeners.on(document.body, 'mouseup', () => { - this.endSelection(); - }, false); + this.enableModuleBindings(); } /** * Init rect params + * * @param {number} pageX - X coord of mouse * @param {number} pageY - Y coord of mouse */ - public startSelection(pageX, pageY) { - this.Editor.BlockSelection.allBlocksSelected = false; - this.clearSelection(); - this.stackOfSelected = []; - + public startSelection(pageX, pageY): void { const elemWhereSelectionStart = document.elementFromPoint(pageX - window.pageXOffset, pageY - window.pageYOffset); - if (!(elemWhereSelectionStart.closest('.' + this.Editor.UI.CSS.editorWrapper) && - !elemWhereSelectionStart.closest('.' + Block.CSS.content))) { + + /** + * Don't clear selected block by clicks on the Block settings + * because we need to keep highlighting working block + */ + const startsInsideToolbar = elemWhereSelectionStart.closest(`.${this.Editor.Toolbar.CSS.toolbar}`); + + if (!startsInsideToolbar) { + this.Editor.BlockSelection.allBlocksSelected = false; + this.clearSelection(); + this.stackOfSelected = []; + } + + const selectorsToAvoid = [ + `.${Block.CSS.content}`, + `.${this.Editor.Toolbar.CSS.toolbar}`, + `.${this.Editor.InlineToolbar.CSS.inlineToolbar}`, + ]; + + const startsInsideEditor = elemWhereSelectionStart.closest('.' + this.Editor.UI.CSS.editorWrapper); + const startsInSelectorToAvoid = selectorsToAvoid.some((selector) => !!elemWhereSelectionStart.closest(selector)); + + /** + * If selection starts outside of the editor or inside the blocks or on Editor UI elements, do not handle it + */ + if (!startsInsideEditor || startsInSelectorToAvoid) { return; } @@ -150,7 +154,7 @@ export default class RectangleSelection extends Module { /** * Clear all params to end selection */ - public endSelection() { + public endSelection(): void { this.mousedown = false; this.startX = 0; this.startY = 0; @@ -160,22 +164,94 @@ export default class RectangleSelection extends Module { /** * is RectSelection Activated */ - public isRectActivated() { + public isRectActivated(): boolean { return this.isRectSelectionActivated; } /** * Mark that selection is end */ - public clearSelection() { + public clearSelection(): void { this.isRectSelectionActivated = false; } + /** + * Sets Module necessary event handlers + */ + private enableModuleBindings(): void { + const { container } = this.genHTML(); + + this.listeners.on(container, 'mousedown', (mouseEvent: MouseEvent) => { + this.processMouseDown(mouseEvent); + }, false); + + this.listeners.on(document.body, 'mousemove', (mouseEvent: MouseEvent) => { + this.processMouseMove(mouseEvent); + }, false); + + this.listeners.on(document.body, 'mouseleave', () => { + this.processMouseLeave(); + }); + + this.listeners.on(window, 'scroll', (mouseEvent: MouseEvent) => { + this.processScroll(mouseEvent); + }, false); + + this.listeners.on(document.body, 'mouseup', () => { + this.processMouseUp(); + }, false); + } + + /** + * Handle mouse down events + * + * @param {MouseEvent} mouseEvent - mouse event payload + */ + private processMouseDown(mouseEvent: MouseEvent): void { + if (mouseEvent.button !== this.MAIN_MOUSE_BUTTON) { + return; + } + this.startSelection(mouseEvent.pageX, mouseEvent.pageY); + } + + /** + * Handle mouse move events + * + * @param {MouseEvent} mouseEvent - mouse event payload + */ + private processMouseMove(mouseEvent: MouseEvent): void { + this.changingRectangle(mouseEvent); + this.scrollByZones(mouseEvent.clientY); + } + + /** + * Handle mouse leave + */ + private processMouseLeave(): void { + this.clearSelection(); + this.endSelection(); + } + + /** + * @param {MouseEvent} mouseEvent - mouse event payload + */ + private processScroll(mouseEvent: MouseEvent): void { + this.changingRectangle(mouseEvent); + } + + /** + * Handle mouse up + */ + private processMouseUp(): void { + this.endSelection(); + } + /** * Scroll If mouse in scroll zone + * * @param {number} clientY - Y coord of mouse */ - private scrollByZones(clientY) { + private scrollByZones(clientY): void { this.inScrollZone = null; if (clientY <= this.HEIGHT_OF_SCROLL_ZONE) { this.inScrollZone = this.TOP_SCROLL_ZONE; @@ -186,6 +262,7 @@ export default class RectangleSelection extends Module { if (!this.inScrollZone) { this.isScrolling = false; + return; } @@ -195,8 +272,13 @@ export default class RectangleSelection extends Module { } } - private genHTML() { - const {UI} = this.Editor; + /** + * Generates required HTML elements + * + * @returns {object} + */ + private genHTML(): {container: Element; overlay: Element} { + const { UI } = this.Editor; const container = UI.nodes.holder.querySelector('.' + UI.CSS.editorWrapper); const overlay = $.make('div', RectangleSelection.CSS.overlay, {}); @@ -208,6 +290,7 @@ export default class RectangleSelection extends Module { container.appendChild(overlay); this.overlayRectangle = overlayRectangle as HTMLDivElement; + return { container, overlay, @@ -216,13 +299,15 @@ export default class RectangleSelection extends Module { /** * Activates scrolling if blockSelection is active and mouse is in scroll zone + * * @param {number} speed - speed of scrolling */ - private scrollVertical(speed) { + private scrollVertical(speed): void { if (!(this.inScrollZone && this.mousedown)) { return; } const lastOffset = window.pageYOffset; + window.scrollBy(0, speed); this.mouseY += window.pageYOffset - lastOffset; setTimeout(() => { @@ -232,9 +317,10 @@ export default class RectangleSelection extends Module { /** * Handles the change in the rectangle and its effect - * @param {MouseEvent} event + * + * @param {MouseEvent} event - mouse event */ - private changingRectangle(event) { + private changingRectangle(event: MouseEvent): void { if (!this.mousedown) { return; } @@ -244,11 +330,12 @@ export default class RectangleSelection extends Module { this.mouseY = event.pageY; } - const {rightPos, leftPos, index} = this.genInfoForMouseSelection(); + const { rightPos, leftPos, index } = this.genInfoForMouseSelection(); // There is not new block in selection const rectIsOnRighSideOfredactor = this.startX > rightPos && this.mouseX > rightPos; const rectISOnLeftSideOfRedactor = this.startX < leftPos && this.mouseX < leftPos; + this.rectCrossesBlocks = !(rectIsOnRighSideOfredactor || rectISOnLeftSideOfRedactor); if (!this.isRectSelectionActivated) { @@ -275,7 +362,7 @@ export default class RectangleSelection extends Module { /** * Shrink rect to singular point */ - private shrinkRectangleToPoint() { + private shrinkRectangleToPoint(): void { this.overlayRectangle.style.left = `${this.startX - window.pageXOffset}px`; this.overlayRectangle.style.top = `${this.startY - window.pageYOffset}px`; this.overlayRectangle.style.bottom = `calc(100% - ${this.startY - window.pageYOffset}px`; @@ -285,17 +372,17 @@ export default class RectangleSelection extends Module { /** * Select or unselect all of blocks in array if rect is out or in selectable area */ - private inverseSelection() { + private inverseSelection(): void { const firstBlockInStack = this.Editor.BlockManager.getBlockByIndex(this.stackOfSelected[0]); - const isSelecteMode = firstBlockInStack.selected; + const isSelectedMode = firstBlockInStack.selected; - if (this.rectCrossesBlocks && !isSelecteMode) { + if (this.rectCrossesBlocks && !isSelectedMode) { for (const it of this.stackOfSelected) { this.Editor.BlockSelection.selectBlockByIndex(it); } } - if (!this.rectCrossesBlocks && isSelecteMode) { + if (!this.rectCrossesBlocks && isSelectedMode) { for (const it of this.stackOfSelected) { this.Editor.BlockSelection.unSelectBlockByIndex(it); } @@ -305,7 +392,7 @@ export default class RectangleSelection extends Module { /** * Updates size of rectangle */ - private updateRectangleSize() { + private updateRectangleSize(): void { // Depending on the position of the mouse relative to the starting point, // change this.e distance from the desired edge of the screen*/ if (this.mouseY >= this.startY) { @@ -327,15 +414,17 @@ export default class RectangleSelection extends Module { /** * Collects information needed to determine the behavior of the rectangle - * @return {number} index - index next Block, leftPos - start of left border of Block, rightPos - right border + * + * @returns {object} index - index next Block, leftPos - start of left border of Block, rightPos - right border */ - private genInfoForMouseSelection() { + private genInfoForMouseSelection(): {index: number; leftPos: number; rightPos: number} { const widthOfRedactor = document.body.offsetWidth; const centerOfRedactor = widthOfRedactor / 2; const Y = this.mouseY - window.pageYOffset; const elementUnderMouse = document.elementFromPoint(centerOfRedactor, Y); const blockInCurrentPos = this.Editor.BlockManager.getBlockByChildNode(elementUnderMouse); let index; + if (blockInCurrentPos !== undefined) { index = this.Editor.BlockManager.blocks.findIndex((block) => block.holder === blockInCurrentPos.holder); } @@ -353,9 +442,10 @@ export default class RectangleSelection extends Module { /** * Select block with index index + * * @param index - index of block in redactor */ - private addBlockInSelection(index) { + private addBlockInSelection(index): void { if (this.rectCrossesBlocks) { this.Editor.BlockSelection.selectBlockByIndex(index); } @@ -364,9 +454,10 @@ export default class RectangleSelection extends Module { /** * Adds a block to the selection and determines which blocks should be selected + * * @param {object} index - index of new block in the reactor */ - private trySelectNextBlock(index) { + private trySelectNextBlock(index): void { const sameBlock = this.stackOfSelected[this.stackOfSelected.length - 1] === index; const sizeStack = this.stackOfSelected.length; const down = 1, up = -1, undef = 0; @@ -376,10 +467,16 @@ export default class RectangleSelection extends Module { } const blockNumbersIncrease = this.stackOfSelected[sizeStack - 1] - this.stackOfSelected[sizeStack - 2] > 0; - const direction = sizeStack <= 1 ? undef : blockNumbersIncrease ? down : up; - const selectionInDownDurection = index > this.stackOfSelected[sizeStack - 1] && direction === down; + + let direction = undef; + + if (sizeStack > 1) { + direction = blockNumbersIncrease ? down : up; + } + + const selectionInDownDirection = index > this.stackOfSelected[sizeStack - 1] && direction === down; const selectionInUpDirection = index < this.stackOfSelected[sizeStack - 1] && direction === up; - const generalSelection = selectionInDownDurection || selectionInUpDirection || direction === undef; + const generalSelection = selectionInDownDirection || selectionInUpDirection || direction === undef; const reduction = !generalSelection; // When the selection is too fast, some blocks do not have time to be noticed. Fix it. @@ -390,6 +487,7 @@ export default class RectangleSelection extends Module { for (ind; ind <= index; ind++) { this.addBlockInSelection(ind); } + return; } @@ -398,6 +496,7 @@ export default class RectangleSelection extends Module { for (let ind = this.stackOfSelected[sizeStack - 1] - 1; ind >= index; ind--) { this.addBlockInSelection(ind); } + return; } @@ -410,9 +509,9 @@ export default class RectangleSelection extends Module { // cmp for different directions if (index > this.stackOfSelected[sizeStack - 1]) { - cmp = () => index > this.stackOfSelected[i]; + cmp = (): boolean => index > this.stackOfSelected[i]; } else { - cmp = () => index < this.stackOfSelected[i]; + cmp = (): boolean => index < this.stackOfSelected[i]; } // Remove blocks missed due to speed. @@ -424,6 +523,5 @@ export default class RectangleSelection extends Module { this.stackOfSelected.pop(); i--; } - return; } } diff --git a/src/components/modules/renderer.ts b/src/components/modules/renderer.ts index 183593625..d94efb8b0 100644 --- a/src/components/modules/renderer.ts +++ b/src/components/modules/renderer.ts @@ -1,7 +1,6 @@ import Module from '../__module'; -import _, {ChainData} from '../utils'; -import {BlockToolData} from '../../../types'; -import {BlockToolConstructable} from '../../../types/tools'; +import * as _ from '../utils'; +import { BlockToolConstructable, OutputBlockData } from '../../../types'; /** * Editor.js Renderer Module @@ -13,9 +12,9 @@ import {BlockToolConstructable} from '../../../types/tools'; */ export default class Renderer extends Module { /** - * @typedef {Object} RendererBlocks - * @property {String} type - tool name - * @property {Object} data - tool data + * @typedef {object} RendererBlocks + * @property {string} type - tool name + * @property {object} data - tool data */ /** @@ -40,12 +39,17 @@ export default class Renderer extends Module { /** * Make plugin blocks from array of plugin`s data - * @param {RendererBlocks[]} blocks + * + * @param {OutputBlockData[]} blocks - blocks to render */ - public render(blocks: BlockToolData[]): Promise { - const chainData = blocks.map((block) => ({function: () => this.insertBlock(block)})); + public async render(blocks: OutputBlockData[]): Promise { + const chainData = blocks.map((block) => ({ function: (): Promise => this.insertBlock(block) })); + + const sequence = await _.sequence(chainData as _.ChainData[]); + + this.Editor.UI.checkEmptiness(); - return _.sequence(chainData as ChainData[]); + return sequence; } /** @@ -53,25 +57,26 @@ export default class Renderer extends Module { * Add plugin instance to BlockManager * Insert block to working zone * - * @param {Object} item + * @param {object} item - Block data to insert + * * @returns {Promise} - * @private */ - public async insertBlock(item): Promise { + public async insertBlock(item: OutputBlockData): Promise { const { Tools, BlockManager } = this.Editor; const tool = item.type; const data = item.data; - const settings = item.settings; if (tool in Tools.available) { try { - BlockManager.insert(tool, data, settings); + BlockManager.insert({ + tool, + data, + }); } catch (error) { _.log(`Block «${tool}» skipped because of plugins error`, 'warn', data); throw Error(error); } } else { - /** If Tool is unavailable, create stub Block for it */ const stubData = { savedData: { @@ -85,10 +90,13 @@ export default class Renderer extends Module { const toolToolboxSettings = (Tools.unavailable[tool] as BlockToolConstructable).toolbox; const userToolboxSettings = Tools.getToolSettings(tool).toolbox; - stubData.title = toolToolboxSettings.title || userToolboxSettings.title || stubData.title; + stubData.title = toolToolboxSettings.title || (userToolboxSettings && userToolboxSettings.title) || stubData.title; } - const stub = BlockManager.insert(Tools.stubTool, stubData, settings); + const stub = BlockManager.insert({ + tool: Tools.stubTool, + data: stubData, + }); stub.stretched = true; diff --git a/src/components/modules/sanitizer.ts b/src/components/modules/sanitizer.ts index 22782c335..f3bc086ff 100644 --- a/src/components/modules/sanitizer.ts +++ b/src/components/modules/sanitizer.ts @@ -17,11 +17,11 @@ */ import Module from '../__module'; -import _ from '../utils'; +import * as _ from '../utils'; /** - * @typedef {Object} SanitizerConfig - * @property {Object} tags - define tags restrictions + * @typedef {object} SanitizerConfig + * @property {object} tags - define tags restrictions * * @example * @@ -36,8 +36,12 @@ import _ from '../utils'; */ import HTMLJanitor from 'html-janitor'; -import {BlockToolData, InlineToolConstructable, SanitizerConfig} from '../../../types'; +import { BlockToolData, InlineToolConstructable, SanitizerConfig } from '../../../types'; +import { SavedData } from '../../../types/data-formats'; +/** + * + */ export default class Sanitizer extends Module { /** * Memoize tools config @@ -54,12 +58,11 @@ export default class Sanitizer extends Module { * * Enumerate blocks and clean data * - * @param {{tool, data: BlockToolData}[]} blocksData[] + * @param {Array<{tool, data: BlockToolData}>} blocksData - blocks' data to sanitize */ public sanitizeBlocks( - blocksData: Array<{tool: string, data: BlockToolData}>, - ): Array<{tool: string, data: BlockToolData}> { - + blocksData: Array> + ): Array> { return blocksData.map((block) => { const toolConfig = this.composeToolConfig(block.tool); @@ -67,7 +70,7 @@ export default class Sanitizer extends Module { return block; } - block.data = this.deepSanitize(block.data, toolConfig); + block.data = this.deepSanitize(block.data, toolConfig) as BlockToolData; return block; }); @@ -79,7 +82,7 @@ export default class Sanitizer extends Module { * @param {BlockToolData|object|*} dataToSanitize - taint string or object/array that contains taint string * @param {SanitizerConfig} rules - object with sanitizer rules */ - public deepSanitize(dataToSanitize: any, rules: SanitizerConfig): any { + public deepSanitize(dataToSanitize: object | string, rules: SanitizerConfig): object | string { /** * BlockData It may contain 3 types: * - Array @@ -91,7 +94,7 @@ export default class Sanitizer extends Module { * Array: call sanitize for each item */ return this.cleanArray(dataToSanitize, rules); - } else if (typeof dataToSanitize === 'object') { + } else if (_.isObject(dataToSanitize)) { /** * Objects: just clean object deeper. */ @@ -102,9 +105,10 @@ export default class Sanitizer extends Module { * * Clean only strings */ - if (typeof dataToSanitize === 'string') { + if (_.isString(dataToSanitize)) { return this.cleanOneItem(dataToSanitize, rules); } + return dataToSanitize; } } @@ -116,10 +120,9 @@ export default class Sanitizer extends Module { * @param {string} taintString - taint string * @param {SanitizerConfig} customConfig - allowed tags * - * @return {string} clean HTML + * @returns {string} clean HTML */ public clean(taintString: string, customConfig: SanitizerConfig = {} as SanitizerConfig): string { - const sanitizerConfig = { tags: customConfig, }; @@ -128,15 +131,16 @@ export default class Sanitizer extends Module { * API client can use custom config to manage sanitize process */ const sanitizerInstance = this.createHTMLJanitorInstance(sanitizerConfig); + return sanitizerInstance.clean(taintString); } /** * Merge with inline tool config * - * @param {string} toolName - * @param {SanitizerConfig} toolRules - * @return {SanitizerConfig} + * @param {string} toolName - tool name + * + * @returns {SanitizerConfig} */ public composeToolConfig(toolName: string): SanitizerConfig { /** @@ -146,7 +150,7 @@ export default class Sanitizer extends Module { return this.configCache[toolName]; } - const sanitizeGetter = this.Editor.Tools.apiSettings.SANITIZE_CONFIG; + const sanitizeGetter = this.Editor.Tools.INTERNAL_SETTINGS.SANITIZE_CONFIG; const toolClass = this.Editor.Tools.available[toolName]; const baseConfig = this.getInlineToolsConfig(toolName); @@ -160,10 +164,12 @@ export default class Sanitizer extends Module { const toolRules = toolClass.sanitize; const toolConfig = {} as SanitizerConfig; + for (const fieldName in toolRules) { - if (toolRules.hasOwnProperty(fieldName)) { + if (Object.prototype.hasOwnProperty.call(toolRules, fieldName)) { const rule = toolRules[fieldName]; - if (typeof rule === 'object') { + + if (_.isObject(rule)) { toolConfig[fieldName] = Object.assign({}, baseConfig, rule); } else { toolConfig[fieldName] = rule; @@ -179,15 +185,17 @@ export default class Sanitizer extends Module { * Returns Sanitizer config * When Tool's "inlineToolbar" value is True, get all sanitizer rules from all tools, * otherwise get only enabled + * + * @param {string} name - Inline Tool name */ public getInlineToolsConfig(name: string): SanitizerConfig { - const {Tools} = this.Editor; + const { Tools } = this.Editor; const toolsConfig = Tools.getToolSettings(name); const enableInlineTools = toolsConfig.inlineToolbar || []; let config = {} as SanitizerConfig; - if (typeof enableInlineTools === 'boolean' && enableInlineTools) { + if (_.isBoolean(enableInlineTools) && enableInlineTools) { /** * getting all tools sanitizer rule */ @@ -196,14 +204,20 @@ export default class Sanitizer extends Module { /** * getting only enabled */ - (enableInlineTools as string[]).map( (inlineToolName) => { + (enableInlineTools as string[]).map((inlineToolName) => { config = Object.assign( config, - Tools.inline[inlineToolName][Tools.apiSettings.SANITIZE_CONFIG], + Tools.inline[inlineToolName][Tools.INTERNAL_SETTINGS.SANITIZE_CONFIG] ) as SanitizerConfig; }); } + /** + * Allow linebreaks + */ + config['br'] = true; + config['wbr'] = true; + return config; } @@ -211,7 +225,7 @@ export default class Sanitizer extends Module { * Return general config for all inline tools */ public getAllInlineToolsConfig(): SanitizerConfig { - const {Tools} = this.Editor; + const { Tools } = this.Editor; if (this.inlineToolsConfigCache) { return this.inlineToolsConfigCache; @@ -220,8 +234,8 @@ export default class Sanitizer extends Module { const config: SanitizerConfig = {} as SanitizerConfig; Object.entries(Tools.inline) - .forEach( ([name, inlineTool]: [string, InlineToolConstructable]) => { - Object.assign(config, inlineTool[Tools.apiSettings.SANITIZE_CONFIG]); + .forEach(([, inlineTool]: [string, InlineToolConstructable]) => { + Object.assign(config, inlineTool[Tools.INTERNAL_SETTINGS.SANITIZE_CONFIG]); }); this.inlineToolsConfigCache = config; @@ -231,24 +245,26 @@ export default class Sanitizer extends Module { /** * Clean array - * @param {array} array - [1, 2, {}, []] - * @param {object} ruleForItem + * + * @param {Array} array - [1, 2, {}, []] + * @param {SanitizerConfig} ruleForItem - sanitizer config for array */ - private cleanArray(array: any[], ruleForItem: SanitizerConfig): any[] { - return array.map( (arrayItem) => this.deepSanitize(arrayItem, ruleForItem)); + private cleanArray(array: Array, ruleForItem: SanitizerConfig): Array { + return array.map((arrayItem) => this.deepSanitize(arrayItem, ruleForItem)); } /** * Clean object + * * @param {object} object - {level: 0, text: 'adada', items: [1,2,3]}} * @param {object} rules - { b: true } or true|false - * @return {object} + * @returns {object} */ - private cleanObject(object: any, rules: SanitizerConfig|{[field: string]: SanitizerConfig}): any { + private cleanObject(object: object, rules: SanitizerConfig|{[field: string]: SanitizerConfig}): object { const cleanData = {}; for (const fieldName in object) { - if (!object.hasOwnProperty(fieldName)) { + if (!Object.prototype.hasOwnProperty.call(object, fieldName)) { continue; } @@ -263,16 +279,20 @@ export default class Sanitizer extends Module { cleanData[fieldName] = this.deepSanitize(currentIterationItem, ruleForItem as SanitizerConfig); } + return cleanData; } /** - * @param {string} taintString - * @param {SanitizerConfig|boolean} rule - * @return {string} + * Clean primitive value + * + * @param {string} taintString - string to clean + * @param {SanitizerConfig|boolean} rule - sanitizer rule + * + * @returns {string} */ private cleanOneItem(taintString: string, rule: SanitizerConfig|boolean): string { - if (typeof rule === 'object') { + if (_.isObject(rule)) { return this.clean(taintString, rule); } else if (rule === false) { return this.clean(taintString, {} as SanitizerConfig); @@ -285,10 +305,11 @@ export default class Sanitizer extends Module { * Check if passed item is a HTML Janitor rule: * { a : true }, {}, false, true, function(){} — correct rules * undefined, null, 0, 1, 2 — not a rules - * @param config + * + * @param {SanitizerConfig} config - config to check */ private isRule(config: SanitizerConfig): boolean { - return typeof config === 'object' || typeof config === 'boolean' || typeof config === 'function'; + return _.isObject(config) || _.isBoolean(config) || _.isFunction(config); } /** @@ -296,8 +317,9 @@ export default class Sanitizer extends Module { * Or, sanitizing config can be defined globally in editors initialization. That config will be used everywhere * At least, if there is no config overrides, that API uses Default configuration * - * @uses https://www.npmjs.com/package/html-janitor - * @license https://github.com/guardian/html-janitor/blob/master/LICENSE + * @see {@link https://www.npmjs.com/package/html-janitor} + * @license Apache-2.0 + * @see {@link https://github.com/guardian/html-janitor/blob/master/LICENSE} * * @param {SanitizerConfig} config - sanitizer extension */ @@ -305,6 +327,7 @@ export default class Sanitizer extends Module { if (config) { return new HTMLJanitor(config); } + return null; } } diff --git a/src/components/modules/saver.ts b/src/components/modules/saver.ts index 4777ba89d..3c0879b0f 100644 --- a/src/components/modules/saver.ts +++ b/src/components/modules/saver.ts @@ -6,9 +6,10 @@ * @version 2.0.0 */ import Module from '../__module'; -import {OutputData} from '../../../types'; -import {ValidatedData} from '../../types-internal/block-data'; +import { OutputData } from '../../../types'; +import { ValidatedData } from '../../../types/data-formats'; import Block from '../block'; +import * as _ from '../utils'; declare const VERSION: string; @@ -17,79 +18,89 @@ declare const VERSION: string; * * @typedef {Saver} Saver * @property {Element} html - Editor HTML content - * @property {String} json - Editor JSON output + * @property {string} json - Editor JSON output */ export default class Saver extends Module { /** * Composes new chain of Promises to fire them alternatelly - * @return {OutputData} + * + * @returns {OutputData} */ public async save(): Promise { - const {BlockManager, Sanitizer, ModificationsObserver} = this.Editor; + const { BlockManager, Sanitizer, ModificationsObserver } = this.Editor; const blocks = BlockManager.blocks, - chainData = []; + chainData = []; /** * Disable modifications observe while saving */ ModificationsObserver.disable(); - blocks.forEach((block: Block) => { - chainData.push(this.getSavedData(block)); - }); - - const extractedData = await Promise.all(chainData); - const sanitizedData = await Sanitizer.sanitizeBlocks(extractedData); + try { + blocks.forEach((block: Block) => { + chainData.push(this.getSavedData(block)); + }); - ModificationsObserver.enable(); + const extractedData = await Promise.all(chainData); + const sanitizedData = await Sanitizer.sanitizeBlocks(extractedData); - return this.makeOutput(sanitizedData); + return this.makeOutput(sanitizedData); + } finally { + ModificationsObserver.enable(); + } } /** * Saves and validates + * * @param {Block} block - Editor's Tool - * @return {ValidatedData} - Tool's validated data + * @returns {ValidatedData} - Tool's validated data */ private async getSavedData(block: Block): Promise { - const blockData = await block.save(); - const isValid = blockData && await block.validate(blockData.data); + const blockData = await block.save(); + const isValid = blockData && await block.validate(blockData.data); - return {...blockData, isValid}; + return { + ...blockData, + isValid, + }; } /** * Creates output object with saved data, time and version of editor - * @param {ValidatedData} allExtractedData - * @return {OutputData} + * + * @param {ValidatedData} allExtractedData - data extracted from Blocks + * @returns {OutputData} */ private makeOutput(allExtractedData): OutputData { let totalTime = 0; const blocks = []; - console.groupCollapsed('[Editor.js saving]:'); + _.log('[Editor.js saving]:', 'groupCollapsed'); - allExtractedData.forEach(({tool, data, time, isValid}) => { + allExtractedData.forEach(({ tool, data, time, isValid }) => { totalTime += time; /** * Capitalize Tool name */ - console.group(`${tool.charAt(0).toUpperCase() + tool.slice(1)}`); + _.log(`${tool.charAt(0).toUpperCase() + tool.slice(1)}`, 'group'); if (isValid) { /** Group process info */ - console.log(data); - console.groupEnd(); + _.log(data); + _.log(undefined, 'groupEnd'); } else { - console.log(`Block «${tool}» skipped because saved data is invalid`); - console.groupEnd(); + _.log(`Block «${tool}» skipped because saved data is invalid`); + _.log(undefined, 'groupEnd'); + return; } /** If it was stub Block, get original data */ if (tool === this.Editor.Tools.stubTool) { blocks.push(data); + return; } @@ -99,8 +110,8 @@ export default class Saver extends Module { }); }); - console.log('Total', totalTime); - console.groupEnd(); + _.log('Total', 'log', totalTime); + _.log(undefined, 'groupEnd'); return { time: +new Date(), diff --git a/src/components/modules/shortcuts.ts b/src/components/modules/shortcuts.ts deleted file mode 100644 index 707b6fa33..000000000 --- a/src/components/modules/shortcuts.ts +++ /dev/null @@ -1,67 +0,0 @@ -import Shortcut from '@codexteam/shortcuts'; - -/** - * ShortcutData interface - * Each shortcut must have name and handler - * `name` is a shortcut, like 'CMD+K', 'CMD+B' etc - * `handler` is a callback - */ -export interface ShortcutData { - - /** - * Shortcut name - * Ex. CMD+I, CMD+B .... - */ - name: string; - - /** - * Shortcut handler - */ - handler(event): void; -} - -/** - * Contains keyboard and mouse events binded on each Block by Block Manager - */ -import Module from '../__module'; - -/** - * @class Shortcut - * @classdesc Allows to register new shortcut - * - * Internal Shortcuts Module - */ -export default class Shortcuts extends Module { - /** - * All registered shortcuts - * @type {Shortcut[]} - */ - private registeredShortcuts: Shortcut[] = []; - - /** - * Register shortcut - * @param {ShortcutData} shortcut - */ - public add(shortcut: ShortcutData): void { - const { UI } = this.Editor; - - const newShortcut = new Shortcut({ - name: shortcut.name, - on: document, // UI.nodes.redactor - callback: shortcut.handler, - }); - - this.registeredShortcuts.push(newShortcut); - } - - /** - * Remove shortcut - * @param {ShortcutData} shortcut - */ - public remove(shortcut: string): void { - const index = this.registeredShortcuts.findIndex((shc) => shc.name === shortcut); - - this.registeredShortcuts[index].remove(); - this.registeredShortcuts.splice(index, 1); - } -} diff --git a/src/components/modules/toolbar/blockSettings.ts b/src/components/modules/toolbar/blockSettings.ts index 4fd3bfb5f..a3a61c54c 100644 --- a/src/components/modules/toolbar/blockSettings.ts +++ b/src/components/modules/toolbar/blockSettings.ts @@ -1,5 +1,17 @@ import Module from '../../__module'; import $ from '../../dom'; +import Flipper, { FlipperOptions } from '../../flipper'; +import * as _ from '../../utils'; +import SelectionUtils from '../../selection'; + +/** + * HTML Elements that used for BlockSettings + */ +interface BlockSettingsNodes { + wrapper: HTMLElement; + toolSettings: HTMLElement; + defaultSettings: HTMLElement; +} /** * Block Settings @@ -12,13 +24,13 @@ import $ from '../../dom'; * | ...................... | * |________________________| */ -export default class BlockSettings extends Module { - +export default class BlockSettings extends Module { /** * Module Events - * @return {{opened: string, closed: string}} + * + * @returns {{opened: string, closed: string}} */ - public get events(): {opened: string, closed: string} { + public get events(): { opened: string; closed: string } { return { opened: 'block-settings-opened', closed: 'block-settings-closed', @@ -27,9 +39,10 @@ export default class BlockSettings extends Module { /** * Block Settings CSS - * @return {{wrapper, wrapperOpened, toolSettings, defaultSettings, button}} + * + * @returns {{wrapper, wrapperOpened, toolSettings, defaultSettings, button}} */ - private static get CSS() { + public get CSS(): { [name: string]: string } { return { // Settings Panel wrapper: 'ce-settings', @@ -38,47 +51,90 @@ export default class BlockSettings extends Module { defaultSettings: 'ce-settings__default-zone', button: 'ce-settings__button', + + focusedButton: 'ce-settings__button--focused', + focusedButtonAnimated: 'ce-settings__button--focused-animated', }; } /** * Is Block Settings opened or not + * * @returns {boolean} */ public get opened(): boolean { - return this.nodes.wrapper.classList.contains(BlockSettings.CSS.wrapperOpened); + return this.nodes.wrapper.classList.contains(this.CSS.wrapperOpened); } /** - * Block settings UI HTML elements + * List of buttons */ - public nodes: {[key: string]: HTMLElement} = { - wrapper: null, - toolSettings: null, - defaultSettings: null, - }; + private buttons: HTMLElement[] = []; + + /** + * Instance of class that responses for leafing buttons by arrows/tab + * + * @type {Flipper|null} + */ + private flipper: Flipper = null; + + /** + * Page selection utils + */ + private selection: SelectionUtils = new SelectionUtils(); /** * Panel with block settings with 2 sections: * - Tool's Settings * - Default Settings [Move, Remove, etc] - * - * @return {Element} */ public make(): void { - this.nodes.wrapper = $.make('div', BlockSettings.CSS.wrapper); + this.nodes.wrapper = $.make('div', this.CSS.wrapper); - this.nodes.toolSettings = $.make('div', BlockSettings.CSS.toolSettings); - this.nodes.defaultSettings = $.make('div', BlockSettings.CSS.defaultSettings); + this.nodes.toolSettings = $.make('div', this.CSS.toolSettings); + this.nodes.defaultSettings = $.make('div', this.CSS.defaultSettings); $.append(this.nodes.wrapper, [this.nodes.toolSettings, this.nodes.defaultSettings]); + + /** + * Active leafing by arrows/tab + * Buttons will be filled on opening + */ + this.enableFlipper(); + } + + /** + * Destroys module + */ + public destroy(): void { + /** + * Sometimes (in read-only mode) there is no Flipper + */ + if (this.flipper) { + this.flipper.deactivate(); + this.flipper = null; + } + + this.removeAllNodes(); } /** * Open Block Settings pane */ public open(): void { - this.nodes.wrapper.classList.add(BlockSettings.CSS.wrapperOpened); + this.nodes.wrapper.classList.add(this.CSS.wrapperOpened); + + /** + * If block settings contains any inputs, focus will be set there, + * so we need to save current selection to restore it after block settings is closed + */ + this.selection.save(); + + /** + * Highlight content of a Block we are working with + */ + this.Editor.BlockManager.currentBlock.selected = true; + this.Editor.BlockSelection.clearCache(); /** * Fill Tool's settings @@ -91,28 +147,89 @@ export default class BlockSettings extends Module { this.addDefaultSettings(); /** Tell to subscribers that block settings is opened */ - this.Editor.Events.emit(this.events.opened); + this.eventsDispatcher.emit(this.events.opened); + + this.flipper.activate(this.blockTunesButtons); } /** * Close Block Settings pane */ public close(): void { - this.nodes.wrapper.classList.remove(BlockSettings.CSS.wrapperOpened); + this.nodes.wrapper.classList.remove(this.CSS.wrapperOpened); + + /** + * If selection is at editor on Block Settings closing, + * it means that caret placed at some editable element inside the Block Settings. + * Previously we have saved the selection, then open the Block Settings and set caret to the input + * + * So, we need to restore selection back to Block after closing the Block Settings + */ + if (!SelectionUtils.isAtEditor) { + this.selection.restore(); + } + + this.selection.clearSaved(); + + /** + * Remove highlighted content of a Block we are working with + */ + if (!this.Editor.CrossBlockSelection.isCrossBlockSelectionStarted && this.Editor.BlockManager.currentBlock) { + this.Editor.BlockManager.currentBlock.selected = false; + } /** Clear settings */ this.nodes.toolSettings.innerHTML = ''; this.nodes.defaultSettings.innerHTML = ''; /** Tell to subscribers that block settings is closed */ - this.Editor.Events.emit(this.events.closed); + this.eventsDispatcher.emit(this.events.closed); + + /** Clear cached buttons */ + this.buttons = []; + + /** Clear focus on active button */ + this.flipper.deactivate(); + } + + /** + * Returns Tools Settings and Default Settings + * + * @returns {HTMLElement[]} + */ + public get blockTunesButtons(): HTMLElement[] { + const { StylesAPI } = this.Editor; + + /** + * Return from cache + * if exists + */ + if (this.buttons.length !== 0) { + return this.buttons; + } + + const toolSettings = this.nodes.toolSettings.querySelectorAll( + // Select buttons and inputs + `.${StylesAPI.classes.settingsButton}, ${$.allInputsSelector}` + ); + const defaultSettings = this.nodes.defaultSettings.querySelectorAll(`.${this.CSS.button}`); + + toolSettings.forEach((item) => { + this.buttons.push((item as HTMLElement)); + }); + + defaultSettings.forEach((item) => { + this.buttons.push((item as HTMLElement)); + }); + + return this.buttons; } /** * Add Tool's settings */ private addToolSettings(): void { - if (typeof this.Editor.BlockManager.currentBlock.tool.renderSettings === 'function') { + if (_.isFunction(this.Editor.BlockManager.currentBlock.tool.renderSettings)) { $.append(this.nodes.toolSettings, this.Editor.BlockManager.currentBlock.tool.renderSettings()); } } @@ -123,4 +240,35 @@ export default class BlockSettings extends Module { private addDefaultSettings(): void { $.append(this.nodes.defaultSettings, this.Editor.BlockManager.currentBlock.renderTunes()); } + + /** + * Active leafing by arrows/tab + * Buttons will be filled on opening + */ + private enableFlipper(): void { + this.flipper = new Flipper({ + focusedItemClass: this.CSS.focusedButton, + /** + * @param {HTMLElement} focusedItem - activated Tune + */ + activateCallback: (focusedItem) => { + /** + * If focused item is editable element, close block settings + */ + if (focusedItem && $.canSetCaret(focusedItem)) { + this.close(); + + return; + } + + /** + * Restoring focus on current Block after settings clicked. + * For example, when H3 changed to H2 — DOM Elements replaced, so we need to focus a new one + */ + _.delay(() => { + this.Editor.Caret.setToBlock(this.Editor.BlockManager.currentBlock); + }, 50)(); + }, + } as FlipperOptions); + } } diff --git a/src/components/modules/toolbar/conversion.ts b/src/components/modules/toolbar/conversion.ts new file mode 100644 index 000000000..a258bf2da --- /dev/null +++ b/src/components/modules/toolbar/conversion.ts @@ -0,0 +1,356 @@ +import Module from '../../__module'; +import $ from '../../dom'; +import { BlockToolConstructable } from '../../../../types'; +import * as _ from '../../utils'; +import { SavedData } from '../../../../types/data-formats'; +import Flipper from '../../flipper'; +import I18n from '../../i18n'; +import { I18nInternalNS } from '../../i18n/namespace-internal'; + +/** + * HTML Elements used for ConversionToolbar + */ +interface ConversionToolbarNodes { + wrapper: HTMLElement; + tools: HTMLElement; +} + +/** + * Block Converter + */ +export default class ConversionToolbar extends Module { + /** + * CSS getter + */ + public static get CSS(): { [key: string]: string } { + return { + conversionToolbarWrapper: 'ce-conversion-toolbar', + conversionToolbarShowed: 'ce-conversion-toolbar--showed', + conversionToolbarTools: 'ce-conversion-toolbar__tools', + conversionToolbarLabel: 'ce-conversion-toolbar__label', + conversionTool: 'ce-conversion-tool', + conversionToolHidden: 'ce-conversion-tool--hidden', + conversionToolIcon: 'ce-conversion-tool__icon', + + conversionToolFocused: 'ce-conversion-tool--focused', + conversionToolActive: 'ce-conversion-tool--active', + }; + } + + /** + * Conversion Toolbar open/close state + * + * @type {boolean} + */ + public opened = false; + + /** + * Available tools + */ + private tools: { [key: string]: HTMLElement } = {}; + + /** + * Instance of class that responses for leafing buttons by arrows/tab + * + * @type {Flipper|null} + */ + private flipper: Flipper = null; + + /** + * Callback that fill be fired on open/close and accepts an opening state + */ + private togglingCallback = null; + + /** + * Create UI of Conversion Toolbar + */ + public make(): HTMLElement { + this.nodes.wrapper = $.make('div', [ + ConversionToolbar.CSS.conversionToolbarWrapper, + ...(this.isRtl ? [ this.Editor.UI.CSS.editorRtlFix ] : []), + ]); + this.nodes.tools = $.make('div', ConversionToolbar.CSS.conversionToolbarTools); + + const label = $.make('div', ConversionToolbar.CSS.conversionToolbarLabel, { + textContent: I18n.ui(I18nInternalNS.ui.inlineToolbar.converter, 'Convert to'), + }); + + /** + * Add Tools that has 'import' method + */ + this.addTools(); + + /** + * Prepare Flipper to be able to leaf tools by arrows/tab + */ + this.enableFlipper(); + + $.append(this.nodes.wrapper, label); + $.append(this.nodes.wrapper, this.nodes.tools); + + return this.nodes.wrapper; + } + + /** + * Deactivates flipper and removes all nodes + */ + public destroy(): void { + /** + * Sometimes (in read-only mode) there is no Flipper + */ + if (this.flipper) { + this.flipper.deactivate(); + this.flipper = null; + } + + this.removeAllNodes(); + } + + /** + * Toggle conversion dropdown visibility + * + * @param {Function} [togglingCallback] — callback that will accept opening state + */ + public toggle(togglingCallback?: (openedState: boolean) => void): void { + if (!this.opened) { + this.open(); + } else { + this.close(); + } + + if (_.isFunction(togglingCallback)) { + this.togglingCallback = togglingCallback; + } + } + + /** + * Shows Conversion Toolbar + */ + public open(): void { + this.filterTools(); + + this.opened = true; + this.nodes.wrapper.classList.add(ConversionToolbar.CSS.conversionToolbarShowed); + + /** + * We use timeout to prevent bubbling Enter keydown on first dropdown item + * Conversion flipper will be activated after dropdown will open + */ + setTimeout(() => { + this.flipper.activate(Object.values(this.tools).filter((button) => { + return !button.classList.contains(ConversionToolbar.CSS.conversionToolHidden); + })); + this.flipper.focusFirst(); + + if (_.isFunction(this.togglingCallback)) { + this.togglingCallback(true); + } + }, 50); + } + + /** + * Closes Conversion Toolbar + */ + public close(): void { + this.opened = false; + this.flipper.deactivate(); + this.nodes.wrapper.classList.remove(ConversionToolbar.CSS.conversionToolbarShowed); + + if (_.isFunction(this.togglingCallback)) { + this.togglingCallback(false); + } + } + + /** + * Returns true if it has more than one tool available for convert in + */ + public hasTools(): boolean { + const tools = Object.keys(this.tools); // available tools in array representation + + return !(tools.length === 1 && tools.shift() === this.config.defaultBlock); + } + + /** + * Replaces one Block with another + * For that Tools must provide import/export methods + * + * @param {string} replacingToolName - name of Tool which replaces current + */ + public async replaceWithBlock(replacingToolName: string): Promise { + /** + * At first, we get current Block data + * + * @type {BlockToolConstructable} + */ + const currentBlockClass = this.Editor.BlockManager.currentBlock.class; + const currentBlockName = this.Editor.BlockManager.currentBlock.name; + const savedBlock = await this.Editor.BlockManager.currentBlock.save() as SavedData; + const { INTERNAL_SETTINGS } = this.Editor.Tools; + const blockData = savedBlock.data; + + /** + * When current Block name is equals to the replacing tool Name, + * than convert this Block back to the default Block + */ + if (currentBlockName === replacingToolName) { + replacingToolName = this.config.defaultBlock; + } + + /** + * Getting a class of replacing Tool + * + * @type {BlockToolConstructable} + */ + const replacingTool = this.Editor.Tools.toolsClasses[replacingToolName] as BlockToolConstructable; + + /** + * Export property can be: + * 1) Function — Tool defines which data to return + * 2) String — the name of saved property + * + * In both cases returning value must be a string + */ + let exportData = ''; + const exportProp = currentBlockClass[INTERNAL_SETTINGS.CONVERSION_CONFIG].export; + + if (_.isFunction(exportProp)) { + exportData = exportProp(blockData); + } else if (_.isString(exportProp)) { + exportData = blockData[exportProp]; + } else { + _.log('Conversion «export» property must be a string or function. ' + + 'String means key of saved data object to export. Function should export processed string to export.'); + + return; + } + + /** + * Clean exported data with replacing sanitizer config + */ + const cleaned: string = this.Editor.Sanitizer.clean( + exportData, + replacingTool.sanitize + ); + + /** + * «import» property can be Function or String + * function — accept imported string and compose tool data object + * string — the name of data field to import + */ + let newBlockData = {}; + const importProp = replacingTool[INTERNAL_SETTINGS.CONVERSION_CONFIG].import; + + if (_.isFunction(importProp)) { + newBlockData = importProp(cleaned); + } else if (_.isString(importProp)) { + newBlockData[importProp] = cleaned; + } else { + _.log('Conversion «import» property must be a string or function. ' + + 'String means key of tool data to import. Function accepts a imported string and return composed tool data.'); + + return; + } + + this.Editor.BlockManager.replace({ + tool: replacingToolName, + data: newBlockData, + }); + this.Editor.BlockSelection.clearSelection(); + + this.close(); + this.Editor.InlineToolbar.close(); + + _.delay(() => { + this.Editor.Caret.setToBlock(this.Editor.BlockManager.currentBlock); + }, 10)(); + } + + /** + * Iterates existing Tools and inserts to the ConversionToolbar + * if tools have ability to import + */ + private addTools(): void { + const tools = this.Editor.Tools.blockTools; + + for (const toolName in tools) { + if (!Object.prototype.hasOwnProperty.call(tools, toolName)) { + continue; + } + + const internalSettings = this.Editor.Tools.INTERNAL_SETTINGS; + const toolClass = tools[toolName] as BlockToolConstructable; + const toolToolboxSettings = toolClass[internalSettings.TOOLBOX]; + const conversionConfig = toolClass[internalSettings.CONVERSION_CONFIG]; + + const userSettings = this.Editor.Tools.USER_SETTINGS; + const userToolboxSettings = this.Editor.Tools.getToolSettings(toolName)[userSettings.TOOLBOX]; + + const toolboxSettings = userToolboxSettings ?? toolToolboxSettings; + + /** + * Skip tools that don't pass 'toolbox' property + */ + if (_.isEmpty(toolboxSettings) || !toolboxSettings.icon) { + continue; + } + + /** + * Skip tools without «import» rule specified + */ + if (!conversionConfig || !conversionConfig.import) { + continue; + } + + this.addTool(toolName, toolboxSettings.icon, toolboxSettings.title); + } + } + + /** + * Add tool to the Conversion Toolbar + * + * @param {string} toolName - name of Tool to add + * @param {string} toolIcon - Tool icon + * @param {string} title - button title + */ + private addTool(toolName: string, toolIcon: string, title: string): void { + const tool = $.make('div', [ ConversionToolbar.CSS.conversionTool ]); + const icon = $.make('div', [ ConversionToolbar.CSS.conversionToolIcon ]); + + tool.dataset.tool = toolName; + icon.innerHTML = toolIcon; + + $.append(tool, icon); + $.append(tool, $.text(I18n.t(I18nInternalNS.toolNames, title || _.capitalize(toolName)))); + + $.append(this.nodes.tools, tool); + this.tools[toolName] = tool; + + this.listeners.on(tool, 'click', async () => { + await this.replaceWithBlock(toolName); + }); + } + + /** + * Hide current Tool and show others + */ + private filterTools(): void { + const { currentBlock } = this.Editor.BlockManager; + + /** + * Show previously hided + */ + Object.entries(this.tools).forEach(([name, button]) => { + button.hidden = false; + button.classList.toggle(ConversionToolbar.CSS.conversionToolHidden, name === currentBlock.name); + }); + } + + /** + * Prepare Flipper to be able to leaf tools by arrows/tab + */ + private enableFlipper(): void { + this.flipper = new Flipper({ + focusedItemClass: ConversionToolbar.CSS.conversionToolFocused, + }); + } +} diff --git a/src/components/modules/toolbar/index.ts b/src/components/modules/toolbar/index.ts index ed710ee54..ea8e6f292 100644 --- a/src/components/modules/toolbar/index.ts +++ b/src/components/modules/toolbar/index.ts @@ -1,18 +1,37 @@ import Module from '../../__module'; import $ from '../../dom'; +import * as _ from '../../utils'; +import I18n from '../../i18n'; +import { I18nInternalNS } from '../../i18n/namespace-internal'; +/** + * HTML Elements used for Toolbar UI + */ +interface ToolbarNodes { + wrapper: HTMLElement; + content: HTMLElement; + actions: HTMLElement; + + // Content Zone + plusButton: HTMLElement; + + // Actions Zone + blockActionsButtons: HTMLElement; + settingsToggler: HTMLElement; +} /** * * «Toolbar» is the node that moves up/down over current block * * ______________________________________ Toolbar ____________________________________________ * | | - * | ..................... Content .................... ......... Block Actions .......... | - * | . . . . | - * | . . . [Open Settings] . | - * | . [Plus Button] [Toolbox: {Tool1}, {Tool2}] . . . | - * | . . . [Settings Panel] . | - * | .................................................. .................................. | + * | ..................... Content ......................................................... | + * | . ........ Block Actions ........... | + * | . . [Open Settings] . | + * | . [Plus Button] [Toolbox: {Tool1}, {Tool2}] . . | + * | . . [Settings Panel] . | + * | . .................................. | + * | ....................................................................................... | * | | * |___________________________________________________________________________________________| * @@ -40,7 +59,7 @@ import $ from '../../dom'; * @classdesc Toolbar module * * @typedef {Toolbar} Toolbar - * @property {Object} nodes + * @property {object} nodes - Toolbar nodes * @property {Element} nodes.wrapper - Toolbar main element * @property {Element} nodes.content - Zone with Plus button and toolbox. * @property {Element} nodes.actions - Zone with Block Settings and Remove Button @@ -52,28 +71,13 @@ import $ from '../../dom'; * @property {Element} nodes.pluginSettings - Plugin Settings section of Settings Panel * @property {Element} nodes.defaultSettings - Default Settings section of Settings Panel */ -export default class Toolbar extends Module { - /** - * HTML Elements used for Toolbar UI - */ - public nodes: {[key: string]: HTMLElement} = { - wrapper : null, - content : null, - actions : null, - - // Content Zone - plusButton : null, - - // Actions Zone - blockActionsButtons: null, - settingsToggler : null, - }; - +export default class Toolbar extends Module { /** * CSS styles - * @return {Object} + * + * @returns {object} */ - private static get CSS() { + public get CSS(): { [name: string]: string } { return { toolbar: 'ce-toolbar', content: 'ce-toolbar__content', @@ -84,6 +88,7 @@ export default class Toolbar extends Module { // Content Zone plusButton: 'ce-toolbar__plus', + plusButtonShortcut: 'ce-toolbar__plus-shortcut', plusButtonHidden: 'ce-toolbar__plus--hidden', // Actions Zone @@ -93,94 +98,70 @@ export default class Toolbar extends Module { } /** - * Makes toolbar + * Returns the Toolbar opening state + * + * @returns {boolean} */ - public make(): void { - this.nodes.wrapper = $.make('div', Toolbar.CSS.toolbar); - - /** - * Make Content Zone and Actions Zone - */ - ['content', 'actions'].forEach( (el) => { - this.nodes[el] = $.make('div', Toolbar.CSS[el]); - $.append(this.nodes.wrapper, this.nodes[el]); - }); - - /** - * Fill Content Zone: - * - Plus Button - * - Toolbox - */ - this.nodes.plusButton = $.make('div', Toolbar.CSS.plusButton); - - /** - * Add events to show/hide tooltip for plus button - */ - this.Editor.Listeners.on(this.nodes.plusButton, 'mouseenter', () => { - const tooltip = this.Editor.Toolbox.nodes.tooltip; - const fragment = document.createDocumentFragment(); - - fragment.appendChild(document.createTextNode('Add')); - fragment.appendChild($.make('div', this.Editor.Toolbox.CSS.tooltipShortcut, { - textContent: '⇥ Tab', - })); - - tooltip.style.left = '-17px'; - - tooltip.innerHTML = ''; - tooltip.appendChild(fragment); - tooltip.classList.add(this.Editor.Toolbox.CSS.tooltipShown); - }); - - this.Editor.Listeners.on(this.nodes.plusButton, 'mouseleave', () => { - this.Editor.Toolbox.hideTooltip(); - }); - - $.append(this.nodes.plusButton, $.svg('plus', 14, 14)); - $.append(this.nodes.content, this.nodes.plusButton); - this.Editor.Listeners.on(this.nodes.plusButton, 'click', () => this.plusButtonClicked(), false); - - /** - * Make a Toolbox - */ - this.Editor.Toolbox.make(); - - /** - * Fill Actions Zone: - * - Settings Toggler - * - Remove Block Button - * - Settings Panel - */ - this.nodes.blockActionsButtons = $.make('div', Toolbar.CSS.blockActionsButtons); - this.nodes.settingsToggler = $.make('span', Toolbar.CSS.settingsToggler); - const settingsIcon = $.svg('dots', 18, 4); - - $.append(this.nodes.settingsToggler, settingsIcon); - $.append(this.nodes.blockActionsButtons, this.nodes.settingsToggler); - $.append(this.nodes.actions, this.nodes.blockActionsButtons); + public get opened(): boolean { + return this.nodes.wrapper.classList.contains(this.CSS.toolbarOpened); + } - /** - * Make and append Settings Panel - */ - this.Editor.BlockSettings.make(); - $.append(this.nodes.actions, this.Editor.BlockSettings.nodes.wrapper); + /** + * Plus Button public methods + * + * @returns {{hide: function(): void, show: function(): void}} + */ + public get plusButton(): { hide: () => void; show: () => void } { + return { + hide: (): void => this.nodes.plusButton.classList.add(this.CSS.plusButtonHidden), + show: (): void => { + if (this.Editor.Toolbox.isEmpty) { + return; + } + this.nodes.plusButton.classList.remove(this.CSS.plusButtonHidden); + }, + }; + } - /** - * Append toolbar to the Editor - */ - $.append(this.Editor.UI.nodes.wrapper, this.nodes.wrapper); + /** + * Block actions appearance manipulations + * + * @returns {{hide: function(): void, show: function(): void}} + */ + private get blockActions(): { hide: () => void; show: () => void } { + return { + hide: (): void => { + this.nodes.actions.classList.remove(this.CSS.actionsOpened); + }, + show: (): void => { + this.nodes.actions.classList.add(this.CSS.actionsOpened); + }, + }; + } - /** - * Bind events on the Toolbar elements - */ - this.bindEvents(); + /** + * Toggles read-only mode + * + * @param {boolean} readOnlyEnabled - read-only mode + */ + public toggleReadOnly(readOnlyEnabled: boolean): void { + if (!readOnlyEnabled) { + this.drawUI(); + this.enableModuleBindings(); + } else { + this.destroy(); + this.Editor.Toolbox.destroy(); + this.Editor.BlockSettings.destroy(); + this.disableModuleBindings(); + } } /** * Move Toolbar to the Current Block - * @param {Boolean} forceClose - force close Toolbar Settings and Toolbar + * + * @param {boolean} forceClose - force close Toolbar Settings and Toolbar */ - public move(forceClose: boolean = true): void { + public move(forceClose = true): void { if (forceClose) { /** Close Toolbox when we move toolbar */ this.Editor.Toolbox.close(); @@ -196,22 +177,32 @@ export default class Toolbar extends Module { return; } + const { isMobile } = this.Editor.UI; + const blockHeight = currentBlock.offsetHeight; + let toolbarY = currentBlock.offsetTop; + /** - * Set Toolbar Min Height as Block's height - * Plus Button and Toolbox positioned at the center of the Toolbar + * 1) On desktop — Toolbar at the top of Block, Plus/Toolbox moved the center of Block + * 2) On mobile — Toolbar at the bottom of Block */ - const contentOffset = Math.floor(currentBlock.offsetHeight / 2); + if (!isMobile) { + const contentOffset = Math.floor(blockHeight / 2); + + this.nodes.plusButton.style.transform = `translate3d(0, calc(${contentOffset}px - 50%), 0)`; + this.Editor.Toolbox.nodes.toolbox.style.transform = `translate3d(0, calc(${contentOffset}px - 50%), 0)`; + } else { + toolbarY += blockHeight; + } - this.nodes.plusButton.style.transform = `translate3d(0, calc(${contentOffset}px - 50%), 0)`; - this.Editor.Toolbox.nodes.toolbox.style.transform = `translate3d(0, calc(${contentOffset}px - 50%), 0)`; /** * Move Toolbar to the Top coordinate of Block */ - this.nodes.wrapper.style.transform = `translate3D(0, ${Math.floor(currentBlock.offsetTop)}px, 0)`; + this.nodes.wrapper.style.transform = `translate3D(0, ${Math.floor(toolbarY)}px, 0)`; } /** * Open Toolbar with Plus Button and Actions + * * @param {boolean} withBlockActions - by default, Toolbar opens with Block Actions. * This flag allows to open Toolbar without Actions. * @param {boolean} needToCloseToolbox - by default, Toolbar will be moved with opening @@ -219,32 +210,24 @@ export default class Toolbar extends Module { * with closing Toolbox and Block Settings * This flag allows to open Toolbar with Toolbox */ - public open(withBlockActions: boolean = true, needToCloseToolbox: boolean = true): void { - setTimeout(() => { + public open(withBlockActions = true, needToCloseToolbox = true): void { + _.delay(() => { this.move(needToCloseToolbox); - this.nodes.wrapper.classList.add(Toolbar.CSS.toolbarOpened); + this.nodes.wrapper.classList.add(this.CSS.toolbarOpened); if (withBlockActions) { this.blockActions.show(); } else { this.blockActions.hide(); } - }, 50); - } - - /** - * returns toolbar opened state - * @return {Boolean} - */ - public get opened(): boolean { - return this.nodes.wrapper.classList.contains(Toolbar.CSS.toolbarOpened); + }, 50)(); } /** * Close the Toolbar */ public close(): void { - this.nodes.wrapper.classList.remove(Toolbar.CSS.toolbarOpened); + this.nodes.wrapper.classList.remove(this.CSS.toolbarOpened); /** Close components */ this.blockActions.hide(); @@ -253,53 +236,107 @@ export default class Toolbar extends Module { } /** - * Plus Button public methods - * @return {{hide: function(): void, show: function(): void}} + * Draws Toolbar elements */ - public get plusButton(): {hide: () => void, show: () => void} { - return { - hide: () => this.nodes.plusButton.classList.add(Toolbar.CSS.plusButtonHidden), - show: () => { - if (this.Editor.Toolbox.isEmpty) { - return; - } - this.nodes.plusButton.classList.remove(Toolbar.CSS.plusButtonHidden); - }, - }; - } + private make(): void { + this.nodes.wrapper = $.make('div', this.CSS.toolbar); - /** - * Block actions appearance manipulations - * @return {{hide: function(): void, show: function(): void}} - */ - private get blockActions(): {hide: () => void, show: () => void} { - return { - hide: () => { - this.nodes.actions.classList.remove(Toolbar.CSS.actionsOpened); - }, - show : () => { - this.nodes.actions.classList.add(Toolbar.CSS.actionsOpened); - }, - }; + /** + * Make Content Zone and Actions Zone + */ + ['content', 'actions'].forEach((el) => { + this.nodes[el] = $.make('div', this.CSS[el]); + }); + + /** + * Actions will be included to the toolbar content so we can align in to the right of the content + */ + $.append(this.nodes.wrapper, this.nodes.content); + $.append(this.nodes.content, this.nodes.actions); + + /** + * Fill Content Zone: + * - Plus Button + * - Toolbox + */ + this.nodes.plusButton = $.make('div', this.CSS.plusButton); + $.append(this.nodes.plusButton, $.svg('plus', 14, 14)); + $.append(this.nodes.content, this.nodes.plusButton); + + this.readOnlyMutableListeners.on(this.nodes.plusButton, 'click', () => { + this.plusButtonClicked(); + }, false); + + /** + * Add events to show/hide tooltip for plus button + */ + const tooltipContent = $.make('div'); + + tooltipContent.appendChild(document.createTextNode(I18n.ui(I18nInternalNS.ui.toolbar.toolbox, 'Add'))); + tooltipContent.appendChild($.make('div', this.CSS.plusButtonShortcut, { + textContent: '⇥ Tab', + })); + + this.Editor.Tooltip.onHover(this.nodes.plusButton, tooltipContent); + + /** + * Fill Actions Zone: + * - Settings Toggler + * - Remove Block Button + * - Settings Panel + */ + this.nodes.blockActionsButtons = $.make('div', this.CSS.blockActionsButtons); + this.nodes.settingsToggler = $.make('span', this.CSS.settingsToggler); + const settingsIcon = $.svg('dots', 8, 8); + + $.append(this.nodes.settingsToggler, settingsIcon); + $.append(this.nodes.blockActionsButtons, this.nodes.settingsToggler); + $.append(this.nodes.actions, this.nodes.blockActionsButtons); + + this.Editor.Tooltip.onHover( + this.nodes.settingsToggler, + I18n.ui(I18nInternalNS.ui.blockTunes.toggler, 'Click to tune'), + { + placement: 'top', + } + ); + + /** + * Appending Toolbar components to itself + */ + $.append(this.nodes.content, this.Editor.Toolbox.nodes.toolbox); + $.append(this.nodes.actions, this.Editor.BlockSettings.nodes.wrapper); + + /** + * Append toolbar to the Editor + */ + $.append(this.Editor.UI.nodes.wrapper, this.nodes.wrapper); } /** * Handler for Plus Button - * @param {MouseEvent} event */ private plusButtonClicked(): void { this.Editor.Toolbox.toggle(); } /** - * Bind events on the Toolbar Elements: - * - Block Settings + * Enable bindings */ - private bindEvents(): void { + private enableModuleBindings(): void { /** * Settings toggler */ - this.Editor.Listeners.on(this.nodes.settingsToggler, 'click', () => this.settingsTogglerClicked()); + this.readOnlyMutableListeners.on(this.nodes.settingsToggler, 'click', () => { + this.settingsTogglerClicked(); + }); + } + + /** + * Disable bindings + */ + private disableModuleBindings(): void { + this.readOnlyMutableListeners.clearAll(); } /** @@ -312,4 +349,40 @@ export default class Toolbar extends Module { this.Editor.BlockSettings.open(); } } + + /** + * Draws Toolbar UI + * + * Toolbar contains BlockSettings and Toolbox. + * Thats why at first we draw its components and then Toolbar itself + * + * Steps: + * - Make Toolbar dependent components like BlockSettings, Toolbox and so on + * - Make itself and append dependent nodes to itself + * + */ + private drawUI(): void { + /** + * Make BlockSettings Panel + */ + this.Editor.BlockSettings.make(); + + /** + * Make Toolbox + */ + this.Editor.Toolbox.make(); + + /** + * Make Toolbar + */ + this.make(); + } + + /** + * Removes all created and saved HTMLElements + * It is used in Read-Only mode + */ + private destroy(): void { + this.removeAllNodes(); + } } diff --git a/src/components/modules/toolbar/inline.ts b/src/components/modules/toolbar/inline.ts index 7184f4b52..d8bc83083 100644 --- a/src/components/modules/toolbar/inline.ts +++ b/src/components/modules/toolbar/inline.ts @@ -1,12 +1,29 @@ import Module from '../../__module'; import $ from '../../dom'; - -import BoldInlineTool from '../../inline-tools/inline-tool-bold'; -import ItalicInlineTool from '../../inline-tools/inline-tool-italic'; -import LinkInlineTool from '../../inline-tools/inline-tool-link'; import SelectionUtils from '../../selection'; -import _ from '../../utils'; -import {InlineTool, InlineToolConstructable, ToolConstructable, ToolSettings} from '../../../../types'; +import * as _ from '../../utils'; +import { InlineTool, InlineToolConstructable, ToolConstructable, ToolSettings } from '../../../../types'; +import Flipper from '../../flipper'; +import I18n from '../../i18n'; +import { I18nInternalNS } from '../../i18n/namespace-internal'; +import Shortcuts from '../../utils/shortcuts'; +import { EditorModules } from '../../../types-internal/editor-modules'; + +/** + * Inline Toolbar elements + */ +interface InlineToolbarNodes { + wrapper: HTMLElement; + togglerAndButtonsWrapper: HTMLElement; + buttons: HTMLElement; + conversionToggler: HTMLElement; + conversionTogglerContent: HTMLElement; + /** + * Zone below the buttons where Tools can create additional actions by 'renderActions()' method + * For example, input for the 'link' tool or textarea for the 'comment' tool + */ + actions: HTMLElement; +} /** * Inline toolbar with actions that modifies selected text fragment @@ -15,88 +32,107 @@ import {InlineTool, InlineToolConstructable, ToolConstructable, ToolSettings} fr * | B i [link] [mark] | * |________________________| */ -export default class InlineToolbar extends Module { - +export default class InlineToolbar extends Module { /** * CSS styles */ public CSS = { inlineToolbar: 'ce-inline-toolbar', inlineToolbarShowed: 'ce-inline-toolbar--showed', + inlineToolbarLeftOriented: 'ce-inline-toolbar--left-oriented', + inlineToolbarRightOriented: 'ce-inline-toolbar--right-oriented', + inlineToolbarShortcut: 'ce-inline-toolbar__shortcut', buttonsWrapper: 'ce-inline-toolbar__buttons', actionsWrapper: 'ce-inline-toolbar__actions', inlineToolButton: 'ce-inline-tool', - inlineToolButtonLast: 'ce-inline-tool--last', inputField: 'cdx-input', + focusedButton: 'ce-inline-tool--focused', + conversionToggler: 'ce-inline-toolbar__dropdown', + conversionTogglerHidden: 'ce-inline-toolbar__dropdown--hidden', + conversionTogglerContent: 'ce-inline-toolbar__dropdown-content', + togglerAndButtonsWrapper: 'ce-inline-toolbar__toggler-and-button-wrapper', }; /** - * Inline Toolbar elements + * State of inline toolbar + * + * @type {boolean} */ - private nodes: { wrapper: HTMLElement, buttons: HTMLElement, actions: HTMLElement } = { - wrapper: null, - buttons: null, - /** - * Zone below the buttons where Tools can create additional actions by 'renderActions()' method - * For example, input for the 'link' tool or textarea for the 'comment' tool - */ - actions: null, - }; + public opened = false; /** * Margin above/below the Toolbar */ - private readonly toolbarVerticalMargin: number = 20; + private readonly toolbarVerticalMargin: number = 5; /** - * Tools instances + * Currently visible tools instances */ private toolsInstances: Map; /** - * Inline Toolbar Tools + * Buttons List * - * @returns Map + * @type {NodeList} */ - get tools(): Map { - if (!this.toolsInstances || this.toolsInstances.size === 0) { - const allTools = this.inlineTools; + private buttonsList: NodeList = null; - this.toolsInstances = new Map(); - for (const tool in allTools) { - if (allTools.hasOwnProperty(tool)) { - this.toolsInstances.set(tool, allTools[tool]); - } - } - } + /** + * Cache for Inline Toolbar width + * + * @type {number} + */ + private width = 0; - return this.toolsInstances; - } + /** + * Instance of class that responses for leafing buttons by arrows/tab + */ + private flipper: Flipper = null; /** - * Making DOM + * Internal inline tools: Link, Bold, Italic */ - public make() { - this.nodes.wrapper = $.make('div', this.CSS.inlineToolbar); - this.nodes.buttons = $.make('div', this.CSS.buttonsWrapper); - this.nodes.actions = $.make('div', this.CSS.actionsWrapper); + private internalTools: {[name: string]: InlineToolConstructable} = {}; - // To prevent reset of a selection when click on the wrapper - this.Editor.Listeners.on(this.nodes.wrapper, 'mousedown', (event) => { - event.preventDefault(); - }); + /** + * Editor modules setter + * + * @param {EditorModules} Editor - Editor's Modules + */ + public set state(Editor: EditorModules) { + this.Editor = Editor; - /** - * Append Inline Toolbar to the Editor - */ - $.append(this.nodes.wrapper, [this.nodes.buttons, this.nodes.actions]); - $.append(this.Editor.UI.nodes.wrapper, this.nodes.wrapper); + const { Tools } = Editor; /** - * Append Inline Toolbar Tools + * Set internal inline tools */ - this.addTools(); + Object + .entries(Tools.internalTools) + .filter(([, toolClass]: [string, ToolConstructable | ToolSettings]) => { + if (_.isFunction(toolClass)) { + return toolClass[Tools.INTERNAL_SETTINGS.IS_INLINE]; + } + return (toolClass as ToolSettings).class[Tools.INTERNAL_SETTINGS.IS_INLINE]; + }) + .map(([name, toolClass]: [string, InlineToolConstructable | ToolSettings]) => { + this.internalTools[name] = _.isFunction(toolClass) ? toolClass : (toolClass as ToolSettings).class; + }); + } + + /** + * Toggles read-only mode + * + * @param {boolean} readOnlyEnabled - read-only mode + */ + public toggleReadOnly(readOnlyEnabled: boolean): void { + if (!readOnlyEnabled) { + this.make(); + } else { + this.destroy(); + this.Editor.ConversionToolbar.destroy(); + } } /** @@ -105,23 +141,23 @@ export default class InlineToolbar extends Module { */ /** - * Shows Inline Toolbar by keyup/mouseup - * @param {KeyboardEvent|MouseEvent} event + * Shows Inline Toolbar if something is selected + * + * @param {boolean} [needToClose] - pass true to close toolbar if it is not allowed. + * Avoid to use it just for closing IT, better call .close() clearly. */ - public handleShowingEvent(event): void { + public tryToShow(needToClose = false): void { if (!this.allowedToShow()) { - this.close(); + if (needToClose) { + this.close(); + } + return; } this.move(); this.open(); - - /** Check Tools state for selected fragment */ - this.checkToolsState(); - - /** Clear selection */ - this.Editor.BlockSelection.clearSelection(); + this.Editor.Toolbar.close(); } /** @@ -132,11 +168,11 @@ export default class InlineToolbar extends Module { const wrapperOffset = this.Editor.UI.nodes.wrapper.getBoundingClientRect(); const newCoords = { x: selectionRect.x - wrapperOffset.left, - y: selectionRect.y - + selectionRect.height + y: selectionRect.y + + selectionRect.height - // + window.scrollY - - wrapperOffset.top - + this.toolbarVerticalMargin, + wrapperOffset.top + + this.toolbarVerticalMargin, }; /** @@ -146,6 +182,26 @@ export default class InlineToolbar extends Module { newCoords.x += Math.floor(selectionRect.width / 2); } + /** + * Inline Toolbar has -50% translateX, so we need to check real coords to prevent overflowing + */ + const realLeftCoord = newCoords.x - this.width / 2; + const realRightCoord = newCoords.x + this.width / 2; + + /** + * By default, Inline Toolbar has top-corner at the center + * We are adding a modifiers for to move corner to the left or right + */ + this.nodes.wrapper.classList.toggle( + this.CSS.inlineToolbarLeftOriented, + realLeftCoord < this.Editor.UI.contentRect.left + ); + + this.nodes.wrapper.classList.toggle( + this.CSS.inlineToolbarRightOriented, + realRightCoord > this.Editor.UI.contentRect.right + ); + this.nodes.wrapper.style.left = Math.floor(newCoords.x) + 'px'; this.nodes.wrapper.style.top = Math.floor(newCoords.y) + 'px'; } @@ -154,36 +210,239 @@ export default class InlineToolbar extends Module { * Hides Inline Toolbar */ public close(): void { + if (!this.opened) { + return; + } + + if (this.Editor.ReadOnly.isEnabled) { + return; + } + this.nodes.wrapper.classList.remove(this.CSS.inlineToolbarShowed); - this.tools.forEach((toolInstance) => { - if (typeof toolInstance.clear === 'function') { + Array.from(this.toolsInstances.entries()).forEach(([name, toolInstance]) => { + const shortcut = this.getToolShortcut(name); + + if (shortcut) { + Shortcuts.remove(this.Editor.UI.nodes.redactor, shortcut); + } + + /** + * @todo replace 'clear' with 'destroy' + */ + if (_.isFunction(toolInstance.clear)) { toolInstance.clear(); } }); + + this.opened = false; + + this.flipper.deactivate(); + this.Editor.ConversionToolbar.close(); } /** * Shows Inline Toolbar */ - private open(): void { + public open(): void { + if (this.opened) { + return; + } /** * Filter inline-tools and show only allowed by Block's Tool */ - this.filterTools(); + this.addToolsFiltered(); /** * Show Inline Toolbar */ this.nodes.wrapper.classList.add(this.CSS.inlineToolbarShowed); + this.buttonsList = this.nodes.buttons.querySelectorAll(`.${this.CSS.inlineToolButton}`); + this.opened = true; + + if (this.Editor.ConversionToolbar.hasTools()) { + /** + * Change Conversion Dropdown content for current tool + */ + this.setConversionTogglerContent(); + } else { + /** + * hide Conversion Dropdown with there are no tools + */ + this.nodes.conversionToggler.hidden = true; + } + /** - * Call 'clear' method for Inline Tools (for example, 'link' want to clear input) + * Get currently visible buttons to pass it to the Flipper */ - this.tools.forEach((toolInstance: InlineTool) => { - if (typeof toolInstance.clear === 'function') { - toolInstance.clear(); + let visibleTools = Array.from(this.buttonsList); + + visibleTools.unshift(this.nodes.conversionToggler); + visibleTools = visibleTools.filter((tool) => !(tool as HTMLElement).hidden); + + this.flipper.activate(visibleTools as HTMLElement[]); + } + + /** + * Check if node is contained by Inline Toolbar + * + * @param {Node} node — node to chcek + */ + public containsNode(node: Node): boolean { + return this.nodes.wrapper.contains(node); + } + + /** + * Removes UI and its components + */ + public destroy(): void { + /** + * Sometimes (in read-only mode) there is no Flipper + */ + if (this.flipper) { + this.flipper.deactivate(); + this.flipper = null; + } + + this.removeAllNodes(); + } + + /** + * Returns inline toolbar settings for a particular tool + * + * @param {string} toolName - user specified name of tool + * @returns {string[] | boolean} array of ordered tool names or false + */ + private getInlineToolbarSettings(toolName): string[] | boolean { + const toolSettings = this.Editor.Tools.getToolSettings(toolName); + + /** + * InlineToolbar property of a particular tool + */ + const settingsForTool = toolSettings[this.Editor.Tools.USER_SETTINGS.ENABLED_INLINE_TOOLS]; + + /** + * Whether to enable IT for a particular tool is the decision of the editor user. + * He can enable it by the inlineToolbar settings for this tool. To enable, he should pass true or strings[] + */ + const enabledForTool = settingsForTool === true || Array.isArray(settingsForTool); + + /** + * Disabled by user + */ + if (!enabledForTool) { + return false; + } + + /** + * 1st priority. + * + * If user pass the list of inline tools for the particular tool, return it. + */ + if (Array.isArray(settingsForTool)) { + return settingsForTool; + } + + /** + * 2nd priority. + * + * If user pass just 'true' for tool, get common inlineToolbar settings + * - if common settings is an array, use it + * - if common settings is 'true' or not specified, get default order + */ + + /** + * Common inlineToolbar settings got from the root of EditorConfig + */ + const commonInlineToolbarSettings = this.config.inlineToolbar; + + /** + * If common settings is an array, use it + */ + if (Array.isArray(commonInlineToolbarSettings)) { + return commonInlineToolbarSettings; + } + + /** + * If common settings is 'true' or not specified (will be set as true at core.ts), get the default order + */ + if (commonInlineToolbarSettings === true) { + const defaultToolsOrder: string[] = Object.entries(this.Editor.Tools.available) + .filter(([name, tool]) => { + return tool[this.Editor.Tools.INTERNAL_SETTINGS.IS_INLINE]; + }) + .map(([name, tool]) => { + return name; + }); + + return defaultToolsOrder; + } + + return false; + } + + /** + * Making DOM + */ + private make(): void { + this.nodes.wrapper = $.make('div', [ + this.CSS.inlineToolbar, + ...(this.isRtl ? [ this.Editor.UI.CSS.editorRtlFix ] : []), + ]); + /** + * Creates a different wrapper for toggler and buttons. + */ + this.nodes.togglerAndButtonsWrapper = $.make('div', this.CSS.togglerAndButtonsWrapper); + this.nodes.buttons = $.make('div', this.CSS.buttonsWrapper); + this.nodes.actions = $.make('div', this.CSS.actionsWrapper); + + // To prevent reset of a selection when click on the wrapper + this.listeners.on(this.nodes.wrapper, 'mousedown', (event) => { + const isClickedOnActionsWrapper = (event.target as Element).closest(`.${this.CSS.actionsWrapper}`); + + // If click is on actions wrapper, + // do not prevent default behaviour because actions might include interactive elements + if (!isClickedOnActionsWrapper) { + event.preventDefault(); } }); + + /** + * Append the intermediary wrapper which contains toggler and buttons and button actions. + */ + $.append(this.nodes.wrapper, [this.nodes.togglerAndButtonsWrapper, this.nodes.actions]); + /** + * Append the inline toolbar to the editor. + */ + $.append(this.Editor.UI.nodes.wrapper, this.nodes.wrapper); + + /** + * Add button that will allow switching block type + */ + this.addConversionToggler(); + + /** + * Wrapper for the inline tools + * Will be appended after the Conversion Toolbar toggler + */ + $.append(this.nodes.togglerAndButtonsWrapper, this.nodes.buttons); + + /** + * Prepare conversion toolbar. + * If it has any conversion tool then it will be enabled in the Inline Toolbar + */ + this.prepareConversionToolbar(); + + /** + * Recalculate initial width with all buttons + */ + this.recalculateWidth(); + + /** + * Allow to leaf buttons by arrows / tab + * Buttons will be filled on opening + */ + this.enableFlipper(); } /** @@ -208,7 +467,9 @@ export default class InlineToolbar extends Module { return false; } - const target = currentSelection.anchorNode.parentElement; + const target = !$.isElement(currentSelection.anchorNode) + ? currentSelection.anchorNode.parentElement + : currentSelection.anchorNode; if (currentSelection && tagsConflictsWithSelection.includes(target.tagName)) { return false; @@ -216,6 +477,7 @@ export default class InlineToolbar extends Module { // The selection of the element only in contenteditable const contenteditable = target.closest('[contenteditable="true"]'); + if (contenteditable === null) { return false; } @@ -227,53 +489,99 @@ export default class InlineToolbar extends Module { return false; } - const toolSettings = this.Editor.Tools.getToolSettings(currentBlock.name); + /** + * getInlineToolbarSettings could return an string[] (order of tools) or false (Inline Toolbar disabled). + */ + const inlineToolbarSettings = this.getInlineToolbarSettings(currentBlock.name); - return toolSettings && toolSettings[this.Editor.Tools.apiSettings.IS_ENABLED_INLINE_TOOLBAR]; + return inlineToolbarSettings !== false; } /** - * Show only allowed Tools + * Recalculate inline toolbar width */ - private filterTools(): void { - const currentSelection = SelectionUtils.get(), - currentBlock = this.Editor.BlockManager.getBlock(currentSelection.anchorNode as HTMLElement); + private recalculateWidth(): void { + this.width = this.nodes.wrapper.offsetWidth; + } - const toolSettings = this.Editor.Tools.getToolSettings(currentBlock.name), - inlineToolbarSettings = toolSettings && toolSettings[this.Editor.Tools.apiSettings.IS_ENABLED_INLINE_TOOLBAR]; + /** + * Create a toggler for Conversion Dropdown + * and prepend it to the buttons list + */ + private addConversionToggler(): void { + this.nodes.conversionToggler = $.make('div', this.CSS.conversionToggler); + this.nodes.conversionTogglerContent = $.make('div', this.CSS.conversionTogglerContent); - /** - * All Inline Toolbar buttons - * @type {HTMLElement[]} - */ - const buttons = Array.from(this.nodes.buttons.querySelectorAll(`.${this.CSS.inlineToolButton}`)) as HTMLElement[]; + const icon = $.svg('toggler-down', 13, 13); - /** - * Show previously hided - */ - buttons.forEach((button) => { - button.hidden = false; - button.classList.remove(this.CSS.inlineToolButtonLast); + this.nodes.conversionToggler.appendChild(this.nodes.conversionTogglerContent); + this.nodes.conversionToggler.appendChild(icon); + + this.nodes.togglerAndButtonsWrapper.appendChild(this.nodes.conversionToggler); + + this.listeners.on(this.nodes.conversionToggler, 'click', () => { + this.Editor.ConversionToolbar.toggle((conversionToolbarOpened) => { + /** + * When ConversionToolbar is opening on activated InlineToolbar flipper + * Then we need to temporarily deactivate InlineToolbar flipper so that we could flip ConversionToolbar items + * + * Other case when ConversionToolbar is closing (for example, by escape) but we need to continue flipping + * InlineToolbar items, we activate InlineToolbar flipper + */ + const canActivateInlineToolbarFlipper = !conversionToolbarOpened && this.opened; + + if (canActivateInlineToolbarFlipper) { + this.flipper.activate(); + } else if (this.opened) { + this.flipper.deactivate(); + } + }); }); + this.Editor.Tooltip.onHover(this.nodes.conversionToggler, I18n.ui(I18nInternalNS.ui.inlineToolbar.converter, 'Convert to'), { + placement: 'top', + hidingDelay: 100, + }); + } + + /** + * Changes Conversion Dropdown content for current block's Tool + */ + private setConversionTogglerContent(): void { + const { BlockManager, Tools } = this.Editor; + const toolName = BlockManager.currentBlock.name; + /** - * Filter buttons if Block Tool pass config like inlineToolbar=['link'] + * If tool does not provide 'export' rule, hide conversion dropdown */ - if (Array.isArray(inlineToolbarSettings)) { - buttons.forEach((button) => { - button.hidden = !inlineToolbarSettings.includes(button.dataset.tool); - }); - } + const conversionConfig = Tools.available[toolName][Tools.INTERNAL_SETTINGS.CONVERSION_CONFIG] || {}; + const exportRuleDefined = conversionConfig && conversionConfig.export; + + this.nodes.conversionToggler.hidden = !exportRuleDefined; + this.nodes.conversionToggler.classList.toggle(this.CSS.conversionTogglerHidden, !exportRuleDefined); /** - * Tick for removing right-margin from last visible button. - * Current generation of CSS does not allow to filter :visible elements + * Get icon or title for dropdown */ - const lastVisibleButton = buttons.filter((button) => !button.hidden).pop(); + const toolSettings = Tools.getToolSettings(toolName); + const toolboxSettings = Tools.available[toolName][Tools.INTERNAL_SETTINGS.TOOLBOX] || {}; + const userToolboxSettings = toolSettings.toolbox || {}; + + this.nodes.conversionTogglerContent.innerHTML = + userToolboxSettings.icon || + toolboxSettings.icon || + userToolboxSettings.title || + toolboxSettings.title || + _.capitalize(toolName); + } - if (lastVisibleButton) { - lastVisibleButton.classList.add(this.CSS.inlineToolButtonLast); - } + /** + * Makes the Conversion Dropdown + */ + private prepareConversionToolbar(): void { + const ct = this.Editor.ConversionToolbar.make(); + + $.append(this.nodes.wrapper, ct); } /** @@ -282,90 +590,146 @@ export default class InlineToolbar extends Module { */ /** - * Fill Inline Toolbar with Tools + * Append only allowed Tools */ - private addTools(): void { - this.tools.forEach((toolInstance, toolName) => { - this.addTool(toolName, toolInstance); + private addToolsFiltered(): void { + const currentSelection = SelectionUtils.get(); + const currentBlock = this.Editor.BlockManager.getBlock(currentSelection.anchorNode as HTMLElement); + + /** + * Clear buttons list + */ + this.nodes.buttons.innerHTML = ''; + this.nodes.actions.innerHTML = ''; + this.toolsInstances = new Map(); + + /** + * Filter buttons if Block Tool pass config like inlineToolbar=['link'] + * Else filter them according to the default inlineToolbar property. + * + * For this moment, inlineToolbarOrder could not be 'false' + * because this method will be called only if the Inline Toolbar is enabled + */ + const inlineToolbarOrder = this.getInlineToolbarSettings(currentBlock.name) as string[]; + + inlineToolbarOrder.forEach((toolName) => { + const toolSettings = this.Editor.Tools.getToolSettings(toolName); + const tool = this.Editor.Tools.constructInline(this.Editor.Tools.inline[toolName], toolName, toolSettings); + + this.addTool(toolName, tool); + tool.checkState(SelectionUtils.get()); }); + + /** + * Recalculate width because some buttons can be hidden + */ + this.recalculateWidth(); } /** * Add tool button and activate clicks + * + * @param {string} toolName - name of Tool to add + * @param {InlineTool} tool - Tool class instance */ private addTool(toolName: string, tool: InlineTool): void { const { - Listeners, Tools, + Tooltip, } = this.Editor; const button = tool.render(); if (!button) { _.log('Render method must return an instance of Node', 'warn', toolName); + return; } button.dataset.tool = toolName; this.nodes.buttons.appendChild(button); + this.toolsInstances.set(toolName, tool); - if (typeof tool.renderActions === 'function') { + if (_.isFunction(tool.renderActions)) { const actions = tool.renderActions(); + this.nodes.actions.appendChild(actions); } - Listeners.on(button, 'click', (event) => { + this.listeners.on(button, 'click', (event) => { this.toolClicked(tool); event.preventDefault(); }); + const shortcut = this.getToolShortcut(toolName); + + if (shortcut) { + this.enableShortcuts(tool, shortcut); + } + /** - * Enable shortcuts - * Ignore tool that doesn't have shortcut or empty string + * Enable tooltip module on button */ - const toolSettings = Tools.getToolSettings(toolName); + const tooltipContent = $.make('div'); + const toolTitle = I18n.t( + I18nInternalNS.toolNames, + Tools.toolsClasses[toolName][Tools.INTERNAL_SETTINGS.TITLE] || _.capitalize(toolName) + ); + + tooltipContent.appendChild($.text(toolTitle)); + + if (shortcut) { + tooltipContent.appendChild($.make('div', this.CSS.inlineToolbarShortcut, { + textContent: _.beautifyShortcut(shortcut), + })); + } - let shortcut = null; + Tooltip.onHover(button, tooltipContent, { + placement: 'top', + hidingDelay: 100, + }); + } + + /** + * Get shortcut name for tool + * + * @param toolName — Tool name + */ + private getToolShortcut(toolName): string | void { + const { Tools } = this.Editor; /** - * Get internal inline tools + * Enable shortcuts + * Ignore tool that doesn't have shortcut or empty string */ - const internalTools: string[] = Object - .entries(Tools.internalTools) - .filter(([name, toolClass]: [string, ToolConstructable | ToolSettings]) => { - if (_.isFunction(toolClass)) { - return toolClass[Tools.apiSettings.IS_INLINE]; - } - - return (toolClass as ToolSettings).class[Tools.apiSettings.IS_INLINE]; - }) - .map(([name]: [string, InlineToolConstructable | ToolSettings]) => name); + const toolSettings = Tools.getToolSettings(toolName); + const tool = this.toolsInstances.get(toolName); /** * 1) For internal tools, check public getter 'shortcut' * 2) For external tools, check tool's settings + * 3) If shortcut is not set in settings, check Tool's public property */ - if (internalTools.includes(toolName)) { - shortcut = this.inlineTools[toolName].shortcut; - } else if (toolSettings && toolSettings[Tools.apiSettings.SHORTCUT]) { - shortcut = toolSettings[Tools.apiSettings.SHORTCUT]; - } - - if (shortcut) { - this.enableShortcuts(tool, shortcut); + if (Object.keys(this.internalTools).includes(toolName)) { + return this.inlineTools[toolName][Tools.INTERNAL_SETTINGS.SHORTCUT]; + } else if (toolSettings && toolSettings[Tools.USER_SETTINGS.SHORTCUT]) { + return toolSettings[Tools.USER_SETTINGS.SHORTCUT]; + } else if (tool.shortcut) { + return tool.shortcut; } } /** * Enable Tool shortcut with Editor Shortcuts Module + * * @param {InlineTool} tool - Tool instance * @param {string} shortcut - shortcut according to the ShortcutData Module format */ private enableShortcuts(tool: InlineTool, shortcut: string): void { - this.Editor.Shortcuts.add({ + Shortcuts.add({ name: shortcut, handler: (event) => { - const {currentBlock} = this.Editor.BlockManager; + const { currentBlock } = this.Editor.BlockManager; /** * Editor is not focused @@ -379,22 +743,24 @@ export default class InlineToolbar extends Module { * it can be used by tools like «Mention» that works without selection: * Example: by SHIFT+@ show dropdown and insert selected username */ - // if (SelectionUtils.isCollapsed) return; + // if (SelectionUtils.isCollapsed) return; const toolSettings = this.Editor.Tools.getToolSettings(currentBlock.name); - if (!toolSettings || !toolSettings[this.Editor.Tools.apiSettings.IS_ENABLED_INLINE_TOOLBAR]) { + if (!toolSettings || !toolSettings[this.Editor.Tools.USER_SETTINGS.ENABLED_INLINE_TOOLS]) { return; } event.preventDefault(); this.toolClicked(tool); }, + on: this.Editor.UI.nodes.redactor, }); } /** * Inline Tool button clicks + * * @param {InlineTool} tool - Tool's instance */ private toolClicked(tool: InlineTool): void { @@ -408,7 +774,7 @@ export default class InlineToolbar extends Module { * Check Tools` state by selection */ private checkToolsState(): void { - this.tools.forEach((toolInstance) => { + this.toolsInstances.forEach((toolInstance) => { toolInstance.checkState(SelectionUtils.get()); }); } @@ -421,13 +787,24 @@ export default class InlineToolbar extends Module { const result = {}; for (const tool in this.Editor.Tools.inline) { - if (this.Editor.Tools.inline.hasOwnProperty(tool)) { + if (Object.prototype.hasOwnProperty.call(this.Editor.Tools.inline, tool)) { const toolSettings = this.Editor.Tools.getToolSettings(tool); - result[tool] = this.Editor.Tools.constructInline(this.Editor.Tools.inline[tool], toolSettings); + result[tool] = this.Editor.Tools.constructInline(this.Editor.Tools.inline[tool], tool, toolSettings); } } return result; } + + /** + * Allow to leaf buttons by arrows / tab + * Buttons will be filled on opening + */ + private enableFlipper(): void { + this.flipper = new Flipper({ + focusedItemClass: this.CSS.focusedButton, + allowArrows: false, + }); + } } diff --git a/src/components/modules/toolbar/toolbox.ts b/src/components/modules/toolbar/toolbox.ts index 134f8bef3..add3e9e73 100644 --- a/src/components/modules/toolbar/toolbox.ts +++ b/src/components/modules/toolbar/toolbox.ts @@ -1,115 +1,119 @@ import Module from '../../__module'; import $ from '../../dom'; -import _ from '../../utils'; -import {BlockToolConstructable, ToolboxConfig} from '../../../../types'; +import * as _ from '../../utils'; +import { BlockToolConstructable, ToolConstructable } from '../../../../types'; +import Flipper from '../../flipper'; +import { BlockToolAPI } from '../../block'; +import I18n from '../../i18n'; +import { I18nInternalNS } from '../../i18n/namespace-internal'; +import Shortcuts from '../../utils/shortcuts'; + +/** + * HTMLElements used for Toolbox UI + */ +interface ToolboxNodes { + toolbox: HTMLElement; + buttons: HTMLElement[]; +} /** * @class Toolbox * @classdesc Holder for Tools * * @typedef {Toolbox} Toolbox - * @property {Boolean} opened - opening state - * @property {Object} nodes - Toolbox nodes - * @property {Object} CSS - CSS class names + * @property {boolean} opened - opening state + * @property {object} nodes - Toolbox nodes + * @property {object} CSS - CSS class names * */ -export default class Toolbox extends Module { +export default class Toolbox extends Module { + /** + * Current module HTML Elements + */ + public nodes = { + toolbox: null, + buttons: [], + } /** * CSS styles - * @return {{toolbox: string, toolboxButton string, toolboxButtonActive: string, - * toolboxOpened: string, tooltip: string, tooltipShown: string, tooltipShortcut: string}} + * + * @returns {object.} */ - get CSS() { - return { + public get CSS(): {[name: string]: string} { + return { toolbox: 'ce-toolbox', toolboxButton: 'ce-toolbox__button', - toolboxButtonActive : 'ce-toolbox__button--active', + toolboxButtonActive: 'ce-toolbox__button--active', toolboxOpened: 'ce-toolbox--opened', - tooltip: 'ce-toolbox__tooltip', - tooltipShown: 'ce-toolbox__tooltip--shown', - tooltipShortcut: 'ce-toolbox__tooltip-shortcut', openedToolbarHolderModifier: 'codex-editor--toolbox-opened', - }; - } - - /** - * get tool name when it is selected - * In case when nothing selected returns null - * - * @return {String|null} - */ - public get getActiveTool(): string { - const childNodes = this.nodes.toolbox.childNodes; - - if (this.activeButtonIndex === -1) { - return null; - } - return (childNodes[this.activeButtonIndex] as HTMLElement).dataset.tool; + buttonTooltip: 'ce-toolbox-button-tooltip', + buttonShortcut: 'ce-toolbox-button-tooltip__shortcut', + }; } /** * Returns True if Toolbox is Empty and nothing to show - * @return {boolean} + * + * @returns {boolean} */ public get isEmpty(): boolean { return this.displayedToolsCount === 0; } - private static LEAF_DIRECTIONS = { - RIGHT: 'right', - LEFT: 'left', - }; - /** * Opening state + * * @type {boolean} */ - public opened: boolean = false; + public opened = false; /** - * HTMLElements used for Toolbox UI - */ - public nodes: { - toolbox: HTMLElement, - tooltip: HTMLElement, - buttons: HTMLElement[], - } = { - toolbox: null, - tooltip: null, - buttons: [], - }; - - /** - * Active button index - * -1 equals no chosen Tool + * How many tools displayed in Toolbox + * * @type {number} */ - private activeButtonIndex: number = -1; + private displayedToolsCount = 0; /** - * How many tools displayed in Toolbox - * @type {number} + * Instance of class that responses for leafing buttons by arrows/tab + * + * @type {Flipper|null} */ - private displayedToolsCount: number = 0; + private flipper: Flipper = null; /** * Makes the Toolbox */ public make(): void { this.nodes.toolbox = $.make('div', this.CSS.toolbox); - $.append(this.Editor.Toolbar.nodes.content, this.nodes.toolbox); this.addTools(); - this.addTooltip(); + this.enableFlipper(); + } + + /** + * Destroy Module + */ + public destroy(): void { + /** + * Sometimes (in read-only mode) there is no Flipper + */ + if (this.flipper) { + this.flipper.deactivate(); + this.flipper = null; + } + + this.removeAllNodes(); + this.removeAllShortcuts(); } /** * Toolbox Tool's button click handler * - * @param {MouseEvent|KeyboardEvent} event - * @param {string} toolName + * @param {MouseEvent|KeyboardEvent} event - event that activates toolbox button + * @param {string} toolName - button to activate */ public toolButtonActivate(event: MouseEvent|KeyboardEvent, toolName: string): void { const tool = this.Editor.Tools.toolsClasses[toolName] as BlockToolConstructable; @@ -129,26 +133,18 @@ export default class Toolbox extends Module { this.nodes.toolbox.classList.add(this.CSS.toolboxOpened); this.opened = true; + this.flipper.activate(); } /** * Close Toolbox */ public close(): void { - this.hideTooltip(); - this.nodes.toolbox.classList.remove(this.CSS.toolboxOpened); this.Editor.UI.nodes.wrapper.classList.remove(this.CSS.openedToolbarHolderModifier); this.opened = false; - - /** remove active item pointer */ - this.activeButtonIndex = -1; - const activeButton = this.nodes.toolbox.querySelector(`.${this.CSS.toolboxButtonActive}`); - - if (activeButton) { - activeButton.classList.remove(this.CSS.toolboxButtonActive); - } + this.flipper.deactivate(); } /** @@ -162,72 +158,6 @@ export default class Toolbox extends Module { } } - /** - * Leaf - * flip through the toolbox items - * @param {String} direction - leaf direction, right is default - */ - public leaf(direction: string = Toolbox.LEAF_DIRECTIONS.RIGHT): void { - const childNodes = this.nodes.toolbox.childNodes; - - /** - * If activeButtonIndex === -1 then we have no chosen Tool in Toolbox - */ - if (this.activeButtonIndex === -1) { - /** - * Normalize "previous" Tool index depending on direction. - * We need to do this to highlight "first" Tool correctly - * - * Order of Tools: [0] [1] ... [n - 1] - * [0 = n] because of: n % n = 0 % n - * - * Direction 'right': for [0] the [n - 1] is a previous index - * [n - 1] -> [0] - * - * Direction 'left': for [n - 1] the [0] is a previous index - * [n - 1] <- [0] - * - * @type {number} - */ - this.activeButtonIndex = direction === Toolbox.LEAF_DIRECTIONS.RIGHT ? -1 : 0; - } else { - /** - * If we have chosen Tool then remove highlighting - */ - (childNodes[this.activeButtonIndex] as HTMLElement).classList.remove(this.CSS.toolboxButtonActive); - } - - /** - * Count index for next Tool - */ - if (direction === Toolbox.LEAF_DIRECTIONS.RIGHT) { - /** - * If we go right then choose next (+1) Tool - * @type {number} - */ - this.activeButtonIndex = (this.activeButtonIndex + 1) % childNodes.length; - } else { - /** - * If we go left then choose previous (-1) Tool - * Before counting module we need to add length before because of "The JavaScript Modulo Bug" - * @type {number} - */ - this.activeButtonIndex = (childNodes.length + this.activeButtonIndex - 1) % childNodes.length; - } - - /** - * Highlight new chosen Tool - */ - (childNodes[this.activeButtonIndex] as HTMLElement).classList.add(this.CSS.toolboxButtonActive); - } - - /** - * Hide toolbox tooltip - */ - public hideTooltip(): void { - this.nodes.tooltip.classList.remove(this.CSS.tooltipShown); - } - /** * Iterates available tools and appends them to the Toolbox */ @@ -235,8 +165,8 @@ export default class Toolbox extends Module { const tools = this.Editor.Tools.available; for (const toolName in tools) { - if (tools.hasOwnProperty(toolName)) { - this.addTool(toolName, tools[toolName] as BlockToolConstructable); + if (Object.prototype.hasOwnProperty.call(tools, toolName)) { + this.addTool(toolName, tools[toolName] as BlockToolConstructable); } } } @@ -248,9 +178,10 @@ export default class Toolbox extends Module { * @param {BlockToolConstructable} tool - tool class */ private addTool(toolName: string, tool: BlockToolConstructable): void { - const api = this.Editor.Tools.apiSettings; + const internalSettings = this.Editor.Tools.INTERNAL_SETTINGS; + const userSettings = this.Editor.Tools.USER_SETTINGS; - const toolToolboxSettings = tool[api.TOOLBOX]; + const toolToolboxSettings = tool[internalSettings.TOOLBOX]; /** * Skip tools that don't pass 'toolbox' property @@ -261,6 +192,7 @@ export default class Toolbox extends Module { if (toolToolboxSettings && !toolToolboxSettings.icon) { _.log('Toolbar icon is missed. Tool %o skipped', 'warn', toolName); + return; } @@ -272,12 +204,19 @@ export default class Toolbox extends Module { // return; // } - const {toolbox: userToolboxSettings = {} as ToolboxConfig} = this.Editor.Tools.getToolSettings(toolName); + const userToolboxSettings = this.Editor.Tools.getToolSettings(toolName)[userSettings.TOOLBOX]; + + /** + * Hide Toolbox button if Toolbox settings is false + */ + if ((userToolboxSettings ?? toolToolboxSettings) === false) { + return; + } const button = $.make('li', [ this.CSS.toolboxButton ]); button.dataset.tool = toolName; - button.innerHTML = userToolboxSettings.icon || toolToolboxSettings.icon; + button.innerHTML = (userToolboxSettings && userToolboxSettings.icon) || toolToolboxSettings.icon; $.append(this.nodes.toolbox, button); @@ -287,28 +226,24 @@ export default class Toolbox extends Module { /** * Add click listener */ - this.Editor.Listeners.on(button, 'click', (event: KeyboardEvent|MouseEvent) => { + this.listeners.on(button, 'click', (event: KeyboardEvent|MouseEvent) => { this.toolButtonActivate(event, toolName); }); /** * Add listeners to show/hide toolbox tooltip */ - this.Editor.Listeners.on(button, 'mouseenter', () => { - this.showTooltip(button, toolName); - }); + const tooltipContent = this.drawTooltip(toolName); - this.Editor.Listeners.on(button, 'mouseleave', () => { - this.hideTooltip(); + this.Editor.Tooltip.onHover(button, tooltipContent, { + placement: 'bottom', + hidingDelay: 200, }); - /** - * Enable shortcut - */ - const toolSettings = this.Editor.Tools.getToolSettings(toolName); + const shortcut = this.getToolShortcut(toolName, tool); - if (toolSettings && toolSettings[this.Editor.Tools.apiSettings.SHORTCUT]) { - this.enableShortcut(tool, toolName, toolSettings[this.Editor.Tools.apiSettings.SHORTCUT]); + if (shortcut) { + this.enableShortcut(tool, toolName, shortcut); } /** Increment Tools count */ @@ -316,86 +251,99 @@ export default class Toolbox extends Module { } /** - * Add toolbox tooltip to page + * Returns tool's shortcut + * It can be specified via internal 'shortcut' static getter or by user settings for tool + * + * @param {string} toolName - tool's name + * @param {ToolConstructable} tool - tool's class (not instance) */ - private addTooltip(): void { - this.nodes.tooltip = $.make('div', this.CSS.tooltip, { - innerHTML: '', - }); + private getToolShortcut(toolName: string, tool: ToolConstructable): string|null { + /** + * Enable shortcut + */ + const toolSettings = this.Editor.Tools.getToolSettings(toolName); + const internalToolShortcut = tool[this.Editor.Tools.INTERNAL_SETTINGS.SHORTCUT]; + const userSpecifiedShortcut = toolSettings ? toolSettings[this.Editor.Tools.USER_SETTINGS.SHORTCUT] : null; - $.append(this.Editor.Toolbar.nodes.content, this.nodes.tooltip); + return userSpecifiedShortcut || internalToolShortcut; } /** - * Show tooltip for toolbox button - * @param {HTMLElement} button - * @param {string} toolName + * Draw tooltip for toolbox tools + * + * @param {string} toolName - toolbox tool name + * @returns {HTMLElement} */ - private showTooltip(button: HTMLElement, toolName: string): void { + private drawTooltip(toolName: string): HTMLElement { + const tool = this.Editor.Tools.available[toolName]; const toolSettings = this.Editor.Tools.getToolSettings(toolName); - const toolboxSettings = this.Editor.Tools.available[toolName][this.Editor.Tools.apiSettings.TOOLBOX] || {}; + const toolboxSettings = this.Editor.Tools.available[toolName][this.Editor.Tools.INTERNAL_SETTINGS.TOOLBOX] || {}; const userToolboxSettings = toolSettings.toolbox || {}; - const name = userToolboxSettings.title || toolboxSettings.title || toolName; + const name = I18n.t(I18nInternalNS.toolNames, userToolboxSettings.title || toolboxSettings.title || toolName); - let shortcut = toolSettings[this.Editor.Tools.apiSettings.SHORTCUT]; + let shortcut = this.getToolShortcut(toolName, tool); - const fragment = document.createDocumentFragment(); + const tooltip = $.make('div', this.CSS.buttonTooltip); const hint = document.createTextNode(_.capitalize(name)); - fragment.appendChild(hint); + tooltip.appendChild(hint); if (shortcut) { - const OS = _.getUserOS(); - - shortcut = shortcut - .replace(/shift/gi, '⇧') - .replace(/backspace/gi, '⌫') - .replace(/enter/gi, '⏎') - .replace(/up/gi, '↑') - .replace(/left/gi, '→') - .replace(/down/gi, '↓') - .replace(/right/gi, '←') - .replace(/escape/gi, '⎋') - .replace(/insert/gi, 'Ins') - .replace(/delete/gi, '␡') - .replace(/\+/gi, ' + '); - - if (OS.mac) { - shortcut = shortcut.replace(/ctrl|cmd/gi, '⌘').replace(/alt/gi, '⌥'); - } else { - shortcut = shortcut.replace(/cmd/gi, 'Ctrl').replace(/windows/gi, 'WIN'); - } + shortcut = _.beautifyShortcut(shortcut); - fragment.appendChild($.make('div', this.CSS.tooltipShortcut, { + tooltip.appendChild($.make('div', this.CSS.buttonShortcut, { textContent: shortcut, })); } - const leftOffset = 16; - const coordinate = button.offsetLeft; - const topOffset = Math.floor(this.Editor.BlockManager.currentBlock.holder.offsetHeight / 2); - - this.nodes.tooltip.innerHTML = ''; - this.nodes.tooltip.appendChild(fragment); - - this.nodes.tooltip.style.left = `${coordinate + leftOffset}px`; - this.nodes.tooltip.style.transform = `translate3d(-50%, ${topOffset}px, 0)`; - this.nodes.tooltip.classList.add(this.CSS.tooltipShown); + return tooltip; } /** * Enable shortcut Block Tool implemented shortcut + * * @param {BlockToolConstructable} tool - Tool class - * @param {String} toolName - Tool name - * @param {String} shortcut - shortcut according to the ShortcutData Module format + * @param {string} toolName - Tool name + * @param {string} shortcut - shortcut according to the ShortcutData Module format */ - private enableShortcut(tool: BlockToolConstructable, toolName: string, shortcut: string) { - this.Editor.Shortcuts.add({ + private enableShortcut(tool: BlockToolConstructable, toolName: string, shortcut: string): void { + Shortcuts.add({ name: shortcut, handler: (event: KeyboardEvent) => { event.preventDefault(); this.insertNewBlock(tool, toolName); }, + on: this.Editor.UI.nodes.redactor, + }); + } + + /** + * Removes all added shortcuts + * Fired when the Read-Only mode is activated + */ + private removeAllShortcuts(): void { + const tools = this.Editor.Tools.available; + + for (const toolName in tools) { + if (Object.prototype.hasOwnProperty.call(tools, toolName)) { + const shortcut = this.getToolShortcut(toolName, tools[toolName]); + + if (shortcut) { + Shortcuts.remove(this.Editor.UI.nodes.redactor, shortcut); + } + } + } + } + + /** + * Creates Flipper instance to be able to leaf tools + */ + private enableFlipper(): void { + const tools = Array.from(this.nodes.toolbox.childNodes) as HTMLElement[]; + + this.flipper = new Flipper({ + items: tools, + focusedItemClass: this.CSS.toolboxButtonActive, }); } @@ -404,27 +352,21 @@ export default class Toolbox extends Module { * Can be called when button clicked on Toolbox or by ShortcutData * * @param {BlockToolConstructable} tool - Tool Class - * @param {String} toolName - Tool name + * @param {string} toolName - Tool name */ - private insertNewBlock(tool: BlockToolConstructable, toolName: string) { - const {BlockManager, Caret} = this.Editor; - /** - * @type {Block} - */ - const {currentBlock} = BlockManager; - - let newBlock; + private insertNewBlock(tool: BlockToolConstructable, toolName: string): void { + const { BlockManager, Caret } = this.Editor; + const { currentBlock } = BlockManager; - if (currentBlock.isEmpty) { - newBlock = BlockManager.replace(toolName); - } else { - newBlock = BlockManager.insert(toolName); - } + const newBlock = BlockManager.insert({ + tool: toolName, + replace: currentBlock.isEmpty, + }); /** * Apply callback before inserting html */ - newBlock.call('appendCallback', {}); + newBlock.call(BlockToolAPI.APPEND_CALLBACK); this.Editor.Caret.setToBlock(newBlock); diff --git a/src/components/modules/tools.ts b/src/components/modules/tools.ts index 68e09153a..ddcf66b18 100644 --- a/src/components/modules/tools.ts +++ b/src/components/modules/tools.ts @@ -1,18 +1,21 @@ import Paragraph from '../tools/paragraph/dist/bundle'; import Module from '../__module'; -import _ from '../utils'; +import * as _ from '../utils'; import { BlockToolConstructable, + EditorConfig, InlineTool, InlineToolConstructable, Tool, ToolConfig, ToolConstructable, - ToolSettings, + ToolSettings } from '../../../types'; import BoldInlineTool from '../inline-tools/inline-tool-bold'; import ItalicInlineTool from '../inline-tools/inline-tool-italic'; import LinkInlineTool from '../inline-tools/inline-tool-link'; import Stub from '../tools/stub'; +import { ModuleConfig } from '../../types-internal/module-config'; +import EventsDispatcher from '../utils/events'; /** * @module Editor.js Tools Submodule @@ -31,41 +34,44 @@ import Stub from '../tools/stub'; * @property {EditorConfig} config - Editor config */ export default class Tools extends Module { - /** * Name of Stub Tool * Stub Tool is used to substitute unavailable block Tools and store their data + * * @type {string} */ public stubTool = 'stub'; /** * Returns available Tools - * @return {Tool[]} + * + * @returns {object} */ - public get available(): {[name: string]: ToolConstructable} { + public get available(): { [name: string]: ToolConstructable } { return this.toolsAvailable; } /** * Returns unavailable Tools - * @return {Tool[]} + * + * @returns {Tool[]} */ - public get unavailable(): {[name: string]: ToolConstructable} { + public get unavailable(): { [name: string]: ToolConstructable } { return this.toolsUnavailable; } /** * Return Tools for the Inline Toolbar - * @return {Object} - object of Inline Tool's classes + * + * @returns {object} - object of Inline Tool's classes */ - public get inline(): {[name: string]: ToolConstructable} { + public get inline(): { [name: string]: InlineToolConstructable } { if (this._inlineTools) { return this._inlineTools; } - const tools = Object.entries(this.available).filter( ([name, tool]) => { - if (!tool[this.apiSettings.IS_INLINE]) { + const tools = Object.entries(this.available).filter(([name, tool]) => { + if (!tool[this.INTERNAL_SETTINGS.IS_INLINE]) { return false; } @@ -73,14 +79,15 @@ export default class Tools extends Module { * Some Tools validation */ const inlineToolRequiredMethods = ['render', 'surround', 'checkState']; - const notImplementedMethods = inlineToolRequiredMethods.filter( (method) => !this.constructInline(tool)[method]); + const notImplementedMethods = inlineToolRequiredMethods.filter((method) => !this.constructInline(tool, name)[method]); if (notImplementedMethods.length) { _.log( `Incorrect Inline Tool: ${tool.name}. Some of required methods is not implemented %o`, 'warn', - notImplementedMethods, + notImplementedMethods ); + return false; } @@ -92,7 +99,9 @@ export default class Tools extends Module { */ const result = {}; - tools.forEach(([name, tool]) => result[name] = tool); + tools.forEach(([name, tool]) => { + result[name] = tool; + }); /** * Cache prepared Tools @@ -105,10 +114,9 @@ export default class Tools extends Module { /** * Return editor block tools */ - public get blockTools(): {[name: string]: BlockToolConstructable} { - // eslint-disable-next-line no-unused-vars - const tools = Object.entries(this.available).filter( ([name, tool]) => { - return !tool[this.apiSettings.IS_INLINE]; + public get blockTools(): { [name: string]: BlockToolConstructable } { + const tools = Object.entries(this.available).filter(([, tool]) => { + return !tool[this.INTERNAL_SETTINGS.IS_INLINE]; }); /** @@ -116,65 +124,89 @@ export default class Tools extends Module { */ const result = {}; - tools.forEach(([name, tool]) => result[name] = tool); + tools.forEach(([name, tool]) => { + result[name] = tool; + }); return result; } /** - * Constant for available Tools Settings - * @return {object} + * Constant for available Tools internal settings provided by Tool developer + * + * @returns {object} */ - public get apiSettings() { + public get INTERNAL_SETTINGS(): { [name: string]: string } { return { - CONFIG: 'config', - IS_ENABLED_INLINE_TOOLBAR: 'inlineToolbar', IS_ENABLED_LINE_BREAKS: 'enableLineBreaks', IS_INLINE: 'isInline', - IS_PASTE_DISALLOWED: 'disallowPaste', + TITLE: 'title', // for Inline Tools. Block Tools can pass title along with icon through the 'toolbox' static prop. SHORTCUT: 'shortcut', TOOLBOX: 'toolbox', SANITIZE_CONFIG: 'sanitize', + CONVERSION_CONFIG: 'conversionConfig', + IS_READ_ONLY_SUPPORTED: 'isReadOnlySupported', + }; + } + + /** + * Constant for available Tools settings provided by user + * + * return {object} + */ + public get USER_SETTINGS(): { [name: string]: string } { + return { + SHORTCUT: 'shortcut', + TOOLBOX: 'toolbox', + ENABLED_INLINE_TOOLS: 'inlineToolbar', + CONFIG: 'config', }; } /** * Map {name: Class, ...} where: * name — block type name in JSON. Got from EditorConfig.tools keys - * @type {Object} + * + * @type {object} */ - public readonly toolsClasses: {[name: string]: ToolConstructable} = {}; + public readonly toolsClasses: { [name: string]: ToolConstructable } = {}; /** * Tools` classes available to use */ - private readonly toolsAvailable: {[name: string]: ToolConstructable} = {}; + private readonly toolsAvailable: { [name: string]: ToolConstructable } = {}; /** - * Tools` classes not availbale to use beacause of preparation failure + * Tools` classes not available to use because of preparation failure */ - private readonly toolsUnavailable: {[name: string]: ToolConstructable} = {}; + private readonly toolsUnavailable: { [name: string]: ToolConstructable } = {}; /** * Tools settings in a map {name: settings, ...} - * @type {Object} + * + * @type {object} */ - private readonly toolsSettings: {[name: string]: ToolSettings} = {}; + private readonly toolsSettings: { [name: string]: ToolSettings } = {}; /** * Cache for the prepared inline tools + * * @type {null|object} * @private */ - private _inlineTools: {[name: string]: ToolConstructable} = {}; + private _inlineTools: { [name: string]: ToolConstructable } = {}; /** - * @constructor + * @class * - * @param {EditorConfig} config + * @param {EditorConfig} config - Editor's configuration + * @param {EventsDispatcher} eventsDispatcher - Editor's event dispatcher */ - constructor({config}) { - super({config}); + constructor({ config, eventsDispatcher }: ModuleConfig) { + super({ + config, + eventsDispatcher, + }); this.toolsClasses = {}; @@ -183,14 +215,16 @@ export default class Tools extends Module { /** * Available tools list * {name: Class, ...} - * @type {Object} + * + * @type {object} */ this.toolsAvailable = {}; /** * Tools that rejected a prepare method * {name: Class, ... } - * @type {Object} + * + * @type {object} */ this.toolsUnavailable = {}; @@ -199,17 +233,18 @@ export default class Tools extends Module { /** * Creates instances via passed or default configuration - * @return {Promise} + * + * @returns {Promise} */ - public prepare() { + public prepare(): Promise { this.validateTools(); /** * Assign internal tools */ - _.deepMerge(this.config.tools, this.internalTools); + this.config.tools = _.deepMerge({}, this.internalTools, this.config.tools); - if (!this.config.hasOwnProperty('tools') || Object.keys(this.config.tools).length === 0) { + if (!Object.prototype.hasOwnProperty.call(this.config, 'tools') || Object.keys(this.config.tools).length === 0) { throw Error('Can\'t start without tools'); } @@ -221,15 +256,17 @@ export default class Tools extends Module { * If Tool is an object not a Tool's class then * save class and settings separately */ - if (typeof this.config.tools[toolName] === 'object') { + if (_.isObject(this.config.tools[toolName])) { /** * Save Tool's class from 'class' field + * * @type {Tool} */ this.toolsClasses[toolName] = (this.config.tools[toolName] as ToolSettings).class; /** * Save Tool's settings + * * @type {ToolSettings} */ this.toolsSettings[toolName] = this.config.tools[toolName] as ToolSettings; @@ -241,15 +278,17 @@ export default class Tools extends Module { } else { /** * Save Tool's class + * * @type {Tool} */ this.toolsClasses[toolName] = this.config.tools[toolName] as ToolConstructable; /** * Set empty settings for Block by default + * * @type {{}} */ - this.toolsSettings[toolName] = {class: this.config.tools[toolName] as ToolConstructable}; + this.toolsSettings[toolName] = { class: this.config.tools[toolName] as ToolConstructable }; } } @@ -266,124 +305,157 @@ export default class Tools extends Module { } /** - * to see how it works {@link Util#sequence} + * to see how it works {@link '../utils.ts#sequence'} */ - return _.sequence(sequenceData, (data: any) => { + return _.sequence(sequenceData, (data: { toolName: string }) => { this.success(data); - }, (data) => { + }, (data: { toolName: string }) => { this.fallback(data); }); } /** - * @param {ChainData.data} data - append tool to available list + * Success callback + * + * @param {object} data - append tool to available list */ - public success(data) { + public success(data: { toolName: string }): void { this.toolsAvailable[data.toolName] = this.toolsClasses[data.toolName]; } /** - * @param {ChainData.data} data - append tool to unavailable list + * Fail callback + * + * @param {object} data - append tool to unavailable list */ - public fallback(data) { + public fallback(data: { toolName: string }): void { this.toolsUnavailable[data.toolName] = this.toolsClasses[data.toolName]; } /** - * Return Tool`s instance + * Return Inline Tool's instance + * + * @param {InlineTool} tool - Inline Tool instance + * @param {string} name - tool name + * @param {ToolSettings} toolSettings - tool settings * - * @param {String} tool — tool name - * @param {BlockToolData} data — initial data - * @return {BlockTool} + * @returns {InlineTool} — instance */ - public construct(tool, data) { - const plugin = this.toolsClasses[tool]; - - /** - * Configuration to be passed to the Tool's constructor - */ - const config = this.toolsSettings[tool][this.apiSettings.CONFIG]; - - /** - * @type {{api: API, config: ({}), data: BlockToolData}} - */ + public constructInline( + tool: InlineToolConstructable, + name: string, + toolSettings: ToolSettings = {} as ToolSettings + ): InlineTool { const constructorOptions = { - api: this.Editor.API.methods, - config: config || {}, - data, + api: this.Editor.API.getMethodsForTool(name), + config: (toolSettings[this.USER_SETTINGS.CONFIG] || {}) as ToolSettings, }; - return new plugin(constructorOptions); + // eslint-disable-next-line new-cap + return new tool(constructorOptions) as InlineTool; } /** - * Return Inline Tool's instance + * Check if passed Tool is an instance of Default Block Tool + * + * @param {Tool} tool - Tool to check * - * @param {InlineTool} tool - * @param {ToolSettings} toolSettings - * @return {InlineTool} — instance + * @returns {boolean} */ - public constructInline(tool: InlineToolConstructable, toolSettings: ToolSettings = {} as ToolSettings): InlineTool { - /** - * @type {{api: API}} - */ - const constructorOptions = { - api: this.Editor.API.methods, - config: toolSettings[this.apiSettings.CONFIG] || {}, - }; + public isDefault(tool): boolean { + return tool instanceof this.available[this.config.defaultBlock]; + } - return new tool(constructorOptions) as InlineTool; + /** + * Return Tool's config by name + * + * @param {string} toolName - name of tool + * + * @returns {ToolSettings} + */ + public getToolSettings(toolName): ToolSettings { + const settings = this.toolsSettings[toolName]; + const config = settings[this.USER_SETTINGS.CONFIG] || {}; + + // Pass placeholder to default Block config + if (toolName === this.config.defaultBlock && !config.placeholder) { + config.placeholder = this.config.placeholder; + settings[this.USER_SETTINGS.CONFIG] = config; + } + + return settings; } /** - * Check if passed Tool is an instance of Initial Block Tool - * @param {Tool} tool - Tool to check - * @return {Boolean} + * Returns internal tools + * Includes Bold, Italic, Link and Paragraph */ - public isInitial(tool) { - return tool instanceof this.available[this.config.initialBlock]; + public get internalTools(): { [toolName: string]: ToolConstructable | ToolSettings } { + return { + bold: { class: BoldInlineTool }, + italic: { class: ItalicInlineTool }, + link: { class: LinkInlineTool }, + paragraph: { + class: Paragraph, + inlineToolbar: true, + }, + stub: { class: Stub }, + }; } /** - * Return Tool's config by name - * @param {string} toolName - * @return {ToolSettings} + * Returns true if tool supports read-only mode + * + * @param tool - tool to check */ - public getToolSettings(toolName): ToolSettings { - return this.toolsSettings[toolName]; + public isReadOnlySupported(tool: BlockToolConstructable): boolean { + return tool[this.INTERNAL_SETTINGS.IS_READ_ONLY_SUPPORTED] === true; + } + + /** + * Calls each Tool reset method to clean up anything set by Tool + */ + public destroy(): void { + Object.values(this.available).forEach(async tool => { + if (_.isFunction(tool.reset)) { + await tool.reset(); + } + }); } /** * Binds prepare function of plugins with user or default config - * @return {Array} list of functions that needs to be fired sequentially + * + * @returns {Array} list of functions that needs to be fired sequentially */ private getListOfPrepareFunctions(): Array<{ - function: (data: {toolName: string, config: ToolConfig}) => void, - data: {toolName: string, config: ToolConfig}, + function: (data: { toolName: string; config: ToolConfig }) => void; + data: { toolName: string; config: ToolConfig }; }> { const toolPreparationList: Array<{ - function: (data: {toolName: string, config: ToolConfig}) => void, - data: {toolName: string, config: ToolConfig}} - > = []; + function: (data: { toolName: string; config: ToolConfig }) => void; + data: { toolName: string; config: ToolConfig }; + } + > = []; for (const toolName in this.toolsClasses) { - if (this.toolsClasses.hasOwnProperty(toolName)) { + if (Object.prototype.hasOwnProperty.call(this.toolsClasses, toolName)) { const toolClass = this.toolsClasses[toolName]; + const toolConfig = this.toolsSettings[toolName][this.USER_SETTINGS.CONFIG]; - if (typeof toolClass.prepare === 'function') { - toolPreparationList.push({ - function: toolClass.prepare, - data: { - toolName, - config: this.toolsSettings[toolName][this.apiSettings.CONFIG], - }, - }); - } else { - /** - * If Tool hasn't a prepare method, mark it as available - */ - this.toolsAvailable[toolName] = toolClass; - } + /** + * If Tool hasn't a prepare method, + * still push it to tool preparation list to save tools order in Toolbox. + * As Tool's prepare method might be async, _.sequence util helps to save the order. + */ + toolPreparationList.push({ + // eslint-disable-next-line @typescript-eslint/no-empty-function + function: _.isFunction(toolClass.prepare) ? toolClass.prepare : (): void => { }, + data: { + toolName, + config: toolConfig, + }, + }); } } @@ -393,12 +465,12 @@ export default class Tools extends Module { /** * Validate Tools configuration objects and throw Error for user if it is invalid */ - private validateTools() { + private validateTools(): void { /** * Check Tools for a class containing */ for (const toolName in this.config.tools) { - if (this.config.tools.hasOwnProperty(toolName)) { + if (Object.prototype.hasOwnProperty.call(this.config.tools, toolName)) { if (toolName in this.internalTools) { return; } @@ -407,27 +479,29 @@ export default class Tools extends Module { if (!_.isFunction(tool) && !_.isFunction((tool as ToolSettings).class)) { throw Error( - `Tool «${toolName}» must be a constructor function or an object with function in the «class» property`, + `Tool «${toolName}» must be a constructor function or an object with function in the «class» property` ); } } } } +} +/** + * What kind of plugins developers can create + */ +export enum ToolType { /** - * Returns internal tools - * Includes Bold, Italic, Link and Paragraph + * Block tool */ - get internalTools() { - return { - bold: {class: BoldInlineTool}, - italic: {class: ItalicInlineTool}, - link: {class: LinkInlineTool}, - paragraph: { - class: Paragraph, - inlineToolbar: true, - }, - stub: {class: Stub}, - }; - } + Block, + /** + * Inline tool + */ + Inline, + + /** + * Block tune + */ + Tune, } diff --git a/src/components/modules/tooltip.ts b/src/components/modules/tooltip.ts new file mode 100644 index 000000000..f3ff6711c --- /dev/null +++ b/src/components/modules/tooltip.ts @@ -0,0 +1,50 @@ +/* eslint-disable jsdoc/no-undefined-types */ +import Module from '../__module'; + +/** + * Use external module CodeX Tooltip + */ +import CodeXTooltips, { TooltipContent, TooltipOptions } from 'codex-tooltip'; + +/** + * Tooltip + * + * Decorates any tooltip module like adapter + */ +export default class Tooltip extends Module { + /** + * Tooltips lib: CodeX Tooltips + * + * @see https://github.com/codex-team/codex.tooltips + */ + private lib: CodeXTooltips = new CodeXTooltips(); + + /** + * Shows tooltip on element with passed HTML content + * + * @param {HTMLElement} element - any HTML element in DOM + * @param {TooltipContent} content - tooltip's content + * @param {TooltipOptions} options - showing settings + */ + public show(element: HTMLElement, content: TooltipContent, options?: TooltipOptions): void { + this.lib.show(element, content, options); + } + + /** + * Hides tooltip + */ + public hide(): void { + this.lib.hide(); + } + + /** + * Binds 'mouseenter' and 'mouseleave' events that shows/hides the Tooltip + * + * @param {HTMLElement} element - any HTML element in DOM + * @param {TooltipContent} content - tooltip's content + * @param {TooltipOptions} options - showing settings + */ + public onHover(element: HTMLElement, content: TooltipContent, options?: TooltipOptions): void { + this.lib.onHover(element, content, options); + } +} diff --git a/src/components/modules/ui.ts b/src/components/modules/ui.ts index 2c5af425a..1d9874b39 100644 --- a/src/components/modules/ui.ts +++ b/src/components/modules/ui.ts @@ -1,3 +1,4 @@ +/* eslint-disable jsdoc/no-undefined-types */ /** * Prebuilded sprite of SVG icons */ @@ -10,9 +11,21 @@ import sprite from '../../../dist/sprite.svg'; */ import Module from '../__module'; import $ from '../dom'; -import _ from '../utils'; +import * as _ from '../utils'; import Selection from '../selection'; +import Block from '../block'; +import Flipper from '../flipper'; + +/** + * HTML Elements used for UI + */ +interface UINodes { + holder: HTMLElement; + wrapper: HTMLElement; + redactor: HTMLElement; + loader: HTMLElement; +} /** * @class @@ -26,46 +39,84 @@ import Selection from '../selection'; * * @typedef {UI} UI * @property {EditorConfig} config - editor configuration {@link EditorJS#configuration} - * @property {Object} Editor - available editor modules {@link EditorJS#moduleInstances} - * @property {Object} nodes - + * @property {object} Editor - available editor modules {@link EditorJS#moduleInstances} + * @property {object} nodes - * @property {Element} nodes.holder - element where we need to append redactor * @property {Element} nodes.wrapper - * @property {Element} nodes.redactor - */ -export default class UI extends Module { - +export default class UI extends Module { /** * Editor.js UI CSS class names - * @return {{editorWrapper: string, editorZone: string}} + * + * @returns {{editorWrapper: string, editorZone: string}} */ public get CSS(): { - editorWrapper: string, editorWrapperNarrow: string, editorZone: string, editorZoneHidden: string, - editorLoader: string, editorEmpty: string, - } { + editorWrapper: string; editorWrapperNarrow: string; editorZone: string; editorZoneHidden: string; + editorLoader: string; editorEmpty: string; editorRtlFix: string; + } { return { - editorWrapper : 'codex-editor', - editorWrapperNarrow : 'codex-editor--narrow', - editorZone : 'codex-editor__redactor', - editorZoneHidden : 'codex-editor__redactor--hidden', - editorLoader : 'codex-editor__loader', - editorEmpty : 'codex-editor--empty', + editorWrapper: 'codex-editor', + editorWrapperNarrow: 'codex-editor--narrow', + editorZone: 'codex-editor__redactor', + editorZoneHidden: 'codex-editor__redactor--hidden', + editorLoader: 'codex-editor__loader', + editorEmpty: 'codex-editor--empty', + editorRtlFix: 'codex-editor--rtl', }; } /** - * Width of center column of Editor - * @type {number} + * Return Width of center column of Editor + * + * @returns {DOMRect} */ - public contentWidth: number = 650; + public get contentRect(): DOMRect { + if (this.contentRectCache) { + return this.contentRectCache; + } + + const someBlock = this.nodes.wrapper.querySelector(`.${Block.CSS.content}`); + + /** + * When Editor is not ready, there is no Blocks, so return the default value + */ + if (!someBlock) { + return { + width: 650, + left: 0, + right: 0, + } as DOMRect; + } + + this.contentRectCache = someBlock.getBoundingClientRect() as DOMRect; + + return this.contentRectCache; + } /** - * HTML Elements used for UI + * Flag that became true on mobile viewport + * + * @type {boolean} + */ + public isMobile = false; + + /** + * Cache for center column rectangle info + * Invalidates on window resize + * + * @type {DOMRect} */ - public nodes: { [key: string]: HTMLElement } = { - holder: null, - wrapper: null, - redactor: null, - }; + private contentRectCache: DOMRect = undefined; + + /** + * Handle window resize only when it finished + * + * @type {() => void} + */ + private resizeDebouncer: () => void = _.debounce(() => { + this.windowResize(); + }, 200); /** * Adds loader to editor while content is not ready @@ -88,34 +139,91 @@ export default class UI extends Module { * Making main interface */ public async prepare(): Promise { - await this.make(); - - this.addLoader(); + /** + * Detect mobile version + */ + this.checkIsMobile(); /** - * Append SVG sprite + * Make main UI elements */ - await this.appendSVGSprite(); + this.make(); /** - * Make toolbar + * Loader for rendering process */ - await this.Editor.Toolbar.make(); + this.addLoader(); /** - * Make the Inline toolbar + * Append SVG sprite */ - await this.Editor.InlineToolbar.make(); + this.appendSVGSprite(); /** * Load and append CSS */ - await this.loadStyles(); + this.loadStyles(); + } + /** + * Toggle read-only state + * + * If readOnly is true: + * - removes all listeners from main UI module elements + * + * if readOnly is false: + * - enables all listeners to UI module elements + * + * @param {boolean} readOnlyEnabled - "read only" state + */ + public toggleReadOnly(readOnlyEnabled: boolean): void { /** - * Bind events for the UI elements + * Prepare components based on read-only state */ - await this.bindEvents(); + if (!readOnlyEnabled) { + /** + * Unbind all events + */ + this.enableModuleBindings(); + } else { + /** + * Bind events for the UI elements + */ + this.disableModuleBindings(); + } + } + + /** + * Check if Editor is empty and set CSS class to wrapper + */ + public checkEmptiness(): void { + const { BlockManager } = this.Editor; + + this.nodes.wrapper.classList.toggle(this.CSS.editorEmpty, BlockManager.isEditorEmpty); + } + + /** + * Check if one of Toolbar is opened + * Used to prevent global keydowns (for example, Enter) conflicts with Enter-on-toolbar + * + * @returns {boolean} + */ + public get someToolbarOpened(): boolean { + const { Toolbox, BlockSettings, InlineToolbar, ConversionToolbar } = this.Editor; + + return BlockSettings.opened || InlineToolbar.opened || ConversionToolbar.opened || Toolbox.opened; + } + + /** + * Check for some Flipper-buttons is under focus + */ + public get someFlipperButtonFocused(): boolean { + return Object.entries(this.Editor).filter(([moduleName, moduleClass]) => { + return moduleClass.flipper instanceof Flipper; + }) + .some(([moduleName, moduleClass]) => { + return moduleClass.flipper.currentItem; + }); } /** @@ -125,37 +233,59 @@ export default class UI extends Module { this.nodes.holder.innerHTML = ''; } + /** + * Close all Editor's toolbars + */ + public closeAllToolbars(): void { + const { Toolbox, BlockSettings, InlineToolbar, ConversionToolbar } = this.Editor; + + BlockSettings.close(); + InlineToolbar.close(); + ConversionToolbar.close(); + Toolbox.close(); + } + + /** + * Check for mobile mode and cache a result + */ + private checkIsMobile(): void { + this.isMobile = window.innerWidth < 650; + } + /** * Makes Editor.js interface - * @return {Promise} */ - private async make(): Promise { + private make(): void { /** * Element where we need to append Editor.js + * * @type {Element} */ - this.nodes.holder = document.getElementById(this.config.holderId); - - if (!this.nodes.holder) { - throw Error('Holder wasn\'t found by ID: #' + this.config.holderId); - } + this.nodes.holder = $.getHolder(this.config.holder); /** * Create and save main UI elements */ - this.nodes.wrapper = $.make('div', this.CSS.editorWrapper); + this.nodes.wrapper = $.make('div', [ + this.CSS.editorWrapper, + ...(this.isRtl ? [ this.CSS.editorRtlFix ] : []), + ]); this.nodes.redactor = $.make('div', this.CSS.editorZone); /** * If Editor has injected into the narrow container, enable Narrow Mode */ - if (this.nodes.holder.offsetWidth < this.contentWidth) { + if (this.nodes.holder.offsetWidth < this.contentRect.width) { this.nodes.wrapper.classList.add(this.CSS.editorWrapperNarrow); } + /** + * Set customizable bottom zone height + */ + this.nodes.redactor.style.paddingBottom = this.config.minHeight + 'px'; + this.nodes.wrapper.appendChild(this.nodes.redactor); this.nodes.holder.appendChild(this.nodes.wrapper); - } /** @@ -165,12 +295,22 @@ export default class UI extends Module { /** * Load CSS */ + // eslint-disable-next-line @typescript-eslint/no-var-requires const styles = require('../../styles/main.css'); + const styleTagId = 'editor-js-styles'; + + /** + * Do not append styles again if they are already on the page + */ + if ($.get(styleTagId)) { + return; + } /** * Make tag */ const tag = $.make('style', null, { + id: styleTagId, textContent: styles.toString(), }); @@ -183,29 +323,82 @@ export default class UI extends Module { /** * Bind events on the Editor.js interface */ - private bindEvents(): void { - this.Editor.Listeners.on( - this.nodes.redactor, - 'click', - (event) => this.redactorClicked(event as MouseEvent), - false, - ); - this.Editor.Listeners.on(document, 'keydown', (event) => this.documentKeydown(event as KeyboardEvent), true); - this.Editor.Listeners.on(document, 'click', (event) => this.documentClicked(event as MouseEvent), true); + private enableModuleBindings(): void { + this.readOnlyMutableListeners.on(this.nodes.redactor, 'click', (event: MouseEvent) => { + this.redactorClicked(event); + }, false); + + this.readOnlyMutableListeners.on(this.nodes.redactor, 'mousedown', (event: MouseEvent | TouchEvent) => { + this.documentTouched(event); + }, true); + + this.readOnlyMutableListeners.on(this.nodes.redactor, 'touchstart', (event: MouseEvent | TouchEvent) => { + this.documentTouched(event); + }, true); + + this.readOnlyMutableListeners.on(document, 'keydown', (event: KeyboardEvent) => { + this.documentKeydown(event); + }, true); + + this.readOnlyMutableListeners.on(document, 'click', (event: MouseEvent) => { + this.documentClicked(event); + }, true); + + /** + * Handle selection change to manipulate Inline Toolbar appearance + */ + this.readOnlyMutableListeners.on(document, 'selectionchange', (event: Event) => { + this.selectionChanged(event); + }, true); + + this.readOnlyMutableListeners.on(window, 'resize', () => { + this.resizeDebouncer(); + }, { + passive: true, + }); + } + + /** + * Unbind events on the Editor.js interface + */ + private disableModuleBindings(): void { + this.readOnlyMutableListeners.clearAll(); + } + + /** + * Resize window handler + */ + private windowResize(): void { + /** + * Invalidate content zone size cached, because it may be changed + */ + this.contentRectCache = null; + + /** + * Detect mobile version + */ + this.checkIsMobile(); } /** * All keydowns on document - * @param {Event} event + * + * @param {KeyboardEvent} event - keyboard event */ private documentKeydown(event: KeyboardEvent): void { switch (event.keyCode) { case _.keyCodes.ENTER: this.enterPressed(event); break; + case _.keyCodes.BACKSPACE: this.backspacePressed(event); break; + + case _.keyCodes.ESC: + this.escapePressed(event); + break; + default: this.defaultBehaviour(event); break; @@ -214,13 +407,23 @@ export default class UI extends Module { /** * Ignore all other document's keydown events - * @param {KeyboardEvent} event + * + * @param {KeyboardEvent} event - keyboard event */ private defaultBehaviour(event: KeyboardEvent): void { + const { currentBlock } = this.Editor.BlockManager; const keyDownOnEditor = (event.target as HTMLElement).closest(`.${this.CSS.editorWrapper}`); - const {currentBlock} = this.Editor.BlockManager; const isMetaKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey; + /** + * When some block is selected, but the caret is not set inside the editor, treat such keydowns as keydown on selected block. + */ + if (currentBlock !== undefined && keyDownOnEditor === null) { + this.Editor.BlockEvents.keydown(event); + + return; + } + /** * Ignore keydowns on editor and meta keys */ @@ -240,42 +443,75 @@ export default class UI extends Module { } /** - * @param {KeyboardEvent} event + * @param {KeyboardEvent} event - keyboard event */ private backspacePressed(event: KeyboardEvent): void { - const {BlockManager, BlockSelection, Caret} = this.Editor; + const { BlockManager, BlockSelection, Caret } = this.Editor; - if (BlockSelection.anyBlockSelected) { + /** + * If any block selected and selection doesn't exists on the page (that means no other editable element is focused), + * remove selected blocks + */ + if (BlockSelection.anyBlockSelected && !Selection.isSelectionExists) { const selectionPositionIndex = BlockManager.removeSelectedBlocks(); - Caret.setToBlock(BlockManager.insertAtIndex(selectionPositionIndex, true), Caret.positions.START); + + Caret.setToBlock(BlockManager.insertDefaultBlockAtIndex(selectionPositionIndex, true), Caret.positions.START); /** Clear selection */ - BlockSelection.clearSelection(); + BlockSelection.clearSelection(event); /** * Stop propagations * Manipulation with BlockSelections is handled in global backspacePress because they may occur * with CMD+A or RectangleSelection and they can be handled on document event */ + event.preventDefault(); event.stopPropagation(); event.stopImmediatePropagation(); } } + /** + * Escape pressed + * If some of Toolbar components are opened, then close it otherwise close Toolbar + * + * @param {Event} event - escape keydown event + */ + private escapePressed(event): void { + /** + * Clear blocks selection by ESC + */ + this.Editor.BlockSelection.clearSelection(event); + + if (this.Editor.Toolbox.opened) { + this.Editor.Toolbox.close(); + } else if (this.Editor.BlockSettings.opened) { + this.Editor.BlockSettings.close(); + } else if (this.Editor.ConversionToolbar.opened) { + this.Editor.ConversionToolbar.close(); + } else if (this.Editor.InlineToolbar.opened) { + this.Editor.InlineToolbar.close(); + } else { + this.Editor.Toolbar.close(); + } + } + /** * Enter pressed on document - * @param event + * + * @param {KeyboardEvent} event - keyboard event */ private enterPressed(event: KeyboardEvent): void { - const {BlockManager, BlockSelection, Caret} = this.Editor; + const { BlockManager, BlockSelection } = this.Editor; const hasPointerToBlock = BlockManager.currentBlockIndex >= 0; - if (BlockSelection.anyBlockSelected) { - const selectionPositionIndex = BlockManager.removeSelectedBlocks(); - Caret.setToBlock(BlockManager.insertAtIndex(selectionPositionIndex, true), Caret.positions.START); - + /** + * If any block selected and selection doesn't exists on the page (that means no other editable element is focused), + * remove selected blocks + */ + if (BlockSelection.anyBlockSelected && !Selection.isSelectionExists) { /** Clear selection */ - BlockSelection.clearSelection(); + BlockSelection.clearSelection(event); /** * Stop propagations @@ -285,6 +521,7 @@ export default class UI extends Module { event.preventDefault(); event.stopImmediatePropagation(); event.stopPropagation(); + return; } @@ -295,9 +532,9 @@ export default class UI extends Module { * So, BlockManager points some Block and Enter press is on Body * We can create a new block */ - if (hasPointerToBlock && (event.target as HTMLElement).tagName === 'BODY') { + if (!this.someToolbarOpened && hasPointerToBlock && (event.target as HTMLElement).tagName === 'BODY') { /** - * Insert initial typed Block + * Insert the default typed Block */ const newBlock = this.Editor.BlockManager.insert(); @@ -315,23 +552,30 @@ export default class UI extends Module { this.Editor.Toolbar.plusButton.show(); } - this.Editor.BlockSelection.clearSelection(); + this.Editor.BlockSelection.clearSelection(event); } /** * All clicks on document - * @param {MouseEvent} event - Click + * + * @param {MouseEvent} event - Click event */ private documentClicked(event: MouseEvent): void { + /** + * Sometimes we emulate click on some UI elements, for example by Enter on Block Settings button + * We don't need to handle such events, because they handled in other place. + */ + if (!event.isTrusted) { + return; + } /** * Close Inline Toolbar when nothing selected * Do not fire check on clicks at the Inline Toolbar buttons */ const target = event.target as HTMLElement; - const clickedOnInlineToolbarButton = target.closest(`.${this.Editor.InlineToolbar.CSS.inlineToolbar}`); - const clickedInsideofEditor = target.closest(`#${this.config.holderId}`); + const clickedInsideOfEditor = this.nodes.holder.contains(target) || Selection.isAtEditor; - if (!clickedInsideofEditor) { + if (!clickedInsideOfEditor) { /** * Clear highlightings and pointer on BlockManager * @@ -341,58 +585,39 @@ export default class UI extends Module { this.Editor.BlockManager.dropPointer(); this.Editor.InlineToolbar.close(); this.Editor.Toolbar.close(); - this.Editor.BlockSelection.clearSelection(); + this.Editor.ConversionToolbar.close(); + } - } else if (!clickedOnInlineToolbarButton) { - /** - * Move inline toolbar to the focused Block - */ - this.Editor.InlineToolbar.handleShowingEvent(event); - } else if (Selection.isAtEditor) { - /** - * Focus clicked Block - */ - this.Editor.BlockManager.setCurrentBlockByChildNode(Selection.anchorNode); + /** + * Clear Selection if user clicked somewhere + */ + if (!this.Editor.CrossBlockSelection.isCrossBlockSelectionStarted) { + this.Editor.BlockSelection.clearSelection(event); } } /** - * All clicks on the redactor zone - * - * @param {MouseEvent} event - * - * @description - * 1. Save clicked Block as a current {@link BlockManager#currentNode} - * it uses for the following: - * - add CSS modifier for the selected Block - * - on Enter press, we make a new Block under that + * First touch on editor + * Fired before click * - * 2. Move and show the Toolbar - * - * 3. Set a Caret - * - * 4. By clicks on the Editor's bottom zone: - * - if last Block is empty, set a Caret to this - * - otherwise, add a new empty Block and set a Caret to that - * - * 5. Hide the Inline Toolbar - * - * @see selectClickedBlock + * Used to change current block — we need to do it before 'selectionChange' event. + * Also: + * - Move and show the Toolbar + * - Set a Caret * + * @param {MouseEvent | TouchEvent} event - touch or mouse event */ - private redactorClicked(event: MouseEvent): void { - - if (!Selection.isCollapsed) { - return; - } - + private documentTouched(event: MouseEvent | TouchEvent): void { let clickedNode = event.target as HTMLElement; /** * If click was fired is on Editor`s wrapper, try to get clicked node by elementFromPoint method */ if (clickedNode === this.nodes.redactor) { - clickedNode = document.elementFromPoint(event.clientX, event.clientY) as HTMLElement; + const clientX = event instanceof MouseEvent ? event.clientX : event.touches[0].clientX; + const clientY = event instanceof MouseEvent ? event.clientY : event.touches[0].clientY; + + clickedNode = document.elementFromPoint(clientX, clientY) as HTMLElement; } /** @@ -417,9 +642,6 @@ export default class UI extends Module { } } - event.stopImmediatePropagation(); - event.stopPropagation(); - /** * Move and open toolbar */ @@ -429,19 +651,62 @@ export default class UI extends Module { * Hide the Plus Button */ this.Editor.Toolbar.plusButton.hide(); + } + + /** + * All clicks on the redactor zone + * + * @param {MouseEvent} event - click event + * + * @description + * - By clicks on the Editor's bottom zone: + * - if last Block is empty, set a Caret to this + * - otherwise, add a new empty Block and set a Caret to that + */ + private redactorClicked(event: MouseEvent): void { + if (!Selection.isCollapsed) { + return; + } + + const stopPropagation = (): void => { + event.stopImmediatePropagation(); + event.stopPropagation(); + }; + + /** + * case when user clicks on anchor element + * if it is clicked via ctrl key, then we open new window with url + */ + const element = event.target as Element; + const ctrlKey = event.metaKey || event.ctrlKey; + + if ($.isAnchor(element) && ctrlKey) { + stopPropagation(); + + const href = element.getAttribute('href'); + const validUrl = _.getValidUrl(href); + + _.openTab(validUrl); + + return; + } if (!this.Editor.BlockManager.currentBlock) { + stopPropagation(); + this.Editor.BlockManager.insert(); } /** * Show the Plus Button if: - * - Block is an initial-block (Text) + * - Block is an default-block (Text) * - Block is empty */ - const isInitialBlock = this.Editor.Tools.isInitial(this.Editor.BlockManager.currentBlock.tool); + const isDefaultBlock = this.Editor.Tools.isDefault(this.Editor.BlockManager.currentBlock.tool); + + if (isDefaultBlock) { + stopPropagation(); - if (isInitialBlock) { /** * Check isEmpty only for paragraphs to prevent unnecessary tree-walking on Tools with many nodes (for ex. Table) */ @@ -451,13 +716,55 @@ export default class UI extends Module { this.Editor.Toolbar.plusButton.show(); } } + } + + /** + * Handle selection changes on mobile devices + * Uses for showing the Inline Toolbar + * + * @param {Event} event - selection event + */ + private selectionChanged(event: Event): void { + const { CrossBlockSelection, BlockSelection } = this.Editor; + const focusedElement = Selection.anchorElement; + + if (CrossBlockSelection.isCrossBlockSelectionStarted) { + // Removes all ranges when any Block is selected + if (BlockSelection.anyBlockSelected) { + Selection.get().removeAllRanges(); + } + } + + /** + * Event can be fired on clicks at the Editor elements, for example, at the Inline Toolbar + * We need to skip such firings + */ + if (!focusedElement || !focusedElement.closest(`.${Block.CSS.content}`)) { + /** + * If new selection is not on Inline Toolbar, we need to close it + */ + if (!this.Editor.InlineToolbar.containsNode(focusedElement)) { + this.Editor.InlineToolbar.close(); + } + + return; + } - /** Clear selection */ - this.Editor.BlockSelection.clearSelection(); + /** + * Set current block when entering to Editor.js by tab key + */ + if (!this.Editor.BlockManager.currentBlock) { + this.Editor.BlockManager.setCurrentBlockByChildNode(focusedElement); + } + + /** + * @todo add debounce + */ + this.Editor.InlineToolbar.tryToShow(true); } /** - * Append prebuilded sprite with SVG icons + * Append prebuilt sprite with SVG icons */ private appendSVGSprite(): void { const spriteHolder = $.make('div'); diff --git a/src/components/polyfills.ts b/src/components/polyfills.ts index 106ee7342..cfa9af748 100644 --- a/src/components/polyfills.ts +++ b/src/components/polyfills.ts @@ -18,7 +18,9 @@ interface Element { * would be selected by the specified selector string; * otherwise, returns false. * - * {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill} + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill} + * + * @param {string} s - selector */ if (!Element.prototype.matches) { Element.prototype.matches = Element.prototype.matchesSelector || @@ -26,7 +28,7 @@ if (!Element.prototype.matches) { Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector || - function(s) { + function (s): boolean { const matches = (this.document || this.ownerDocument).querySelectorAll(s); let i = matches.length; @@ -43,10 +45,13 @@ if (!Element.prototype.matches) { * matches the selectors given in parameter. * If there isn't such an ancestor, it returns null. * - * {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill} + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill} + * + * @param {string} s - selector */ if (!Element.prototype.closest) { - Element.prototype.closest = function(s) { + Element.prototype.closest = function (s): Element | null { + // eslint-disable-next-line @typescript-eslint/no-this-alias let el = this; if (!document.documentElement.contains(el)) { @@ -70,20 +75,22 @@ if (!Element.prototype.closest) { * or DOMString objects before the first child of the ParentNode. * DOMString objects are inserted as equivalent Text nodes. * - * {@link https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/prepend#Polyfill} + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/prepend#Polyfill} + * + * @param {Node | Node[] | string | string[]} nodes - nodes to prepend */ if (!Element.prototype.prepend) { - Element.prototype.prepend = function prepend(nodes: Node|Node[]|any) { + Element.prototype.prepend = function prepend(nodes: Array | Node | string): void { const docFrag = document.createDocumentFragment(); if (!Array.isArray(nodes)) { nodes = [ nodes ]; } - nodes.forEach((node: Node|any) => { + nodes.forEach((node: Node | string) => { const isNode = node instanceof Node; - docFrag.appendChild(isNode ? node : document.createTextNode(String(node))); + docFrag.appendChild(isNode ? node as Node : document.createTextNode(node as string)); }); this.insertBefore(docFrag, this.firstChild); diff --git a/src/components/selection.ts b/src/components/selection.ts index c002405cf..32c12ee06 100644 --- a/src/components/selection.ts +++ b/src/components/selection.ts @@ -1,7 +1,8 @@ /** - * TextRange interface fot IE9- + * TextRange interface for IE9- */ -import _ from './utils'; +import * as _ from './utils'; +import $ from './dom'; interface TextRange { boundingTop: number; @@ -29,15 +30,16 @@ interface Document { /** * Working with selection + * * @typedef {SelectionUtils} SelectionUtils */ export default class SelectionUtils { - /** * Editor styles - * @return {{editorWrapper: string, editorZone: string}} + * + * @returns {{editorWrapper: string, editorZone: string}} */ - static get CSS(): { editorWrapper: string, editorZone: string } { + public static get CSS(): { editorWrapper: string; editorZone: string } { return { editorWrapper: 'codex-editor', editorZone: 'codex-editor__redactor', @@ -47,20 +49,47 @@ export default class SelectionUtils { /** * Returns selected anchor * {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorNode} - * @return {Node|null} + * + * @returns {Node|null} */ - static get anchorNode(): Node | null { + public static get anchorNode(): Node | null { const selection = window.getSelection(); return selection ? selection.anchorNode : null; } + /** + * Returns selected anchor element + * + * @returns {Element|null} + */ + public static get anchorElement(): Element | null { + const selection = window.getSelection(); + + if (!selection) { + return null; + } + + const anchorNode = selection.anchorNode; + + if (!anchorNode) { + return null; + } + + if (!$.isElement(anchorNode)) { + return anchorNode.parentElement; + } else { + return anchorNode; + } + } + /** * Returns selection offset according to the anchor node * {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorOffset} - * @return {Number|null} + * + * @returns {number|null} */ - static get anchorOffset(): number | null { + public static get anchorOffset(): number | null { const selection = window.getSelection(); return selection ? selection.anchorOffset : null; @@ -68,9 +97,10 @@ export default class SelectionUtils { /** * Is current selection range collapsed - * @return {boolean|null} + * + * @returns {boolean|null} */ - static get isCollapsed(): boolean | null { + public static get isCollapsed(): boolean | null { const selection = window.getSelection(); return selection ? selection.isCollapsed : null; @@ -78,9 +108,10 @@ export default class SelectionUtils { /** * Check current selection if it is at Editor's zone - * @return {boolean} + * + * @returns {boolean} */ - static get isAtEditor(): boolean { + public static get isAtEditor(): boolean { const selection = SelectionUtils.get(); /** @@ -93,6 +124,7 @@ export default class SelectionUtils { } let editorZone = null; + if (selectedNode) { editorZone = selectedNode.closest(`.${SelectionUtils.CSS.editorZone}`); } @@ -103,11 +135,21 @@ export default class SelectionUtils { return editorZone && editorZone.nodeType === Node.ELEMENT_NODE; } + /** + * Methods return boolean that true if selection exists on the page + */ + public static get isSelectionExists(): boolean { + const selection = SelectionUtils.get(); + + return !!selection.anchorNode; + } + /** * Return first range - * @return {Range|null} + * + * @returns {Range|null} */ - static get range(): Range { + public static get range(): Range | null { const selection = window.getSelection(); return selection && selection.rangeCount ? selection.getRangeAt(0) : null; @@ -115,11 +157,12 @@ export default class SelectionUtils { /** * Calculates position and size of selected text - * @return {{x, y, width, height, top?, left?, bottom?, right?}} + * + * @returns {DOMRect | ClientRect} */ - static get rect(): DOMRect | ClientRect { + public static get rect(): DOMRect | ClientRect { let sel: Selection | MSSelection = (document as Document).selection, - range: TextRange | Range; + range: TextRange | Range; let rect = { x: 0, @@ -141,6 +184,7 @@ export default class SelectionUtils { if (!window.getSelection) { _.log('Method window.getSelection is not supported', 'warn'); + return rect; } @@ -148,6 +192,11 @@ export default class SelectionUtils { if (sel.rangeCount === null || isNaN(sel.rangeCount)) { _.log('Method SelectionUtils.rangeCount is not supported', 'warn'); + + return rect; + } + + if (sel.rangeCount === 0) { return rect; } @@ -181,26 +230,24 @@ export default class SelectionUtils { /** * Returns selected text as String + * * @returns {string} */ - static get text(): string { + public static get text(): string { return window.getSelection ? window.getSelection().toString() : ''; } /** - * Returns window SelectionUtils - * {@link https://developer.mozilla.org/ru/docs/Web/API/Window/getSelection} - * @return {Selection} + * Selection instances + * + * @todo Check if this is still relevant */ - public static get(): Selection { - return window.getSelection(); - } - public instance: Selection = null; public selection: Selection = null; /** * This property can store SelectionUtils's range for restoring later + * * @type {Range|null} */ public savedSelectionRange: Range = null; @@ -208,7 +255,7 @@ export default class SelectionUtils { /** * Fake background is active * - * @return {boolean} + * @returns {boolean} */ public isFakeBackgroundEnabled = false; @@ -218,10 +265,53 @@ export default class SelectionUtils { private readonly commandBackground: string = 'backColor'; private readonly commandRemoveFormat: string = 'removeFormat'; + /** + * Returns window SelectionUtils + * {@link https://developer.mozilla.org/ru/docs/Web/API/Window/getSelection} + * + * @returns {Selection} + */ + public static get(): Selection { + return window.getSelection(); + } + + /** + * Set focus to contenteditable or native input element + * + * @param element - element where to set focus + * @param offset - offset of cursor + * + * @returns {DOMRect} of range + */ + public static setCursor(element: HTMLElement, offset = 0): DOMRect { + const range = document.createRange(); + const selection = window.getSelection(); + + /** if found deepest node is native input */ + if ($.isNativeInput(element)) { + if (!$.canSetCaret(element)) { + return; + } + + element.focus(); + element.selectionStart = element.selectionEnd = offset; + + return element.getBoundingClientRect(); + } + + range.setStart(element, offset); + range.setEnd(element, offset); + + selection.removeAllRanges(); + selection.addRange(range); + + return range.getBoundingClientRect(); + } + /** * Removes fake background */ - public removeFakeBackground() { + public removeFakeBackground(): void { if (!this.isFakeBackgroundEnabled) { return; } @@ -233,7 +323,7 @@ export default class SelectionUtils { /** * Sets fake background */ - public setFakeBackground() { + public setFakeBackground(): void { document.execCommand(this.commandBackground, false, '#a8d6ff'); this.isFakeBackgroundEnabled = true; @@ -267,13 +357,27 @@ export default class SelectionUtils { this.savedSelectionRange = null; } + /** + * Collapse current selection + */ + public collapseToEnd(): void { + const sel = window.getSelection(); + const range = document.createRange(); + + range.selectNodeContents(sel.focusNode); + range.collapse(false); + sel.removeAllRanges(); + sel.addRange(range); + } + /** * Looks ahead to find passed tag from current selection * - * @param {String} tagName - tag to found - * @param {String} [className] - tag's class name - * @param {Number} [searchDepth] - count of tags that can be included. For better performance. - * @return {HTMLElement|null} + * @param {string} tagName - tag to found + * @param {string} [className] - tag's class name + * @param {number} [searchDepth] - count of tags that can be included. For better performance. + * + * @returns {HTMLElement|null} */ public findParentTag(tagName: string, className?: string, searchDepth = 10): HTMLElement | null { const selection = window.getSelection(); @@ -346,7 +450,7 @@ export default class SelectionUtils { /** * Expands selection range to the passed parent node * - * @param {HTMLElement} element + * @param {HTMLElement} element - element which contents should be selcted */ public expandToTag(element: HTMLElement): void { const selection = window.getSelection(); diff --git a/src/components/tools/paragraph b/src/components/tools/paragraph index 698fdbe5a..4832182dc 160000 --- a/src/components/tools/paragraph +++ b/src/components/tools/paragraph @@ -1 +1 @@ -Subproject commit 698fdbe5a739043b69349e8ed8ff49788722feae +Subproject commit 4832182dcf3874cbaedcb789f682bd61782e49ad diff --git a/src/components/tools/stub/index.ts b/src/components/tools/stub/index.ts index 5721f7bfc..38f98b153 100644 --- a/src/components/tools/stub/index.ts +++ b/src/components/tools/stub/index.ts @@ -1,10 +1,25 @@ import $ from '../../dom'; -import {BlockTool, BlockToolData} from '../../../../types'; +import { API, BlockTool, BlockToolData, BlockToolConstructorOptions } from '../../../../types'; +export interface StubData extends BlockToolData { + title: string; + savedData: BlockToolData; +} + +/** + * This tool will be shown in place of a block without corresponding plugin + * It will store its data inside and pass it back with article saving + */ export default class Stub implements BlockTool { + /** + * Notify core that tool supports read-only mode + */ + public static isReadOnlySupported = true; + /** * Stub styles - * @type {{wrapper: string; info: string; title: string; subtitle: string}} + * + * @type {{wrapper: string, info: string, title: string, subtitle: string}} */ private CSS = { wrapper: 'ce-stub', @@ -18,6 +33,11 @@ export default class Stub implements BlockTool { */ private readonly wrapper: HTMLElement; + /** + * Editor.js API + */ + private readonly api: API; + /** * Stub title — tool name */ @@ -33,9 +53,15 @@ export default class Stub implements BlockTool { */ private readonly savedData: BlockToolData; - constructor({data, config, api}) { - this.title = data.title || 'Error'; - this.subtitle = 'The block can not be displayed correctly.'; + /** + * @param options - constructor options + * @param options.data - stub tool data + * @param options.api - Editor.js API + */ + constructor({ data, api }: BlockToolConstructorOptions) { + this.api = api; + this.title = data.title || this.api.i18n.t('Error'); + this.subtitle = this.api.i18n.t('The block can not be displayed correctly.'); this.savedData = data.savedData; this.wrapper = this.make(); @@ -43,7 +69,8 @@ export default class Stub implements BlockTool { /** * Returns stub holder - * @return {HTMLElement} + * + * @returns {HTMLElement} */ public render(): HTMLElement { return this.wrapper; @@ -51,7 +78,8 @@ export default class Stub implements BlockTool { /** * Return original Tool data - * @return {BlockToolData} + * + * @returns {BlockToolData} */ public save(): BlockToolData { return this.savedData; @@ -59,7 +87,8 @@ export default class Stub implements BlockTool { /** * Create Tool html markup - * @return {HTMLElement} + * + * @returns {HTMLElement} */ private make(): HTMLElement { const wrapper = $.make('div', this.CSS.wrapper); diff --git a/src/components/utils.ts b/src/components/utils.ts index 5bcf231f1..4634e590e 100644 --- a/src/components/utils.ts +++ b/src/components/utils.ts @@ -4,41 +4,121 @@ import Dom from './dom'; +/** + * Possible log levels + */ +export enum LogLevels { + VERBOSE = 'VERBOSE', + INFO = 'INFO', + WARN = 'WARN', + ERROR = 'ERROR', +} + /** * Allow to use global VERSION, that will be overwritten by Webpack */ declare const VERSION: string; /** - * @typedef {Object} ChainData - * @property {Object} data - data that will be passed to the success or fallback - * @property {Function} function - function's that must be called asynchronically + * @typedef {object} ChainData + * @property {object} data - data that will be passed to the success or fallback + * @property {Function} function - function's that must be called asynchronously + * + * @interface ChainData */ export interface ChainData { - data?: any; + data?: object; + // eslint-disable-next-line @typescript-eslint/no-explicit-any function: (...args: any[]) => any; } /** * Editor.js utils */ -export default class Util { - /** - * Custom logger - * - * @param {string} msg - message - * @param {string} type - logging type 'log'|'warn'|'error'|'info' - * @param {*} [args] - argument to log with a message - * @param {string} style - additional styling to message - */ - public static log(msg: string, type: string = 'log', args?: any, style: string = 'color: inherit'): void { - if ( !('console' in window) || !window.console[ type ] ) { - return; - } +/** + * Returns basic keycodes as constants + * + * @returns {{}} + */ +export const keyCodes = { + BACKSPACE: 8, + TAB: 9, + ENTER: 13, + SHIFT: 16, + CTRL: 17, + ALT: 18, + ESC: 27, + SPACE: 32, + LEFT: 37, + UP: 38, + DOWN: 40, + RIGHT: 39, + DELETE: 46, + META: 91, +}; + +/** + * Return mouse buttons codes + */ +export const mouseButtons = { + LEFT: 0, + WHEEL: 1, + RIGHT: 2, + BACKWARD: 3, + FORWARD: 4, +}; + +/** + * Custom logger + * + * @param {boolean} labeled — if true, Editor.js label is shown + * @param {string} msg - message + * @param {string} type - logging type 'log'|'warn'|'error'|'info' + * @param {*} [args] - argument to log with a message + * @param {string} style - additional styling to message + */ +function _log( + labeled: boolean, + msg: string, + type = 'log', + // eslint-disable-next-line @typescript-eslint/no-explicit-any + args?: any, + style = 'color: inherit' +): void { + if (!('console' in window) || !window.console[type]) { + return; + } + + const isSimpleType = ['info', 'log', 'warn', 'error'].includes(type); + const argsToPass = []; + + switch (_log.logLevel) { + case LogLevels.ERROR: + if (type !== 'error') { + return; + } + break; + + case LogLevels.WARN: + if (!['error', 'warn'].includes(type)) { + return; + } + break; + + case LogLevels.INFO: + if (!isSimpleType || labeled) { + return; + } + break; + } + + if (args) { + argsToPass.push(args); + } - const editorLabelText = `Editor.js ${VERSION}`; - const editorLabelStyle = `line-height: 1em; + const editorLabelText = `Editor.js ${VERSION}`; + const editorLabelStyle = `line-height: 1em; color: #006FEA; display: inline-block; font-size: 11px; @@ -49,293 +129,516 @@ export default class Util { border: 1px solid rgba(56, 138, 229, 0.16); margin: 4px 5px 4px 0;`; - try { - if (['time', 'timeEnd'].includes(type)) { - console[type](`( ${editorLabelText} ) ${msg}`); - } else if (args) { - console[type](`%c${editorLabelText}%c ${msg} %o`, editorLabelStyle, style, args); - } else { - console[type](`%c${editorLabelText}%c ${msg}`, editorLabelStyle, style); - } - } catch (ignored) {} - } - - /** - * Returns basic keycodes as constants - * @return {{}} - */ - static get keyCodes() { - return { - BACKSPACE: 8, - TAB: 9, - ENTER: 13, - SHIFT: 16, - CTRL: 17, - ALT: 18, - ESC: 27, - SPACE: 32, - LEFT: 37, - UP: 38, - DOWN: 40, - RIGHT: 39, - DELETE: 46, - META: 91, - }; + if (labeled) { + if (isSimpleType) { + argsToPass.unshift(editorLabelStyle, style); + msg = `%c${editorLabelText}%c ${msg}`; + } else { + msg = `( ${editorLabelText} )${msg}`; + } } - /** - * Fires a promise sequence asyncronically - * - * @param {ChainData[]} chains - list or ChainData's - * @param {Function} success - success callback - * @param {Function} fallback - callback that fires in case of errors - * - * @return {Promise} - */ - public static async sequence( - chains: ChainData[], - success: (data: any) => void = () => {}, - fallback: (data: any) => void = () => {}, - ): Promise { - /** - * Decorator - * - * @param {ChainData} chainData - * - * @param {Function} successCallback - * @param {Function} fallbackCallback - * - * @return {Promise} - */ - async function waitNextBlock( - chainData: ChainData, - successCallback: (data: any) => void, - fallbackCallback: (data: any) => void, - ): Promise { - try { - await chainData.function(chainData.data); - await successCallback(typeof chainData.data !== 'undefined' ? chainData.data : {}); - } catch (e) { - fallbackCallback(typeof chainData.data !== 'undefined' ? chainData.data : {}); - } + try { + if (!isSimpleType) { + console[type](msg); + } else if (args) { + console[type](`${msg} %o`, ...argsToPass); + } else { + console[type](msg, ...argsToPass); } + } catch (ignored) {} +} - /** - * pluck each element from queue - * First, send resolved Promise as previous value - * Each plugins "prepare" method returns a Promise, that's why - * reduce current element will not be able to continue while can't get - * a resolved Promise - */ - return await chains.reduce(async (previousValue, currentValue) => { - await previousValue; - return waitNextBlock(currentValue, success, fallback); - }, Promise.resolve()); - } +/** + * Current log level + */ +_log.logLevel = LogLevels.VERBOSE; - /** - * Make array from array-like collection - * - * @param {ArrayLike} collection - * - * @return {Array} - */ - public static array(collection: ArrayLike): any[] { - return Array.prototype.slice.call(collection); - } +/** + * Set current log level + * + * @param {LogLevels} logLevel - log level to set + */ +export function setLogLevel(logLevel: LogLevels): void { + _log.logLevel = logLevel; +} - /** - * Check if passed variable is a function - * @param {*} fn - * @return {boolean} - */ - public static isFunction(fn: any): boolean { - return typeof fn === 'function'; - } +/** + * _log method proxy without Editor.js label + */ +export const log = _log.bind(window, false); - /** - * Check if passed function is a class - * @param {function} fn - * @return {boolean} - */ - public static isClass(fn: any): boolean { - return typeof fn === 'function' && /^\s*class\s+/.test(fn.toString()); - } +/** + * _log method proxy with Editor.js label + */ +export const logLabeled = _log.bind(window, true); - /** - * Checks if object is empty - * - * @param {Object} object - * @return {boolean} - */ - public static isEmpty(object: object): boolean { - if (!object) { - return true; - } +/** + * Return string representation of the object type + * + * @param {*} object - object to get type + * + * @returns {string} + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function typeOf(object: any): string { + return Object.prototype.toString.call(object).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); +} - return Object.keys(object).length === 0 && object.constructor === Object; - } +/** + * Check if passed variable is a function + * + * @param {*} fn - function to check + * + * @returns {boolean} + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function isFunction(fn: any): fn is Function { + return typeOf(fn) === 'function'; +} - /** - * Check if passed object is a Promise - * @param {*} object - object to check - * @return {Boolean} - */ - public static isPromise(object: any): boolean { - return Promise.resolve(object) === object; - } +/** + * Checks if passed argument is an object + * + * @param {*} v - object to check + * + * @returns {boolean} + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function isObject(v: any): v is object { + return typeOf(v) === 'object'; +} - /** - * Delays method execution - * - * @param {Function} method - * @param {Number} timeout - */ - public static delay(method: (...args: any[]) => any, timeout: number) { - return function() { - const context = this, - args = arguments; +/** + * Checks if passed argument is a string + * + * @param {*} v - variable to check + * + * @returns {boolean} + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function isString(v: any): v is string { + return typeOf(v) === 'string'; +} - window.setTimeout(() => method.apply(context, args), timeout); - }; - } +/** + * Checks if passed argument is boolean + * + * @param {*} v - variable to check + * + * @returns {boolean} + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function isBoolean(v: any): v is boolean { + return typeOf(v) === 'boolean'; +} - /** - * Get file extension - * - * @param {File} file - * @return string - */ - public static getFileExtension(file: File): string { - return file.name.split('.').pop(); +/** + * Checks if passed argument is number + * + * @param {*} v - variable to check + * + * @returns {boolean} + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function isNumber(v: any): v is number { + return typeOf(v) === 'number'; +} + +/** + * Checks if passed argument is undefined + * + * @param {*} v - variable to check + * + * @returns {boolean} + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function isUndefined(v: any): v is undefined { + return typeOf(v) === 'undefined'; +} + +/** + * Check if passed function is a class + * + * @param {Function} fn - function to check + * + * @returns {boolean} + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function isClass(fn: any): boolean { + return isFunction(fn) && /^\s*class\s+/.test(fn.toString()); +} + +/** + * Checks if object is empty + * + * @param {object} object - object to check + * + * @returns {boolean} + */ +export function isEmpty(object: object): boolean { + if (!object) { + return true; } + return Object.keys(object).length === 0 && object.constructor === Object; +} + +/** + * Check if passed object is a Promise + * + * @param {*} object - object to check + * @returns {boolean} + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function isPromise(object: any): object is Promise { + return Promise.resolve(object) === object; +} + +/** + * Returns true if passed key code is printable (a-Z, 0-9, etc) character. + * + * @param {number} keyCode - key code + * + * @returns {boolean} + */ +export function isPrintableKey(keyCode: number): boolean { + return (keyCode > 47 && keyCode < 58) || // number keys + keyCode === 32 || keyCode === 13 || // Spacebar & return key(s) + keyCode === 229 || // processing key input for certain languages — Chinese, Japanese, etc. + (keyCode > 64 && keyCode < 91) || // letter keys + (keyCode > 95 && keyCode < 112) || // Numpad keys + (keyCode > 185 && keyCode < 193) || // ;=,-./` (in order) + (keyCode > 218 && keyCode < 223); // [\]' (in order) +} + +/** + * Fires a promise sequence asynchronously + * + * @param {ChainData[]} chains - list or ChainData's + * @param {Function} success - success callback + * @param {Function} fallback - callback that fires in case of errors + * + * @returns {Promise} + */ +export async function sequence( + chains: ChainData[], + // eslint-disable-next-line @typescript-eslint/no-empty-function + success: (data: object) => void = (): void => {}, + // eslint-disable-next-line @typescript-eslint/no-empty-function + fallback: (data: object) => void = (): void => {} +): Promise { /** - * Check if string is MIME type + * Decorator + * + * @param {ChainData} chainData - Chain data * - * @param {string} type - * @return boolean + * @param {Function} successCallback - success callback + * @param {Function} fallbackCallback - fail callback + * + * @returns {Promise} */ - public static isValidMimeType(type: string): boolean { - return /^[-\w]+\/([-+\w]+|\*)$/.test(type); + async function waitNextBlock( + chainData: ChainData, + successCallback: (data: object) => void, + fallbackCallback: (data: object) => void + ): Promise { + try { + await chainData.function(chainData.data); + await successCallback(!isUndefined(chainData.data) ? chainData.data : {}); + } catch (e) { + fallbackCallback(!isUndefined(chainData.data) ? chainData.data : {}); + } } /** - * Debouncing method - * Call method after passed time - * - * Note that this method returns Function and declared variable need to be called - * - * @param {Function} func - function that we're throttling - * @param {Number} wait - time in milliseconds - * @param {Boolean} immediate - call now - * @return {Function} + * pluck each element from queue + * First, send resolved Promise as previous value + * Each plugins "prepare" method returns a Promise, that's why + * reduce current element will not be able to continue while can't get + * a resolved Promise */ - public static debounce(func: () => void, wait?: number , immediate?: boolean): () => void { - let timeout; + return chains.reduce(async (previousValue, currentValue) => { + await previousValue; + + return waitNextBlock(currentValue, success, fallback); + }, Promise.resolve()); +} + +/** + * Make array from array-like collection + * + * @param {ArrayLike} collection - collection to convert to array + * + * @returns {Array} + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function array(collection: ArrayLike): any[] { + return Array.prototype.slice.call(collection); +} - return () => { - const context = this, +/** + * Delays method execution + * + * @param {Function} method - method to execute + * @param {number} timeout - timeout in ms + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function delay(method: (...args: any[]) => any, timeout: number) { + return function (): void { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const context = this, + // eslint-disable-next-line prefer-rest-params args = arguments; - const later = () => { - timeout = null; - if (!immediate) { - func.apply(context, args); - } - }; + window.setTimeout(() => method.apply(context, args), timeout); + }; +} + +/** + * Get file extension + * + * @param {File} file - file + * + * @returns {string} + */ +export function getFileExtension(file: File): string { + return file.name.split('.').pop(); +} - const callNow = immediate && !timeout; +/** + * Check if string is MIME type + * + * @param {string} type - string to check + * + * @returns {boolean} + */ +export function isValidMimeType(type: string): boolean { + return /^[-\w]+\/([-+\w]+|\*)$/.test(type); +} - window.clearTimeout(timeout); - timeout = window.setTimeout(later, wait); - if (callNow) { +/** + * Debouncing method + * Call method after passed time + * + * Note that this method returns Function and declared variable need to be called + * + * @param {Function} func - function that we're throttling + * @param {number} wait - time in milliseconds + * @param {boolean} immediate - call now + * @returns {Function} + */ +export function debounce(func: () => void, wait?: number, immediate?: boolean): () => void { + let timeout; + + return (): void => { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const context = this, + // eslint-disable-next-line prefer-rest-params + args = arguments; + + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type + const later = () => { + timeout = null; + if (!immediate) { func.apply(context, args); } }; - } - /** - * Copies passed text to the clipboard - * @param text - */ - public static copyTextToClipboard(text) { - const el = Dom.make('div', 'codex-editor-clipboard', { - innerHTML: text, - }); + const callNow = immediate && !timeout; - document.body.appendChild(el); + window.clearTimeout(timeout); + timeout = window.setTimeout(later, wait); + if (callNow) { + func.apply(context, args); + } + }; +} - const selection = window.getSelection(); - const range = document.createRange(); - range.selectNode(el); +/** + * Copies passed text to the clipboard + * + * @param text - text to copy + */ +export function copyTextToClipboard(text): void { + const el = Dom.make('div', 'codex-editor-clipboard', { + innerHTML: text, + }); - window.getSelection().removeAllRanges(); - selection.addRange(range); + document.body.appendChild(el); - document.execCommand('copy'); - document.body.removeChild(el); - } + const selection = window.getSelection(); + const range = document.createRange(); - /** - * Returns object with os name as key and boolean as value. Shows current user OS - * - * @return {[key: string]: boolean} - */ - public static getUserOS(): {[key: string]: boolean} { - const OS = { - win: false, - mac: false, - x11: false, - linux: false, - }; + range.selectNode(el); - const userOS = Object.keys(OS).find((os: string) => navigator.appVersion.toLowerCase().indexOf(os) !== -1); + window.getSelection().removeAllRanges(); + selection.addRange(range); - if (userOS) { - OS[userOS] = true; - return OS; - } + document.execCommand('copy'); + document.body.removeChild(el); +} + +/** + * Returns object with os name as key and boolean as value. Shows current user OS + */ +export function getUserOS(): {[key: string]: boolean} { + const OS = { + win: false, + mac: false, + x11: false, + linux: false, + }; + + const userOS = Object.keys(OS).find((os: string) => navigator.appVersion.toLowerCase().indexOf(os) !== -1); + + if (userOS) { + OS[userOS] = true; return OS; } - /** - * Capitalizes first letter of the string - * @param {string} text - * @return {string} - */ - public static capitalize(text: string): string { - return text[0].toUpperCase() + text.slice(1); + return OS; +} + +/** + * Capitalizes first letter of the string + * + * @param {string} text - text to capitalize + * + * @returns {string} + */ +export function capitalize(text: string): string { + return text[0].toUpperCase() + text.slice(1); +} + +/** + * Merge to objects recursively + * + * @param {object} target - merge target + * @param {object[]} sources - merge sources + * @returns {object} + */ +export function deepMerge(target, ...sources): T { + if (!sources.length) { + return target; } + const source = sources.shift(); - /** - * Merge to objects recursively - * @param {object} target - * @param {object[]} sources - * @return {object} - */ - public static deepMerge(target, ...sources) { - const isObject = (item) => item && typeof item === 'object' && !Array.isArray(item); - - if (!sources.length) { return target; } - const source = sources.shift(); - - if (isObject(target) && isObject(source)) { - for (const key in source) { - if (isObject(source[key])) { - if (!target[key]) { - Object.assign(target, { [key]: {} }); - } - - Util.deepMerge(target[key], source[key]); - } else { - Object.assign(target, { [key]: source[key] }); + if (isObject(target) && isObject(source)) { + for (const key in source) { + if (isObject(source[key])) { + if (!target[key]) { + Object.assign(target, { [key]: {} }); } + + deepMerge(target[key], source[key]); + } else { + Object.assign(target, { [key]: source[key] }); } } + } - return Util.deepMerge(target, ...sources); + return deepMerge(target, ...sources); +} + +/** + * Return true if current device supports touch events + * + * Note! This is a simple solution, it can give false-positive results. + * To detect touch devices more carefully, use 'touchstart' event listener + * + * @see http://www.stucox.com/blog/you-cant-detect-a-touchscreen/ + * + * @returns {boolean} + */ +export const isTouchSupported: boolean = 'ontouchstart' in document.documentElement; + +/** + * Make shortcut command more human-readable + * + * @param {string} shortcut — string like 'CMD+B' + */ +export function beautifyShortcut(shortcut: string): string { + const OS = getUserOS(); + + shortcut = shortcut + .replace(/shift/gi, '⇧') + .replace(/backspace/gi, '⌫') + .replace(/enter/gi, '⏎') + .replace(/up/gi, '↑') + .replace(/left/gi, '→') + .replace(/down/gi, '↓') + .replace(/right/gi, '←') + .replace(/escape/gi, '⎋') + .replace(/insert/gi, 'Ins') + .replace(/delete/gi, '␡') + .replace(/\+/gi, ' + '); + + if (OS.mac) { + shortcut = shortcut.replace(/ctrl|cmd/gi, '⌘').replace(/alt/gi, '⌥'); + } else { + shortcut = shortcut.replace(/cmd/gi, 'Ctrl').replace(/windows/gi, 'WIN'); + } + + return shortcut; +} + +/** + * Returns valid URL. If it is going outside and valid, it returns itself + * If url has `one slash`, then it concatenates with window location origin + * or when url has `two lack` it appends only protocol + * + * @param {string} url - url to prettify + */ +export function getValidUrl(url: string): string { + try { + const urlObject = new URL(url); + + return urlObject.href; + } catch (e) { + // do nothing but handle below + } + + if (url.substring(0, 2) === '//') { + return window.location.protocol + url; + } else { + return window.location.origin + url; } +} +/** + * Opens new Tab with passed URL + * + * @param {string} url - URL address to redirect + */ +export function openTab(url: string): void { + window.open(url, '_blank'); +} + +/** + * Returns random generated identifier + * + * @param {string} prefix - identifier prefix + * + * @returns {string} + */ +export function generateId(prefix = ''): string { + // tslint:disable-next-line:no-bitwise + return `${prefix}${(Math.floor(Math.random() * 1e8)).toString(16)}`; +} + +/** + * Common method for printing a warning about the usage of deprecated property or method. + * + * @param condition - condition for deprecation. + * @param oldProperty - deprecated property. + * @param newProperty - the property that should be used instead. + */ +export function deprecationAssert(condition: boolean, oldProperty: string, newProperty: string): void { + const message = `«${oldProperty}» is deprecated and will be removed in the next major release. Please use the «${newProperty}» instead.`; + + if (condition) { + logLabeled(message, 'warn'); + } } diff --git a/src/components/utils/events.ts b/src/components/utils/events.ts new file mode 100644 index 000000000..10d501ece --- /dev/null +++ b/src/components/utils/events.ts @@ -0,0 +1,104 @@ +/** + * @class EventDispatcher + * + * Has two important methods: + * - {Function} on - appends subscriber to the event. If event doesn't exist - creates new one + * - {Function} emit - fires all subscribers with data + * - {Function off - unsubscribes callback + * + * @version 1.0.0 + * + * @typedef {Events} Events + * @property {object} subscribers - all subscribers grouped by event name + */ +export default class EventsDispatcher { + /** + * Object with events` names as key and array of callback functions as value + * + * @type {{}} + */ + private subscribers: {[name: string]: Array<(data?: object) => object>} = {}; + + /** + * Subscribe any event on callback + * + * @param {string} eventName - event name + * @param {Function} callback - subscriber + */ + public on(eventName: string, callback: (data: object) => object): void { + if (!(eventName in this.subscribers)) { + this.subscribers[eventName] = []; + } + + // group by events + this.subscribers[eventName].push(callback); + } + + /** + * Subscribe any event on callback. Callback will be called once and be removed from subscribers array after call. + * + * @param {string} eventName - event name + * @param {Function} callback - subscriber + */ + public once(eventName: string, callback: (data: object) => object): void { + if (!(eventName in this.subscribers)) { + this.subscribers[eventName] = []; + } + + const wrappedCallback = (data: object): object => { + const result = callback(data); + + const indexOfHandler = this.subscribers[eventName].indexOf(wrappedCallback); + + if (indexOfHandler !== -1) { + this.subscribers[eventName].splice(indexOfHandler, 1); + } + + return result; + }; + + // group by events + this.subscribers[eventName].push(wrappedCallback); + } + + /** + * Emit callbacks with passed data + * + * @param {string} eventName - event name + * @param {object} data - subscribers get this data when they were fired + */ + public emit(eventName: string, data?: object): void { + if (!this.subscribers[eventName]) { + return; + } + + this.subscribers[eventName].reduce((previousData, currentHandler) => { + const newData = currentHandler(previousData); + + return newData || previousData; + }, data); + } + + /** + * Unsubscribe callback from event + * + * @param {string} eventName - event name + * @param {Function} callback - event handler + */ + public off(eventName: string, callback: (data: object) => object): void { + for (let i = 0; i < this.subscribers[eventName].length; i++) { + if (this.subscribers[eventName][i] === callback) { + delete this.subscribers[eventName][i]; + break; + } + } + } + + /** + * Destroyer + * clears subsribers list + */ + public destroy(): void { + this.subscribers = null; + } +} diff --git a/src/components/utils/listeners.ts b/src/components/utils/listeners.ts new file mode 100644 index 000000000..e0e356094 --- /dev/null +++ b/src/components/utils/listeners.ts @@ -0,0 +1,249 @@ +import * as _ from '../utils'; + +/** + * Event listener information + * + * @interface ListenerData + */ +export interface ListenerData { + /** + * Listener unique identifier + */ + id: string; + + /** + * Element where to listen to dispatched events + */ + element: EventTarget; + + /** + * Event to listen + */ + eventType: string; + + /** + * Event handler + * + * @param {Event} event - event object + */ + handler: (event: Event) => void; + + /** + * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener + */ + options: boolean | AddEventListenerOptions; +} + +/** + * Editor.js Listeners helper + * + * Decorator for event listeners assignment + * + * @author Codex Team + * @version 2.0.0 + */ + +/** + * @typedef {Listeners} Listeners + * @property {ListenerData[]} allListeners - listeners store + */ +export default class Listeners { + /** + * Stores all listeners data to find/remove/process it + * + * @type {ListenerData[]} + */ + private allListeners: ListenerData[] = []; + + /** + * Assigns event listener on element and returns unique identifier + * + * @param {EventTarget} element - DOM element that needs to be listened + * @param {string} eventType - event type + * @param {Function} handler - method that will be fired on event + * @param {boolean|AddEventListenerOptions} options - useCapture or {capture, passive, once} + * + * @returns {string} + */ + public on( + element: EventTarget, + eventType: string, + handler: (event: Event) => void, + options: boolean | AddEventListenerOptions = false + ): string { + const id = _.generateId('l'); + const assignedEventData = { + id, + element, + eventType, + handler, + options, + }; + + const alreadyExist = this.findOne(element, eventType, handler); + + if (alreadyExist) { + return; + } + + this.allListeners.push(assignedEventData); + element.addEventListener(eventType, handler, options); + + return id; + } + + /** + * Removes event listener from element + * + * @param {EventTarget} element - DOM element that we removing listener + * @param {string} eventType - event type + * @param {Function} handler - remove handler, if element listens several handlers on the same event type + * @param {boolean|AddEventListenerOptions} options - useCapture or {capture, passive, once} + */ + public off( + element: EventTarget, + eventType: string, + handler?: (event: Event) => void, + options?: boolean | AddEventListenerOptions + ): void { + const existingListeners = this.findAll(element, eventType, handler); + + existingListeners.forEach((listener, i) => { + const index = this.allListeners.indexOf(existingListeners[i]); + + if (index > -1) { + this.allListeners.splice(index, 1); + + listener.element.removeEventListener(listener.eventType, listener.handler, listener.options); + } + }); + } + + /** + * Removes listener by id + * + * @param {string} id - listener identifier + */ + public offById(id: string): void { + const listener = this.findById(id); + + if (!listener) { + return; + } + + listener.element.removeEventListener(listener.eventType, listener.handler, listener.options); + } + + /** + * Finds and returns first listener by passed params + * + * @param {EventTarget} element - event target + * @param {string} [eventType] - event type + * @param {Function} [handler] - event handler + * + * @returns {ListenerData|null} + */ + public findOne(element: EventTarget, eventType?: string, handler?: (event: Event) => void): ListenerData { + const foundListeners = this.findAll(element, eventType, handler); + + return foundListeners.length > 0 ? foundListeners[0] : null; + } + + /** + * Return all stored listeners by passed params + * + * @param {EventTarget} element - event target + * @param {string} eventType - event type + * @param {Function} handler - event handler + * + * @returns {ListenerData[]} + */ + public findAll(element: EventTarget, eventType?: string, handler?: (event: Event) => void): ListenerData[] { + let found; + const foundByEventTargets = element ? this.findByEventTarget(element) : []; + + if (element && eventType && handler) { + found = foundByEventTargets.filter((event) => event.eventType === eventType && event.handler === handler); + } else if (element && eventType) { + found = foundByEventTargets.filter((event) => event.eventType === eventType); + } else { + found = foundByEventTargets; + } + + return found; + } + + /** + * Removes all listeners + */ + public removeAll(): void { + this.allListeners.map((current) => { + current.element.removeEventListener(current.eventType, current.handler, current.options); + }); + + this.allListeners = []; + } + + /** + * Module cleanup on destruction + */ + public destroy(): void { + this.removeAll(); + } + + /** + * Search method: looks for listener by passed element + * + * @param {EventTarget} element - searching element + * + * @returns {Array} listeners that found on element + */ + private findByEventTarget(element: EventTarget): ListenerData[] { + return this.allListeners.filter((listener) => { + if (listener.element === element) { + return listener; + } + }); + } + + /** + * Search method: looks for listener by passed event type + * + * @param {string} eventType - event type + * + * @returns {ListenerData[]} listeners that found on element + */ + private findByType(eventType: string): ListenerData[] { + return this.allListeners.filter((listener) => { + if (listener.eventType === eventType) { + return listener; + } + }); + } + + /** + * Search method: looks for listener by passed handler + * + * @param {Function} handler - event handler + * + * @returns {ListenerData[]} listeners that found on element + */ + private findByHandler(handler: (event: Event) => void): ListenerData[] { + return this.allListeners.filter((listener) => { + if (listener.handler === handler) { + return listener; + } + }); + } + + /** + * Returns listener data found by id + * + * @param {string} id - listener identifier + * + * @returns {ListenerData} + */ + private findById(id: string): ListenerData { + return this.allListeners.find((listener) => listener.id === id); + } +} diff --git a/src/components/utils/shortcuts.ts b/src/components/utils/shortcuts.ts new file mode 100644 index 000000000..3e45210f5 --- /dev/null +++ b/src/components/utils/shortcuts.ts @@ -0,0 +1,107 @@ +import Shortcut from '@codexteam/shortcuts'; + +/** + * Contains keyboard and mouse events binded on each Block by Block Manager + */ + +/** + * ShortcutData interface + * Each shortcut must have name and handler + * `name` is a shortcut, like 'CMD+K', 'CMD+B' etc + * `handler` is a callback + * + * @interface ShortcutData + */ +export interface ShortcutData { + + /** + * Shortcut name + * Ex. CMD+I, CMD+B .... + */ + name: string; + + /** + * Shortcut handler + */ + handler(event): void; + + /** + * Element handler should be added for + */ + on: HTMLElement; +} + +/** + * @class Shortcut + * @classdesc Allows to register new shortcut + * + * Internal Shortcuts Module + */ +class Shortcuts { + /** + * All registered shortcuts + * + * @type {Map} + */ + private registeredShortcuts: Map = new Map(); + + /** + * Register shortcut + * + * @param shortcut - shortcut options + */ + public add(shortcut: ShortcutData): void { + const foundShortcut = this.findShortcut(shortcut.on, shortcut.name); + + if (foundShortcut) { + throw Error( + `Shortcut ${shortcut.name} is already registered for ${shortcut.on}. Please remove it before add a new handler.` + ); + } + + const newShortcut = new Shortcut({ + name: shortcut.name, + on: shortcut.on, + callback: shortcut.handler, + }); + const shortcuts = this.registeredShortcuts.get(shortcut.on) || []; + + this.registeredShortcuts.set(shortcut.on, [...shortcuts, newShortcut]); + } + + /** + * Remove shortcut + * + * @param element - Element shortcut is set for + * @param name - shortcut name + */ + public remove(element: Element, name: string): void { + const shortcut = this.findShortcut(element, name); + + if (!shortcut) { + return; + } + + shortcut.remove(); + + const shortcuts = this.registeredShortcuts.get(element); + + this.registeredShortcuts.set(element, shortcuts.filter(el => el !== shortcut)); + } + + /** + * Get Shortcut instance if exist + * + * @param element - Element shorcut is set for + * @param shortcut - shortcut name + * + * @returns {number} index - shortcut index if exist + */ + private findShortcut(element: Element, shortcut: string): Shortcut | void { + const shortcuts = this.registeredShortcuts.get(element) || []; + + return shortcuts.find(({ name }) => name === shortcut); + } +} + +export default new Shortcuts(); diff --git a/src/styles/animations.css b/src/styles/animations.css index cb63a422e..fced4886d 100644 --- a/src/styles/animations.css +++ b/src/styles/animations.css @@ -78,3 +78,42 @@ } } +@keyframes buttonClicked { + from, + 20%, + 40%, + 60%, + 80%, + to { + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + 0% { + transform: scale3d(0.95, 0.95, 0.95); + } + + 60% { + transform: scale3d(1.02, 1.02, 1.02); + } + + 80% { + transform: scale3d(1, 1, 1); + } +} + +@keyframes panelShowing { + from { + opacity: 0; + transform: translateY(-8px) scale(0.9); + } + + 70% { + opacity: 1; + transform: translateY(2px); + } + + to { + + transform: translateY(0); + } +} diff --git a/src/styles/block.css b/src/styles/block.css index 89801f4d8..55bbc142b 100644 --- a/src/styles/block.css +++ b/src/styles/block.css @@ -3,23 +3,16 @@ margin-top: 0; } - &--focused { - background-image: linear-gradient(17deg, rgba(243, 248, 255, 0.03) 63.45%, rgba(207, 214, 229, 0.27) 98%); - border-radius: 3px; - - @media (--mobile){ - background-image: none; - background-color: rgba(200, 199, 219, 0.17); - margin: 0 -10px; - padding: 0 10px; - } - } - &--selected &__content { background: var(--selectionColor); - box-shadow: 0 31px 23px -22px rgba(175, 220, 255, 1); - animation: selectionBounce 0.2s 1; - animation-fill-mode: forwards; + + /** + * Workaround Safari case when user can select inline-fragment with cross-block-selection + */ + & [contenteditable] { + -webkit-user-select: none; + user-select: none; + } img, .ce-stub { @@ -35,6 +28,7 @@ position: relative; max-width: var(--content-width); margin: 0 auto; + transition: background-color 150ms ease; } &--drop-target &__content { @@ -83,7 +77,6 @@ } } - .codex-editor--narrow .ce-block--focused { @media (--not-mobile) { margin-right: calc(var(--narrow-mode-right-padding) * -1); diff --git a/src/styles/conversion-toolbar.css b/src/styles/conversion-toolbar.css new file mode 100644 index 000000000..0676ecb01 --- /dev/null +++ b/src/styles/conversion-toolbar.css @@ -0,0 +1,94 @@ +.ce-conversion-toolbar { + @apply --overlay-pane; + + opacity: 0; + visibility: hidden; + will-change: transform, opacity; + transition: transform 100ms ease, opacity 100ms ease; + transform: translateY(-8px); + left: -1px; + width: 150px; + margin-top: 5px; + box-sizing: content-box; + + &--showed { + opacity: 1; + visibility: visible; + transform: none; + } + + [hidden] { + display: none !important; + } + + &__buttons { + display: flex; + } + + &__label { + color: var(--grayText); + font-size: 11px; + font-weight: 500; + letter-spacing: 0.33px; + padding: 10px 10px 5px; + text-transform: uppercase; + } +} + +.ce-conversion-tool { + display: flex; + padding: 5px 10px; + font-size: 14px; + line-height: 20px; + font-weight: 500; + cursor: pointer; + align-items: center; + + &--hidden { + display: none; + } + + &--focused { + box-shadow: inset 0 0 0px 1px rgba(7, 161, 227, 0.08); + background: rgba(34, 186, 255, 0.08) !important; + + &-animated { + animation-name: buttonClicked; + animation-duration: 250ms; + } + } + + &:hover { + background: var(--bg-light); + } + + &__icon { + display: inline-flex; + width: 20px; + height: 20px; + border: 1px solid var(--color-gray-border); + border-radius: 3px; + align-items: center; + justify-content: center; + margin-right: 10px; + background: #fff; + + svg { + width: 11px; + height: 11px; + } + } + + &--last { + margin-right: 0 !important; + } + + &--active { + color: var(--color-active-icon) !important; + } + + &--active { + animation: bounceIn 0.75s 1; + animation-fill-mode: forwards; + } +} diff --git a/src/styles/export.css b/src/styles/export.css index 98cb8b7e7..582e900bf 100644 --- a/src/styles/export.css +++ b/src/styles/export.css @@ -2,7 +2,7 @@ * Block Tool wrapper */ .cdx-block { - padding: 0.7em 0; + padding: 0.4em 0; } /** @@ -16,6 +16,18 @@ outline: none; width: 100%; box-sizing: border-box; + + /** + * Workaround Firefox bug with cursor position on empty content editable elements with ::before pseudo + * https://bugzilla.mozilla.org/show_bug.cgi?id=904846 + */ + &[data-placeholder]::before { + position: static !important; + display: inline-block; + width: 0; + white-space: nowrap; + pointer-events: none; + } } /** @@ -25,11 +37,11 @@ @apply --toolbar-button; &:not(:nth-child(3n+3)) { - margin-right: 5px; + margin-right: 3px; } &:nth-child(n+4) { - margin-top: 5px; + margin-top: 3px; } &--active { diff --git a/src/styles/inline-toolbar.css b/src/styles/inline-toolbar.css index 90c32df65..2a0837a73 100644 --- a/src/styles/inline-toolbar.css +++ b/src/styles/inline-toolbar.css @@ -1,42 +1,109 @@ .ce-inline-toolbar { @apply --overlay-pane; - padding: 6px; - transform: translateX(-50%); - display: none; - box-shadow: 0 6px 12px -6px rgba(131, 147, 173, 0.46), - 5px -12px 34px -13px rgba(97, 105, 134, 0.6), - 0 26px 52px 3px rgba(147, 165, 186, 0.24); + transform: translateX(-50%) translateY(8px) scale(0.9); + opacity: 0; + visibility: hidden; + transition: transform 150ms ease, opacity 250ms ease; + will-change: transform, opacity; + top: 0; + left: 0; &--showed { - display: block; + opacity: 1; + visibility: visible; + transform: translateX(-50%) + } + + &--left-oriented { + transform: translateX(-23px) translateY(8px) scale(0.9); + } + + &--left-oriented&--showed { + transform: translateX(-23px); + } + + &--right-oriented { + transform: translateX(-100%) translateY(8px) scale(0.9); + margin-left: 23px; + } + + &--right-oriented&--showed { + transform: translateX(-100%); } [hidden] { display: none !important; } + &__toggler-and-button-wrapper { + display: flex; + width: 100%; + padding: 0 6px; + } + &__buttons { display: flex; } + + &__actions { + } + + &__dropdown { + display: inline-flex; + height: var(--toolbar-buttons-size); + padding: 0 9px 0 10px; + margin: 0 6px 0 -6px; + align-items: center; + cursor: pointer; + border-right: 1px solid var(--color-gray-border); + + &:hover { + background: var(--bg-light); + } + + &--hidden { + display: none; + } + + &-content{ + display: flex; + font-weight: 500; + font-size: 14px; + + svg { + height: 12px; + } + } + + .icon--toggler-down { + margin-left: 4px; + } + } + + &__shortcut { + opacity: 0.6; + word-spacing: -3px; + margin-top: 3px; + } } .ce-inline-tool { @apply --toolbar-button; + border-radius: 0; line-height: normal; + width: auto; + padding: 0 5px !important; + min-width: 24px; &:not(:last-of-type) { - margin-right: 5px; + margin-right: 2px; } - &--last { - margin-right: 0 !important; + .icon { + height: 12px; } &--link { - .icon { - margin-top: -2px; - } - .icon--unlink { display: none; } @@ -48,20 +115,22 @@ } .icon--unlink { display: inline-block; + margin-bottom: -1px; } } &-input { - background-color: var(--bg-light); outline: none; border: 0; - border-radius: 3px; - margin: 6px 0 0; + border-radius: 0 0 4px 4px; + margin: 0; font-size: 13px; - padding: 8px; + padding: 10px; width: 100%; box-sizing: border-box; display: none; + font-weight: 500; + border-top: 1px solid rgba(201,201,204,.48); &::placeholder { color: var(--grayText); diff --git a/src/styles/main.css b/src/styles/main.css index 8f2f52e7e..94fa26bd1 100644 --- a/src/styles/main.css +++ b/src/styles/main.css @@ -3,8 +3,10 @@ @import './toolbar.css'; @import './toolbox.css'; @import './inline-toolbar.css'; +@import './conversion-toolbar.css'; @import './settings.css'; @import './block.css'; @import './animations.css'; @import './export.css'; @import './stub.css'; +@import './rtl.css'; diff --git a/src/styles/rtl.css b/src/styles/rtl.css new file mode 100644 index 000000000..f65cce74a --- /dev/null +++ b/src/styles/rtl.css @@ -0,0 +1,82 @@ +.codex-editor.codex-editor--rtl { + direction: rtl; + + .cdx-list { + padding-left: 0; + padding-right: 40px; + } + + .ce-toolbar { + &__plus { + right: calc(var(--toolbox-buttons-size) * -1); + left: auto; + } + + &__actions { + right: auto; + left: calc(var(--toolbox-buttons-size) * -1); + + @media (--mobile){ + margin-left: 0; + margin-right: auto; + padding-right: 0; + padding-left: 10px; + } + } + } + + .ce-settings { + left: 5px; + right: auto; + + &::before{ + right: auto; + left: 25px; + } + + &__button { + &:not(:nth-child(3n+3)) { + margin-left: 3px; + margin-right: 0; + } + } + } + + .ce-conversion-tool { + &__icon { + margin-right: 0px; + margin-left: 10px; + } + } + + .ce-inline-toolbar { + &__dropdown { + border-right: 0px solid transparent; + border-left: 1px solid var(--color-gray-border); + margin: 0 -6px 0 6px; + + .icon--toggler-down { + margin-left: 0px; + margin-right: 4px; + } + } + } + +} + +.codex-editor--narrow.codex-editor--rtl { + .ce-toolbar__plus { + @media (--not-mobile) { + left: 0px; + right: 5px; + } + } + + .ce-toolbar__actions { + @media (--not-mobile) { + left: -5px; + } + } +} + + diff --git a/src/styles/settings.css b/src/styles/settings.css index 651a95960..e7171c246 100644 --- a/src/styles/settings.css +++ b/src/styles/settings.css @@ -1,11 +1,13 @@ .ce-settings { @apply --overlay-pane; - right: 5px; - top: 35px; - min-width: 124px; + right: -1px; + top: 30px; + min-width: 114px; + box-sizing: content-box; @media (--mobile){ - bottom: 50px; + bottom: 40px; + right: -11px; top: auto; } @@ -23,19 +25,19 @@ &--opened { display: block; - animation-duration: 0.5s; - animation-name: bounceIn; + animation-duration: 0.1s; + animation-name: panelShowing; } &__plugin-zone { &:not(:empty){ - padding: 6px 6px 0; + padding: 3px 3px 0; } } &__default-zone { &:not(:empty){ - padding: 6px; + padding: 3px; } } @@ -43,11 +45,11 @@ @apply --toolbar-button; &:not(:nth-child(3n+3)) { - margin-right: 5px; + margin-right: 3px; } &:nth-child(n+4) { - margin-top: 5px; + margin-top: 3px; } line-height: 32px; @@ -72,7 +74,7 @@ } &--confirm { - background-color: var(--color-confirm); + background-color: var(--color-confirm) !important; color: #fff; &:hover { diff --git a/src/styles/toolbar.css b/src/styles/toolbar.css index ac77f7fc3..955ca7d73 100644 --- a/src/styles/toolbar.css +++ b/src/styles/toolbar.css @@ -10,16 +10,9 @@ display: none; @media (--mobile) { - position: fixed; - bottom: 0; - top: auto; - left: 0; - right: 0; - z-index: 9; - height: 50px; - background: #fff; - box-shadow: 0 -2px 12px rgba(60, 67, 81, 0.18); - transform: none !important; + @apply --overlay-pane; + padding: 3px; + margin-top: 5px; } &--opened { @@ -39,9 +32,7 @@ display: flex; align-content: center; margin: 0; - padding: 0 10px; - max-width: calc(100% - 70px); - overflow-x: auto; + max-width: calc(100% - 35px); } } @@ -50,13 +41,22 @@ position: absolute; left: calc(var(--toolbox-buttons-size) * -1); + flex-shrink: 0; + + &-shortcut { + opacity: 0.6; + word-spacing: -2px; + margin-top: 5px; + } &--hidden { display: none; } @media (--mobile){ - display: none !important; + display: inline-flex !important; + position: static; + transform: none !important; } } @@ -72,14 +72,15 @@ */ &__actions { position: absolute; - right: 0; - top: 10px; - padding-right: 16px; + right: -30px; + top: 5px; opacity: 0; @media (--mobile){ - position: static; - margin-left: auto; + position: absolute; + right: -28px; + top: 50%; + transform: translateY(-50%); display: flex; align-items: center; } @@ -94,11 +95,23 @@ } &__settings-btn { - display: inline-block; - width: 24px; - height: 24px; + display: flex; + align-items: center; + justify-content: center; + width: 18px; + height: 18px; color: var(--grayText); cursor: pointer; + background: var(--bg-light); + user-select: none; + + &:hover { + color: var(--color-dark); + } + + @media (--mobile){ + background: transparent; + } } } diff --git a/src/styles/toolbox.css b/src/styles/toolbox.css index bb5feb79a..ab4c11915 100644 --- a/src/styles/toolbox.css +++ b/src/styles/toolbox.css @@ -10,7 +10,7 @@ position: static; transform: none !important; align-items: center; - visibility: visible !important; + overflow-x: auto; } &--opened { @@ -20,54 +20,18 @@ &__button { @apply --toolbox-button; + flex-shrink: 0; } +} - &__tooltip { - position: absolute; - top: 25px; - padding: 6px 10px; - border-radius: 5px; - line-height: 21px; - opacity: 0; - background: var(--bg-light); - box-shadow: 0 10px 12px -9px rgba(26, 39, 54, 0.32), 0 3px 2px -2px rgba(33, 48, 73, 0.05); - color: #5C6174; - font-size: 12px; - text-align: center; - user-select: none; - pointer-events: none; - transition: opacity 150ms ease-in, left 0.1s linear; - will-change: opacity, left; - letter-spacing: 0.02em; - line-height: 1em; - - &-shortcut { - color: rgba(100, 105, 122, 0.6); - word-spacing: -2px; - margin-top: 5px; - } - - &--shown { - opacity: 1; - transition-delay: 0.1s, 0s; - } - - &::before { - content: ''; - width: 10px; - height: 10px; - position: absolute; - top: -5px; - left: 50%; - margin-left: -5px; - transform: rotate(-45deg); - background-color: var(--bg-light); - z-index: -1; - } +.ce-toolbox-button-tooltip { + &__shortcut { + opacity: 0.6; + word-spacing: -3px; + margin-top: 3px; } } - /** * Styles for Narrow mode */ diff --git a/src/styles/ui.css b/src/styles/ui.css index b04d2ecda..4a240994b 100644 --- a/src/styles/ui.css +++ b/src/styles/ui.css @@ -11,11 +11,17 @@ } &__redactor { - padding-bottom: 300px; - &--hidden { display: none; } + + /** + * Workaround firefox bug: empty content editable elements has collapsed height + * https://bugzilla.mozilla.org/show_bug.cgi?id=1098151#c18 + */ + [contenteditable]:empty::after { + content: "\feff "; + } } /** @@ -27,6 +33,13 @@ } } + &--narrow&--rtl &__redactor { + @media (--not-mobile) { + margin-left: var(--narrow-mode-right-padding); + margin-right: 0; + } + } + &--narrow .ce-toolbar__actions { @media (--not-mobile) { right: -5px; @@ -98,25 +111,11 @@ * Set color for native selection */ ::selection{ - background-color: var(--selectionColor); -} - -/** - * Add placeholder to content editable elements with data attribute - * data-placeholder="Hello world!" - */ -[contentEditable=true][data-placeholder]:empty::before{ - content: attr(data-placeholder); - color: var(--grayText); - font-weight: normal; -} - -[contentEditable=true][data-placeholder]:empty:focus::before { - opacity: 0.3; + background-color: var(--inlineSelectionColor); } .codex-editor--toolbox-opened [contentEditable=true][data-placeholder]:focus::before { - opacity: 0; + opacity: 0 !important; } @keyframes editor-loader-spin { diff --git a/src/styles/variables.css b/src/styles/variables.css index 48e08c622..42e749cbb 100644 --- a/src/styles/variables.css +++ b/src/styles/variables.css @@ -5,7 +5,8 @@ /** * Selection color */ - --selectionColor: #a8d6ff; + --selectionColor: #e1f2ff; + --inlineSelectionColor: #d4ecff; /** * Toolbar buttons @@ -17,6 +18,11 @@ */ --grayText: #707684; + /** + * Gray icons hover + */ + --color-dark: #1D202B; + /** * Blue icons */ @@ -56,21 +62,29 @@ --overlay-pane: { position: absolute; background-color: #FFFFFF; - box-shadow: 0 8px 23px -6px rgba(21,40,54,0.31), 22px -14px 34px -18px rgba(33,48,73,0.26); + border: 1px solid #EAEAEA; + box-shadow: 0 3px 15px -3px rgba(13,20,33,0.13); border-radius: 4px; z-index: 2; - &::before { - content: ''; - width: 15px; - height: 15px; - position: absolute; - top: -7px; - left: 50%; - margin-left: -7px; - transform: rotate(-45deg); - background-color: #fff; - z-index: -1; + @media (--mobile){ + box-shadow: 0 13px 7px -5px rgba(26, 38, 49, 0.09),6px 15px 34px -6px rgba(33, 48, 73, 0.29); + border-bottom-color: #d5d7db; + } + + &--left-oriented { + &::before { + left: 15px; + margin-left: 0; + } + } + + &--right-oriented { + &::before { + left: auto; + right: 15px; + margin-left: 0; + } } }; @@ -103,9 +117,12 @@ */ --toolbar-button: { display: inline-flex; + align-items: center; + justify-content: center; width: 34px; height: 34px; line-height: 34px; + padding: 0 !important; text-align: center; border-radius: 3px; cursor: pointer; @@ -113,19 +130,25 @@ outline: none; background-color: transparent; vertical-align: bottom; - color: var(--grayText); + color: #000; + margin: 0; &:hover { background-color: var(--bg-light); } - & > svg, - .icon { - margin: auto; - } - &--active { color: var(--color-active-icon); } + + &--focused { + box-shadow: inset 0 0 0px 1px rgba(7, 161, 227, 0.08); + background: rgba(34, 186, 255, 0.08) !important; + + &-animated { + animation-name: buttonClicked; + animation-duration: 250ms; + } + } }; } diff --git a/src/types-internal/block-data.d.ts b/src/types-internal/block-data.d.ts deleted file mode 100644 index 7c84aad38..000000000 --- a/src/types-internal/block-data.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {BlockToolData} from '../../types/tools'; - -/** - * Tool's saved data - */ -export interface SavedData { - tool: string; - data: BlockToolData; - time: number; -} - -/** - * Tool's data after validation - */ -export interface ValidatedData { - tool?: string; - data?: BlockToolData; - time?: number; - isValid: boolean; -} diff --git a/src/types-internal/editor-modules.d.ts b/src/types-internal/editor-modules.d.ts index d30ecb516..14ad7e304 100644 --- a/src/types-internal/editor-modules.d.ts +++ b/src/types-internal/editor-modules.d.ts @@ -1,14 +1,12 @@ import UI from '../components/modules/ui'; import BlockEvents from '../components/modules/blockEvents'; -import Listeners from '../components/modules/listeners'; import Toolbar from '../components/modules/toolbar/index'; import InlineToolbar from '../components/modules/toolbar/inline'; import Toolbox from '../components/modules/toolbar/toolbox'; import BlockSettings from '../components/modules/toolbar/blockSettings'; -import Events from '../components/modules/events'; -import Shortcuts from '../components/modules/shortcuts'; import Paste from '../components/modules/paste'; import Notifier from '../components/modules/notifier'; +import Tooltip from '../components/modules/tooltip'; import DragNDrop from '../components/modules/dragNDrop'; import ModificationsObserver from '../components/modules/modificationsObserver'; import Renderer from '../components/modules/renderer'; @@ -30,19 +28,24 @@ import SaverAPI from '../components/modules/api/saver'; import Saver from '../components/modules/saver'; import BlockSelection from '../components/modules/blockSelection'; import RectangleSelection from '../components/modules/RectangleSelection'; +import InlineToolbarAPI from '../components/modules/api/inlineToolbar'; +import CrossBlockSelection from '../components/modules/crossBlockSelection'; +import ConversionToolbar from '../components/modules/toolbar/conversion'; +import TooltipAPI from '../components/modules/api/tooltip'; +import ReadOnly from '../components/modules/readonly'; +import ReadOnlyAPI from '../components/modules/api/readonly'; +import I18nAPI from '../components/modules/api/i18n'; export interface EditorModules { UI: UI; BlockEvents: BlockEvents; BlockSelection: BlockSelection; RectangleSelection: RectangleSelection; - Listeners: Listeners; Toolbar: Toolbar; InlineToolbar: InlineToolbar; Toolbox: Toolbox; BlockSettings: BlockSettings; - Events: Events; - Shortcuts: Shortcuts; + ConversionToolbar: ConversionToolbar; Paste: Paste; DragNDrop: DragNDrop; ModificationsObserver: ModificationsObserver; @@ -53,6 +56,7 @@ export interface EditorModules { Caret: Caret; Saver: Saver; Notifier: Notifier; + Tooltip: Tooltip; BlockManager: BlockManager; BlocksAPI: BlocksAPI; CaretAPI: CaretAPI; @@ -63,5 +67,11 @@ export interface EditorModules { SelectionAPI: SelectionAPI; StylesAPI: StylesAPI; ToolbarAPI: ToolbarAPI; + InlineToolbarAPI: InlineToolbarAPI; + CrossBlockSelection: CrossBlockSelection; NotifierAPI: NotifierAPI; + TooltipAPI: TooltipAPI; + ReadOnly: ReadOnly; + ReadOnlyAPI: ReadOnlyAPI; + I18nAPI: I18nAPI; } diff --git a/src/types-internal/html-janitor.d.ts b/src/types-internal/html-janitor.d.ts index 6f9cc0352..66f1c6a3a 100644 --- a/src/types-internal/html-janitor.d.ts +++ b/src/types-internal/html-janitor.d.ts @@ -3,9 +3,15 @@ * After that we can use it at the TS modules */ declare module 'html-janitor' { + /** + * Sanitizer config of each HTML element + * @see {@link https://github.com/guardian/html-janitor#options} + */ + type TagConfig = boolean | { [attr: string]: boolean | string }; + interface Config { tags: { - [key: string]: boolean|{[attr: string]: boolean|string}|(() => any) + [key: string]: TagConfig | ((el: Element) => TagConfig) }; } diff --git a/src/types-internal/i18n-internal-namespace.d.ts b/src/types-internal/i18n-internal-namespace.d.ts new file mode 100644 index 000000000..f2a520cbf --- /dev/null +++ b/src/types-internal/i18n-internal-namespace.d.ts @@ -0,0 +1,68 @@ +/** +* Decorator above the type object +*/ +type Indexed = { [key: string]: T }; + +/** + * Type for I18n dictionary values that can be strings or dictionary sub-sections + * + * Can be used as: + * LeavesDictKeys + * + * where myDictionary is a JSON with messages + */ +export type LeavesDictKeys = D extends string + /** + * If generic type is string, just return it + */ + ? D + /** + * If generic type is object that has only one level and contains only strings, return it's keys union + * + * { key: "string", anotherKey: "string" } => "key" | "anotherKey" + * + */ + : D extends Indexed + ? keyof D + /** + * If generic type is object, but not the one described above, + * use LeavesDictKey on it's values recursively and union the results + * + * { "rootKey": { "subKey": "string" }, "anotherRootKey": { "anotherSubKey": "string" } } => "subKey" | "anotherSubKey" + * + */ + : D extends Indexed + ? { [K in keyof D]: LeavesDictKeys }[keyof D] + + /** + * In other cases, return never type + */ + : never; + +/** + * Provide type-safe access to the available namespaces of the dictionary + * + * Can be uses as: + * DictNamespaces + * + * where myDictionary is a JSON with messages + */ +export type DictNamespaces = { + /** + * Iterate through generic type keys + * + * If value under current key is object that has only one level and contains only strings, return string type + */ + [K in keyof D]: D[K] extends Indexed + ? string + /** + * If value under current key is object with depth more than one, apply DictNamespaces recursively + */ + : D[K] extends Indexed + ? DictNamespaces + /** + * In other cases, return never type + */ + : never; +} + diff --git a/src/types-internal/module-config.d.ts b/src/types-internal/module-config.d.ts index f0e224c64..195395850 100644 --- a/src/types-internal/module-config.d.ts +++ b/src/types-internal/module-config.d.ts @@ -1,8 +1,10 @@ -import {EditorConfig} from '../../types/index'; +import { EditorConfig } from '../../types/index'; +import EventsDispatcher from '../components/utils/events'; /** * Describes object passed to Editor modules constructor */ export interface ModuleConfig { config: EditorConfig; + eventsDispatcher: EventsDispatcher; } diff --git a/test/cypress/.eslintrc b/test/cypress/.eslintrc new file mode 100644 index 000000000..9318c8d89 --- /dev/null +++ b/test/cypress/.eslintrc @@ -0,0 +1,17 @@ +{ + "plugins": [ + "cypress" + ], + "env": { + "cypress/globals": true + }, + "extends": [ + "plugin:cypress/recommended" + ], + "rules": { + "cypress/require-data-selectors": 2 + }, + "globals": { + "EditorJS": true + } +} \ No newline at end of file diff --git a/test/cypress/fixtures/test.html b/test/cypress/fixtures/test.html new file mode 100644 index 000000000..c35c64375 --- /dev/null +++ b/test/cypress/fixtures/test.html @@ -0,0 +1,8 @@ + + + + + +

Editor.js test page

+ + diff --git a/test/cypress/plugins/index.ts b/test/cypress/plugins/index.ts new file mode 100644 index 000000000..11c2d42f1 --- /dev/null +++ b/test/cypress/plugins/index.ts @@ -0,0 +1,5 @@ +/** + * This file contains connection of Cypres plugins + */ +// eslint-disable-next-line @typescript-eslint/no-empty-function +// export default function(on, config): void {} diff --git a/test/cypress/support/commands.ts b/test/cypress/support/commands.ts new file mode 100644 index 000000000..e23e84315 --- /dev/null +++ b/test/cypress/support/commands.ts @@ -0,0 +1,38 @@ +/** + * This file contains custom commands for Cypress. + * Also it can override the existing commands. + * + * -------------------------------------------------- + */ + +import type { EditorConfig } from './../../../types/index'; +import type EditorJS from '../../../types/index'; +import Chainable = Cypress.Chainable; + +/** + * Create a wrapper and initialize the new instance of editor.js + * Then return the instance + * + * @param editorConfig - config to pass to the editor + * @returns EditorJS - created instance + */ +Cypress.Commands.add('createEditor', (editorConfig: EditorConfig = {}): Chainable => { + return cy.window() + .then((window) => { + return new Promise((resolve: (instance: EditorJS) => void) => { + const editorContainer = window.document.createElement('div'); + + editorContainer.setAttribute('id', 'editorjs'); + editorContainer.dataset.cy = 'editorjs'; + editorContainer.style.border = '1px dotted #388AE5'; + + window.document.body.appendChild(editorContainer); + + const editorInstance: EditorJS = new window.EditorJS(editorConfig); + + editorInstance.isReady.then(() => { + resolve(editorInstance); + }); + }); + }); +}); diff --git a/test/cypress/support/index.d.ts b/test/cypress/support/index.d.ts new file mode 100644 index 000000000..5a9e86319 --- /dev/null +++ b/test/cypress/support/index.d.ts @@ -0,0 +1,23 @@ +// in cypress/support/index.d.ts +// load type definitions that come with Cypress module +/// + +import type { EditorConfig } from './../../../types/index'; +import type EditorJS from '../../../types/index' + +declare global { + namespace Cypress { + interface Chainable { + /** + * Custom command to select DOM element by data-cy attribute. + * @param editorConfig - config to pass to the editor + * @example cy.createEditor({}) + */ + createEditor(editorConfig: EditorConfig): Chainable + } + + interface ApplicationWindow { + EditorJS: typeof EditorJS + } + } +} diff --git a/test/cypress/support/index.ts b/test/cypress/support/index.ts new file mode 100644 index 000000000..252bff1f0 --- /dev/null +++ b/test/cypress/support/index.ts @@ -0,0 +1,19 @@ +/** + * This file is processed and + * loaded automatically before the test files. + * + * This is a great place to put global configuration and + * behavior that modifies Cypress. + */ + +/** + * File with the helpful commands + */ +import './commands'; + +/** + * Before-each hook for the cypress tests + */ +beforeEach((): void => { + cy.visit('test/cypress/fixtures/test.html'); +}); diff --git a/test/cypress/tests/initialization.spec.ts b/test/cypress/tests/initialization.spec.ts new file mode 100644 index 000000000..67750c5ff --- /dev/null +++ b/test/cypress/tests/initialization.spec.ts @@ -0,0 +1,28 @@ +// eslint-disable-next-line spaced-comment +/// + +describe('Editor basic initialization', () => { + describe('Zero-config initialization', () => { + /** + * In this test suite we use zero (omitted) configuration + */ + const editorConfig = {}; + + beforeEach(() => { + if (this.editorInstance) { + this.editorInstance.destroy(); + } else { + cy.createEditor(editorConfig).as('editorInstance'); + } + }); + + it('should create a visible UI', () => { + /** + * Assert if created instance is visible or not. + */ + cy.get('[data-cy=editorjs]') + .get('div.codex-editor') + .should('be.visible'); + }); + }); +}); diff --git a/test/cypress/tsconfig.json b/test/cypress/tsconfig.json new file mode 100644 index 000000000..86b00a579 --- /dev/null +++ b/test/cypress/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "es2017", + "lib": ["es2017", "dom"], + "types": ["cypress"] + }, + "include": [ + "**/*.ts" + ] + } \ No newline at end of file diff --git a/test/testcases.md b/test/testcases.md new file mode 100644 index 000000000..00080a09c --- /dev/null +++ b/test/testcases.md @@ -0,0 +1,82 @@ +# Editor.js specs + +This document will describe various test cases of the editor.js functionality. Features will be organized by modules. Cases covered by tests should be marked by the checkmark. + +## Configuration + +- [ ] Zero configuration + - [ ] Editor.js should be initialized on the element with the default `editorjs` id. + - [ ] Editor.js should throw an error in case when there is no element with `editorjs` id. + - [ ] Editor.js should be initialized with the Paragraph tool only. + - [ ] The Inline Toolbar of the Paragraph tool should contain all default Inline Tools - `bold`, `italic`, `link`. + +- [ ] `holder` property + - [ ] Editor.js should be initialized on the element with passed via `holder` property. + - [ ] Editor.js should throw an error if passed `holder` value is not an Element node. + +- [ ] `autofocus` property + - [ ] With the empty editor + - [ ] If `true` passed, the caret should be placed to the first empty block. + - [ ] If `false` passed, the caret shouldn't be placed anywhere. + - [ ] If omitted, the caret shouldn't be placed anywhere. + - [ ] With the not-empty editor + - [ ] If `true` passed, the caret should be placed to the end of the last block. + - [ ] If `false` passed, the caret shouldn't be placed anywhere. + - [ ] If omitted, the caret shouldn't be placed anywhere. + +- [ ] `placeholder` property + - [ ] With the empty editor + - [ ] If `string` passed, the string should be placed as a placeholder to the first empty block only. + - [ ] If `false` passed, the first empty block should be placed without a placeholder. + - [ ] If omitted, the first empty block should be placed without a placeholder. + +- [ ] `minHeight` property + - [ ] If `number` passed, the height of the editor's bottom area from the last Block should be the `number`. + - [ ] If omitted the height of editor's bottom area from the last Block should be the default `300`. + +- [ ] `logLevel` property + - [ ] If `VERBOSE` passed, the editor should output all messages to the console. + - [ ] If `INFO` passed, the editor should output info and debug messages to the console. + - [ ] If `WARN` passed, the editor should output only warning messages to the console. + - [ ] If `ERROR` passed, the editor should output only error messages to the console. + - [ ] If omitted, the editor should output all messages to the console. + +- [ ] `defaultBlock` property + - [ ] If `string` passed + - [ ] If passed `string` in the `tools` option, the passed tool should be used as the default tool. + - [ ] If passed `string` not in the `tools` option, the Paragraph tool should be used as the default tool. + - [ ] If omitted the Paragraph tool should be used as default tool. + +- [ ] `sanitizer` property + - [ ] If `object` passed + - [ ] The Editor.js should clean the HTML tags according to mentioned configuration. + - [ ] If omitted the Editor.js should be initialized with the default `sanitizer` configuration, which allows the tags like `paragraph`, `anchor`, and `bold` for cleaning HTML. + +- [ ] `tools` property + - [ ] If omitted + - [ ] Editor.js should be initialized with the Paragraph tool only. + - [ ] If `object` passed + - [ ] Editor.js should be initialized with all the passed tools. + - [ ] The keys of the object should be represented as `type` fields for corresponded blocks in output JSON + - [ ] If value is a JavaScript class + - [ ] This class should be used as a tool + - [ ] If value is an `object` + - [ ] Checking the `class` property + - [ ] If omitted, the tool should be skipped with a warning in a console. + - [ ] If existed, the value of the `class` property should be used as a tool + - [ ] Checking the `config` property + - [ ] If `object` passed Editor.js should initialize `tool` and pass this object as `config` parameter of the tool's constructor + - [ ] Checking the `shortcut` property + - [ ] If `string` passed Editor.js should append the `tool` when such keys combination executed. + - [ ] Checking the `inilineToolbar` property + - [ ] If `true` + - [ ] Editor.js should show the Inline Toolbar for this tool with [common](https://editorjs.io/configuration#inline-toolbar-order) settings. + - [ ] If `false` + - [ ] Editor.js should not show the Inline Toolbar for this tool. + - [ ] If `array` + - [ ] Editor.js should show the Inline Toolbar for this tool with a passed list of tools and their order. + - [ ] If omitted + - [ ] Editor.js should not show the Inline Toolbar for this tool. + - [ ] Checking the `toolbox` property + - [ ] If it contains `title`, this title should be used as a tool title + - [ ] If it contains `icon`, this HTML code (maybe SVG) should be used as a tool icon diff --git a/tsconfig.json b/tsconfig.json index 0d3f1bb5d..fd0aa5e15 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,6 +4,12 @@ "target": "es2017", "declaration": false, "moduleResolution": "node", // This resolution strategy attempts to mimic the Node.js module resolution mechanism at runtime - "lib": ["dom", "es2017", "es2018"] + "lib": ["dom", "es2017", "es2018"], + + // allows to import .json files for i18n + "resolveJsonModule": true, + + // allows to omit export default in .json files + "allowSyntheticDefaultImports": true } } diff --git a/tslint.json b/tslint.json index d32148ed1..c4406b704 100644 --- a/tslint.json +++ b/tslint.json @@ -20,7 +20,8 @@ "no-string-literal": false, "no-empty": false, "no-namespace": false, - "variable-name": [true, "allow-leading-underscore", "allow-pascal-case"] + "variable-name": [true, "allow-leading-underscore", "allow-pascal-case"], + "no-reference": false }, "globals": { "require": true diff --git a/types/api/block.d.ts b/types/api/block.d.ts new file mode 100644 index 000000000..cb3ca2932 --- /dev/null +++ b/types/api/block.d.ts @@ -0,0 +1,65 @@ +import {BlockToolData, ToolConfig} from '../tools'; +import {SavedData} from '../data-formats'; + +/** + * @interface BlockAPI Describes Block API methods and properties + */ +export interface BlockAPI { + /** + * Tool name + */ + readonly name: string; + + /** + * Tool config passed on Editor's initialization + */ + readonly config: ToolConfig; + + /** + * Wrapper of Tool's HTML element + */ + readonly holder: HTMLElement; + + /** + * True if Block content is empty + */ + readonly isEmpty: boolean; + + /** + * True if Block is selected with Cross-Block selection + */ + readonly selected: boolean; + + /** + * Setter sets Block's stretch state + * + * Getter returns true if Block is stretched + */ + stretched: boolean; + + /** + * Call Tool method with errors handler under-the-hood + * + * @param {string} methodName - method to call + * @param {object} param - object with parameters + * + * @return {void} + */ + call(methodName: string, param?: object): void; + + /** + * Save Block content + * + * @return {Promise} + */ + save(): Promise; + + /** + * Validate Block data + * + * @param {BlockToolData} data + * + * @return {Promise} + */ + validate(data: BlockToolData): Promise; +} diff --git a/types/api/blocks.d.ts b/types/api/blocks.d.ts index 166c1f748..b933a8175 100644 --- a/types/api/blocks.d.ts +++ b/types/api/blocks.d.ts @@ -1,4 +1,6 @@ import {OutputData} from '../data-formats/output-data'; +import {BlockToolData, ToolConfig} from '../tools'; +import {BlockAPI} from './block'; /** * Describes methods to manipulate with Editor`s blocks @@ -11,8 +13,10 @@ export interface Blocks { /** * Render passed data - * @param {OutputData} data - * @return {Promise} + * + * @param {OutputData} data - saved Block data + * + * @returns {Promise} */ render(data: OutputData): Promise; @@ -25,22 +29,30 @@ export interface Blocks { /** * Removes current Block + * @param {number} index - index of a block to delete */ - delete(): void; + delete(index?: number): void; /** * Swaps two Blocks * @param {number} fromIndex - block to swap * @param {number} toIndex - block to swap with + * @deprecated — use 'move' instead */ swap(fromIndex: number, toIndex: number): void; /** - * Returns Block holder by Block index + * Moves a block to a new index + * @param {number} toIndex - index where the block is moved to + * @param {number} fromIndex - block to move + */ + move(toIndex: number, fromIndex?: number): void; + + /** + * Returns Block API object by passed Block index * @param {number} index - * @returns {HTMLElement} */ - getBlockByIndex(index: number): HTMLElement; + getBlockByIndex(index: number): BlockAPI | void; /** * Returns current Block index @@ -52,6 +64,8 @@ export interface Blocks { * Mark Block as stretched * @param {number} index - Block to mark * @param {boolean} status - stretch status + * + * @deprecated Use BlockAPI interface to stretch Blocks */ stretchBlock(index: number, status?: boolean): void; @@ -63,6 +77,26 @@ export interface Blocks { /** * Insert new Initial Block after current Block + * + * @deprecated */ insertNewBlock(): void; + + /** + * Insert new Block + * + * @param {string} type — Tool name + * @param {BlockToolData} data — Tool data to insert + * @param {ToolConfig} config — Tool config + * @param {number?} index — index where to insert new Block + * @param {boolean?} needToFocus - flag to focus inserted Block + */ + insert( + type?: string, + data?: BlockToolData, + config?: ToolConfig, + index?: number, + needToFocus?: boolean, + ): void; + } diff --git a/types/api/i18n.d.ts b/types/api/i18n.d.ts new file mode 100644 index 000000000..7b4e6686e --- /dev/null +++ b/types/api/i18n.d.ts @@ -0,0 +1,11 @@ +/** + * Describes Editor`s I18n API + */ +export interface I18n { + /** + * Perform translation with automatically added namespace like `tools.${toolName}` or `blockTunes.${tuneName}` + * + * @param dictKey - what to translate + */ + t(dictKey: string): string; +} diff --git a/types/api/index.d.ts b/types/api/index.d.ts index 661ed5b42..b1bfe6206 100644 --- a/types/api/index.d.ts +++ b/types/api/index.d.ts @@ -8,3 +8,8 @@ export * from './styles'; export * from './caret'; export * from './toolbar'; export * from './notifier'; +export * from './tooltip'; +export * from './inline-toolbar'; +export * from './block'; +export * from './readonly'; +export * from './i18n'; diff --git a/types/api/inline-toolbar.d.ts b/types/api/inline-toolbar.d.ts new file mode 100644 index 000000000..5b49db54a --- /dev/null +++ b/types/api/inline-toolbar.d.ts @@ -0,0 +1,15 @@ +/** + * Describes InlineToolbar API methods + */ +export interface InlineToolbar { + /** + * Closes InlineToolbar + */ + close(): void; + + /** + * Opens InlineToolbar + */ + open(): void; +} + \ No newline at end of file diff --git a/types/api/readonly.d.ts b/types/api/readonly.d.ts new file mode 100644 index 000000000..a0bf4ca24 --- /dev/null +++ b/types/api/readonly.d.ts @@ -0,0 +1,12 @@ +/** + * ReadOnly API + */ +export interface ReadOnly { + /** + * Set or toggle read-only state + * + * @param {Boolean|undefined} state - set or toggle state + * @returns {Promise} current value + */ + toggle: (state?: boolean) => Promise; +} diff --git a/types/api/toolbar.d.ts b/types/api/toolbar.d.ts index 917108902..0c029004f 100644 --- a/types/api/toolbar.d.ts +++ b/types/api/toolbar.d.ts @@ -11,4 +11,10 @@ export interface Toolbar { * Opens Toolbar */ open(): void; + + /** + * Toggles Block Setting of the current block + * @param {boolean} openingState — opening state of Block Setting + */ + toggleBlockSettings(openingState?: boolean): void; } diff --git a/types/api/tooltip.d.ts b/types/api/tooltip.d.ts new file mode 100644 index 000000000..6ca7c42a2 --- /dev/null +++ b/types/api/tooltip.d.ts @@ -0,0 +1,30 @@ +/** + * Tooltip API + */ +import {TooltipContent, TooltipOptions} from 'codex-tooltip'; + +export interface Tooltip { + /** + * Show tooltip + * + * @param {HTMLElement} element + * @param {TooltipContent} content + * @param {TooltipOptions} options + */ + show: (element: HTMLElement, content: TooltipContent, options?: TooltipOptions) => void; + + /** + * Hides tooltip + */ + hide: () => void; + + /** + * Decorator for showing Tooltip by mouseenter/mouseleave + * + * @param {HTMLElement} element + * @param {TooltipContent} content + * @param {TooltipOptions} options + */ + onHover: (element: HTMLElement, content: TooltipContent, options?: TooltipOptions) => void; + +} diff --git a/types/configs/conversion-config.ts b/types/configs/conversion-config.ts new file mode 100644 index 000000000..25d3ee45b --- /dev/null +++ b/types/configs/conversion-config.ts @@ -0,0 +1,26 @@ +import {BlockToolData} from '../tools'; + +/** + * Config allows Tool to specify how it can be converted into/from another Tool + */ +export interface ConversionConfig { + /** + * How to import string to this Tool. + * + * Can be a String or Function: + * + * 1. String — the key of Tool data object to fill it with imported string on render. + * 2. Function — method that accepts importing string and composes Tool data to render. + */ + import: ((data: string) => string) | string; + + /** + * How to export this Tool to make other Block. + * + * Can be a String or Function: + * + * 1. String — which property of saved Tool data should be used as exported string. + * 2. Function — accepts saved Tool data and create a string to export + */ + export: ((data: BlockToolData) => string) | string; +} diff --git a/types/configs/editor-config.d.ts b/types/configs/editor-config.d.ts index 69a619337..a9353f572 100644 --- a/types/configs/editor-config.d.ts +++ b/types/configs/editor-config.d.ts @@ -1,12 +1,19 @@ import {ToolConstructable, ToolSettings} from '../tools'; -import {OutputData} from '../index'; +import {API, LogLevels, OutputData} from '../index'; import {SanitizerConfig} from './sanitizer-config'; +import {I18nConfig} from './i18n-config'; export interface EditorConfig { /** * Element where Editor will be append + * @deprecated property will be removed in the next major release, use holder instead */ - holderId?: string; + holderId?: string | HTMLElement; + + /** + * Element where Editor will be appended + */ + holder?: string | HTMLElement; /** * If true, set caret at the first Block after Editor is ready @@ -18,12 +25,19 @@ export interface EditorConfig { * Name should be equal to one of Tool`s keys of passed tools * If not specified, Paragraph Tool will be used */ + defaultBlock?: string; + + /** + * @deprecated + * This property will be deprecated in the next major release. + * Use the 'defaultBlock' property instead. + */ initialBlock?: string; /** * First Block placeholder */ - placeholder?: string; + placeholder?: string|false; /** * Define default sanitizer configuration @@ -46,6 +60,26 @@ export interface EditorConfig { */ data?: OutputData; + /** + * Height of Editor's bottom area that allows to set focus on the last Block + */ + minHeight?: number; + + /** + * Editors log level (how many logs you want to see) + */ + logLevel?: LogLevels; + + /** + * Enable read-only mode + */ + readOnly?: boolean; + + /** + * Internalization config + */ + i18n?: I18nConfig; + /** * Fires when Editor is ready to work */ @@ -53,6 +87,12 @@ export interface EditorConfig { /** * Fires when something changed in DOM + * @param {API} api - editor.js api + */ + onChange?(api: API): void; + + /** + * Defines default toolbar for all tools. */ - onChange?(): void; + inlineToolbar?: string[]|boolean; } diff --git a/types/configs/i18n-config.d.ts b/types/configs/i18n-config.d.ts new file mode 100644 index 000000000..4a9375d15 --- /dev/null +++ b/types/configs/i18n-config.d.ts @@ -0,0 +1,16 @@ +/** + * Available options of i18n config property + */ +import { I18nDictionary } from './i18n-dictionary'; + +export interface I18nConfig { + /** + * Dictionary used for translation + */ + messages?: I18nDictionary; + + /** + * Text direction. If not set, uses ltr + */ + direction?: 'ltr' | 'rtl'; +} diff --git a/types/configs/i18n-dictionary.d.ts b/types/configs/i18n-dictionary.d.ts new file mode 100644 index 000000000..4ca25f034 --- /dev/null +++ b/types/configs/i18n-dictionary.d.ts @@ -0,0 +1,93 @@ +/** + * Structure of the i18n dictionary + */ +export interface I18nDictionary { + /** + * Section for translation Tool Names: both block and inline tools + * Example: + * "toolNames": { + * "Text": "Параграф", + * "Heading": "Заголовок", + * "List": "Список", + * ... + * }, + */ + toolNames?: Dictionary; + + /** + * Section for passing translations to the external tools classes + * The first-level keys of this object should be equal of keys ot the 'tools' property of EditorConfig + * Includes internal tools: "paragraph", "stub" + * + * Example: + * "tools": { + * "warning": { + * "Title": "Название", + * "Message": "Сообщение", + * }, + * "link": { + * "Add a link": "Вставьте ссылку" + * }, + * }, + */ + tools?: Dictionary; + + /** + * Section allows to translate Block Tunes + * The first-level keys of this object should be equal of 'name' ot the 'tools..tunes' property of EditorConfig + * Including some internal block-tunes: "delete", "moveUp", "moveDown + * + * Example: + * "blockTunes": { + * "delete": { + * "Delete": "Удалить" + * }, + * "moveUp": { + * "Move up": "Переместить вверх" + * }, + * "moveDown": { + * "Move down": "Переместить вниз" + * } + * }, + */ + blockTunes?: Dictionary; + + /** + * Translation of internal UI components of the editor.js core + */ + ui?: Dictionary; +} + +/** + * Represent item of the I18nDictionary config + */ +export interface Dictionary { + /** + * The keys of the object can represent two entities: + * 1. Dictionary key usually is an original string from default locale, like "Convert to" + * 2. Sub-namespace section, like "toolbar.converter.<...>" + * + * Example of 1: + * toolbox: { + * "Add": "Добавить", + * } + * + * Example of 2: + * ui: { + * toolbar: { + * toolbox: { <-- Example of 1 + * "Add": "Добавить" + * } + * } + * } + */ + [key: string]: DictValue; +} + +/** + * The value of the dictionary can be: + * - other dictionary + * - result translate string + */ +export type DictValue = {[key: string]: Dictionary | string} | string; + diff --git a/types/configs/index.d.ts b/types/configs/index.d.ts index 1ad630202..20723a1db 100644 --- a/types/configs/index.d.ts +++ b/types/configs/index.d.ts @@ -1,3 +1,7 @@ export * from './editor-config'; export * from './sanitizer-config'; export * from './paste-config'; +export * from './conversion-config'; +export * from './log-levels'; +export * from './i18n-config'; +export * from './i18n-dictionary'; diff --git a/types/configs/log-levels.d.ts b/types/configs/log-levels.d.ts new file mode 100644 index 000000000..946a6e1e4 --- /dev/null +++ b/types/configs/log-levels.d.ts @@ -0,0 +1,9 @@ +/** + * Available log levels + */ +export enum LogLevels { + VERBOSE = 'VERBOSE', + INFO = 'INFO', + WARN = 'WARN', + ERROR = 'ERROR', +} diff --git a/types/configs/paste-config.d.ts b/types/configs/paste-config.d.ts index 25d6f98f9..c7e54b22a 100644 --- a/types/configs/paste-config.d.ts +++ b/types/configs/paste-config.d.ts @@ -1,5 +1,3 @@ -import {BlockToolData} from '../index'; - /** * Tool onPaste configuration object */ diff --git a/types/configs/sanitizer-config.d.ts b/types/configs/sanitizer-config.d.ts index c3854d047..e15df7f32 100644 --- a/types/configs/sanitizer-config.d.ts +++ b/types/configs/sanitizer-config.d.ts @@ -1,3 +1,9 @@ +/** + * Sanitizer config of each HTML element + * @see {@link https://github.com/guardian/html-janitor#options} + */ +type TagConfig = boolean | { [attr: string]: boolean | string }; + export interface SanitizerConfig { /** * Tag name and params not to be stripped off @@ -31,5 +37,5 @@ export interface SanitizerConfig { * } * } */ - [key: string]: boolean|{[attr: string]: boolean|string}|(() => any); + [key: string]: TagConfig | ((el: Element) => TagConfig); } diff --git a/types/data-formats/block-data.d.ts b/types/data-formats/block-data.d.ts new file mode 100644 index 000000000..063b63b6f --- /dev/null +++ b/types/data-formats/block-data.d.ts @@ -0,0 +1,20 @@ +import {BlockToolData} from '../tools'; + +/** + * Tool's saved data + */ +export interface SavedData { + tool: string; + data: BlockToolData; + time: number; +} + +/** + * Tool's data after validation + */ +export interface ValidatedData { + tool?: string; + data?: BlockToolData; + time?: number; + isValid: boolean; +} diff --git a/types/data-formats/index.d.ts b/types/data-formats/index.d.ts new file mode 100644 index 000000000..410f36539 --- /dev/null +++ b/types/data-formats/index.d.ts @@ -0,0 +1,2 @@ +export * from './block-data'; +export * from './output-data'; diff --git a/types/data-formats/output-data.d.ts b/types/data-formats/output-data.d.ts index 2d9ffccaa..1e2c0a644 100644 --- a/types/data-formats/output-data.d.ts +++ b/types/data-formats/output-data.d.ts @@ -1,5 +1,22 @@ import {BlockToolData} from '../tools'; +/** + * Output of one Tool + * + * @template Type - the string literal describing a tool type + * @template Data - the structure describing a data object supported by the tool + */ +export interface OutputBlockData { + /** + * Tool type + */ + type: Type; + /** + * Saved Block data + */ + data: BlockToolData; +} + export interface OutputData { /** * Editor's version @@ -14,8 +31,5 @@ export interface OutputData { /** * Saved Blocks */ - blocks: Array<{ - type: string; - data: BlockToolData - }>; + blocks: OutputBlockData[]; } diff --git a/types/index.d.ts b/types/index.d.ts index d02027b2d..07fe5e0d7 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -4,8 +4,32 @@ * ------------------------------------ */ -import {EditorConfig} from './configs'; -import {Blocks, Caret, Events, Listeners, Notifier, Sanitizer, Saver, Selection, Styles, Toolbar} from './api'; +import { + Dictionary, + DictValue, + EditorConfig, + I18nConfig, + I18nDictionary, +} from './configs'; + +import { + Blocks, + Caret, + Events, + InlineToolbar, + Listeners, + Notifier, + ReadOnly, + Sanitizer, + Saver, + Selection, + Styles, + Toolbar, + Tooltip, + I18n, +} from './api'; + +import { OutputData } from './data-formats'; /** * Interfaces used for development @@ -15,7 +39,9 @@ export { BaseToolConstructable, InlineTool, InlineToolConstructable, + InlineToolConstructorOptions, BlockToolConstructable, + BlockToolConstructorOptions, BlockTool, BlockToolData, Tool, @@ -33,8 +59,19 @@ export { FilePasteEventDetail, } from './tools'; export {BlockTune, BlockTuneConstructable} from './block-tunes'; -export {EditorConfig, SanitizerConfig, PasteConfig} from './configs'; -export {OutputData} from './data-formats/output-data'; +export { + EditorConfig, + SanitizerConfig, + PasteConfig, + LogLevels, + ConversionConfig, + I18nDictionary, + Dictionary, + DictValue, + I18nConfig, +} from './configs'; +export {OutputData, OutputBlockData} from './data-formats/output-data'; +export { BlockAPI } from './api' /** * We have a namespace API {@link ./api/index.d.ts} (APIMethods) but we can not use it as interface @@ -51,6 +88,10 @@ export interface API { selection: Selection; styles: Styles; toolbar: Toolbar; + inlineToolbar: InlineToolbar; + tooltip: Tooltip; + i18n: I18n; + readOnly: ReadOnly; } /** @@ -63,16 +104,57 @@ declare class EditorJS { public blocks: Blocks; public caret: Caret; - public events: Events; - public listeners: Listeners; public sanitizer: Sanitizer; public saver: Saver; public selection: Selection; public styles: Styles; public toolbar: Toolbar; - + public inlineToolbar: InlineToolbar; + public readOnly: ReadOnly; constructor(configuration?: EditorConfig|string); + /** + * API shorthands + */ + + /** + * @see Saver.save + */ + public save(): Promise; + + /** + * @see Blocks.clear + */ + public clear(): void; + + /** + * @see Blocks.render + */ + public render(data: OutputData): Promise; + + /** + * @see Caret.focus + */ + public focus(atEnd?: boolean): boolean; + + /** + * @see Events.on + */ + public on(eventName: string, callback: (data?: any) => void): void; + + /** + * @see Events.off + */ + public off(eventName: string, callback: (data?: any) => void): void; + + /** + * @see Events.emit + */ + public emit(eventName: string, data: any): void; + + /** + * Destroy Editor instance and related DOM elements + */ public destroy(): void; } diff --git a/types/tools/block-tool-data.d.ts b/types/tools/block-tool-data.d.ts index e1db12a32..b3760dd62 100644 --- a/types/tools/block-tool-data.d.ts +++ b/types/tools/block-tool-data.d.ts @@ -2,4 +2,4 @@ * Object returned by Tool's {@link BlockTool#save} method * Specified by Tool developer, so leave it as object */ -export type BlockToolData = object; +export type BlockToolData = T; diff --git a/types/tools/block-tool.d.ts b/types/tools/block-tool.d.ts index 25e3c2f65..3b109de6f 100644 --- a/types/tools/block-tool.d.ts +++ b/types/tools/block-tool.d.ts @@ -1,9 +1,11 @@ -import {PasteConfig, SanitizerConfig} from '../configs'; -import {BlockToolData} from './block-tool-data'; +import { ConversionConfig, PasteConfig, SanitizerConfig } from '../configs'; +import { BlockToolData } from './block-tool-data'; import {BaseTool, BaseToolConstructable} from './tool'; -import {ToolConfig} from './tool-config'; -import {API} from '../index'; -import {PasteEvent} from './paste-events'; +import { ToolConfig } from './tool-config'; +import {API, BlockAPI} from '../index'; +import { PasteEvent } from './paste-events'; +import { MoveEvent } from './hook-events'; + /** * Describe Block Tool object * @see {@link docs/tools.md} @@ -46,6 +48,47 @@ export interface BlockTool extends BaseTool { * @param {PasteEvent} event */ onPaste?(event: PasteEvent): void; + + /** + * Cleanup resources used by your tool here + * Called when the editor is destroyed + */ + destroy?(): void; + + /** + * Lifecycle hooks + */ + + /** + * Called after block content added to the page + */ + rendered?(): void; + + /** + * Called each time block content is updated + */ + updated?(): void; + + /** + * Called after block removed from the page but before instance is deleted + */ + removed?(): void; + + /** + * Called after block was moved + */ + moved?(event: MoveEvent): void; +} + +/** + * Describe constructor parameters + */ +export interface BlockToolConstructorOptions { + api: API; + data: BlockToolData; + config?: ToolConfig; + block?: BlockAPI; + readOnly: boolean; } export interface BlockToolConstructable extends BaseToolConstructable { @@ -67,7 +110,24 @@ export interface BlockToolConstructable extends BaseToolConstructable { /** * Paste substitutions configuration */ - pasteConfig?: PasteConfig; + pasteConfig?: PasteConfig | false; - new (config: {api: API, config: ToolConfig, data: BlockToolData}): BlockTool; + /** + * Rules that specified how this Tool can be converted into/from another Tool + */ + conversionConfig?: ConversionConfig; + + /** + * Is Tool supports read-only mode, this property should return true + */ + isReadOnlySupported?: boolean; + + /** + * @constructor + * + * @param {BlockToolConstructorOptions} config - constructor parameters + * + * @return {BlockTool} + */ + new(config: BlockToolConstructorOptions): BlockTool; } diff --git a/types/tools/hook-events.d.ts b/types/tools/hook-events.d.ts new file mode 100644 index 000000000..fd8e6984f --- /dev/null +++ b/types/tools/hook-events.d.ts @@ -0,0 +1,23 @@ +/** + * Event detail for block relocation + */ +export interface MoveEventDetail { + /** + * index the block was moved from + */ + fromIndex: number; + /** + * index the block was moved to + */ + toIndex: number; +} + +/** + * Move event for block relocation + */ +export interface MoveEvent extends CustomEvent { + /** + * Override detail property of CustomEvent by MoveEvent hook + */ + readonly detail: MoveEventDetail; +} diff --git a/types/tools/index.d.ts b/types/tools/index.d.ts index ad8f22e87..4d43d407c 100644 --- a/types/tools/index.d.ts +++ b/types/tools/index.d.ts @@ -9,6 +9,7 @@ export * from './tool'; export * from './tool-config'; export * from './tool-settings'; export * from './paste-events'; +export * from './hook-events'; -export type Tool = BaseTool | BlockTool | InlineTool; -export type ToolConstructable = BaseToolConstructable | BlockToolConstructable | InlineToolConstructable; +export type Tool = BlockTool | InlineTool; +export type ToolConstructable = BlockToolConstructable | InlineToolConstructable; diff --git a/types/tools/inline-tool.d.ts b/types/tools/inline-tool.d.ts index 0ad6866d1..705a14912 100644 --- a/types/tools/inline-tool.d.ts +++ b/types/tools/inline-tool.d.ts @@ -1,4 +1,5 @@ import {BaseTool, BaseToolConstructable} from './tool'; +import {API, ToolConfig} from "../index"; /** * Base structure for the Inline Toolbar Tool */ @@ -30,8 +31,26 @@ export interface InlineTool extends BaseTool { /** * Function called with Inline Toolbar closing + * @deprecated 2020 10/02 - The new instance will be created each time the button is rendered. So clear is not needed. + * Better to create the 'destroy' method in a future. */ clear?(): void; } -export interface InlineToolConstructable extends BaseToolConstructable {} + +/** + * Describe constructor parameters + */ +export interface InlineToolConstructorOptions { + api: API; + config?: ToolConfig; +} + +export interface InlineToolConstructable extends BaseToolConstructable { + /** + * Constructor + * + * @param {InlineToolConstructorOptions} config - constructor parameters + */ + new(config: InlineToolConstructorOptions): BaseTool; +} diff --git a/types/tools/tool-config.d.ts b/types/tools/tool-config.d.ts index 9c97af597..74f25b074 100644 --- a/types/tools/tool-config.d.ts +++ b/types/tools/tool-config.d.ts @@ -1,4 +1,4 @@ /** * Tool configuration object. Specified by Tool developer, so leave it as object */ -export type ToolConfig = object; +export type ToolConfig = T; diff --git a/types/tools/tool-settings.d.ts b/types/tools/tool-settings.d.ts index 22c56a6a2..53b8f8c19 100644 --- a/types/tools/tool-settings.d.ts +++ b/types/tools/tool-settings.d.ts @@ -18,8 +18,10 @@ export interface ToolboxConfig { /** * Object passed to the Tool's constructor by {@link EditorConfig#tools} + * + * @template Config - the structure describing a config object supported by the tool */ -export interface ToolSettings { +export interface ToolSettings { /** * Tool's class @@ -29,12 +31,7 @@ export interface ToolSettings { /** * User configuration object that will be passed to the Tool's constructor */ - config?: ToolConfig; - - /** - * Is user available to add line brakes in Tool (for example by Shift+Enter) - */ - enableLineBreaks?: boolean; + config?: ToolConfig; /** * Is need to show Inline Toolbar. @@ -49,6 +46,7 @@ export interface ToolSettings { /** * Tool's Toolbox settings + * It will be hidden from Toolbox when false is specified. */ - toolbox?: ToolboxConfig; + toolbox?: ToolboxConfig | false; } diff --git a/types/tools/tool.d.ts b/types/tools/tool.d.ts index 6f1afba9a..bd18fc239 100644 --- a/types/tools/tool.d.ts +++ b/types/tools/tool.d.ts @@ -1,4 +1,4 @@ -import {API, ToolSettings} from '../index'; +import {API} from '../index'; import {ToolConfig} from './tool-config'; import {SanitizerConfig} from '../configs'; @@ -15,7 +15,6 @@ export interface BaseTool { } export interface BaseToolConstructable { - /** * Define Tool type as Inline */ @@ -26,14 +25,24 @@ export interface BaseToolConstructable { */ sanitize?: SanitizerConfig; + /** + * Title of Inline Tool + */ + title?: string; + /** * Describe constructor parameters */ - new (config: {api: API, config?: ToolSettings}): BaseTool; + new (config: {api: API, config?: ToolConfig}): BaseTool; /** * Tool`s prepare method. Can be async * @param data */ prepare?(data: {toolName: string, config: ToolConfig}): void | Promise; + + /** + * Tool`s reset method to clean up anything set by prepare. Can be async + */ + reset?(): void | Promise; } diff --git a/webpack.config.js b/webpack.config.js index 83a98bd4a..898be3a8c 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -9,58 +9,60 @@ module.exports = (env, argv) => { const path = require('path'); const TerserPlugin = require('terser-webpack-plugin'); - const {LicenseWebpackPlugin} = require('license-webpack-plugin'); + const { LicenseWebpackPlugin } = require('license-webpack-plugin'); const pkg = require('./package.json'); /** * Environment + * * @type {any} */ const NODE_ENV = argv.mode || 'development'; - const VERSION = process.env.VERSION || pkg.version; + const VERSION = process.env.VERSION || pkg.version; /** * Plugins for bundle + * * @type {webpack} */ const webpack = require('webpack'); return { entry: { - 'editor': ['@babel/polyfill/noConflict', './src/codex.ts'] + editor: ['@babel/polyfill/noConflict', './src/codex.ts'], }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].js', library: [ 'EditorJS' ], - libraryTarget: 'umd' + libraryTarget: 'umd', }, watchOptions: { - aggregateTimeout: 50 + aggregateTimeout: 50, }, /** * Tell webpack what directories should be searched when resolving modules. */ resolve: { - modules: [path.join(__dirname, 'src'), 'node_modules'], - extensions: ['.js', '.ts'] + modules: [path.join(__dirname, 'src'), 'node_modules'], + extensions: ['.js', '.ts'], }, plugins: [ /** Pass variables into modules */ new webpack.DefinePlugin({ NODE_ENV: JSON.stringify(NODE_ENV), - VERSION: JSON.stringify(VERSION) + VERSION: JSON.stringify(VERSION), }), new webpack.BannerPlugin({ - banner: `Editor.js\n\n@version ${VERSION}\n\n@licence Apache-2.0\n@author CodeX \n\n@uses html-janitor\n@licence Apache-2.0 (https://github.com/guardian/html-janitor/blob/master/LICENSE)` + banner: `Editor.js\n\n@version ${VERSION}\n\n@licence Apache-2.0\n@author CodeX \n\n@uses html-janitor\n@licence Apache-2.0 (https://github.com/guardian/html-janitor/blob/master/LICENSE)`, }), - new LicenseWebpackPlugin() + new LicenseWebpackPlugin(), ], module: { @@ -72,35 +74,29 @@ module.exports = (env, argv) => { loader: 'babel-loader', options: { cacheDirectory: true, - } + }, }, { - loader: 'ts-loader' + loader: 'ts-loader', }, - { - loader: 'tslint-loader', - options: { - fix: true - } - } - ] + ], }, { test: /\.css$/, exclude: /node_modules/, use: [ - 'postcss-loader' - ] + 'postcss-loader', + ], }, { test: /\.(svg)$/, use: [ { loader: 'raw-loader', - } - ] - } - ] + }, + ], + }, + ], }, devtool: NODE_ENV === 'development' ? 'source-map' : false, @@ -109,9 +105,9 @@ module.exports = (env, argv) => { minimizer: [ new TerserPlugin({ cache: true, - parallel: true - }) - ] - } + parallel: true, + }), + ], + }, }; }; diff --git a/yarn.lock b/yarn.lock index 8449137ae..0a5b9f99d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,1026 +2,1092 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" - integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" dependencies: - "@babel/highlight" "^7.0.0" + "@babel/highlight" "^7.8.3" -"@babel/core@>=7.1.0", "@babel/core@^7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.3.4.tgz#921a5a13746c21e32445bf0798680e9d11a6530b" - integrity sha512-jRsuseXBo9pN197KnDwhhaaBzyZr2oIcLHHTt2oDdQrej5Qp57dCCJafWx5ivU8/alEYDpssYqv1MUqcxwQlrA== +"@babel/compat-data@^7.8.6", "@babel/compat-data@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.0.tgz#04815556fc90b0c174abd2c0c1bb966faa036a6c" dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.3.4" - "@babel/helpers" "^7.2.0" - "@babel/parser" "^7.3.4" - "@babel/template" "^7.2.2" - "@babel/traverse" "^7.3.4" - "@babel/types" "^7.3.4" - convert-source-map "^1.1.0" + browserslist "^4.9.1" + invariant "^2.2.4" + semver "^5.5.0" + +"@babel/core@>=7.9.0", "@babel/core@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.9.0" + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helpers" "^7.9.0" + "@babel/parser" "^7.9.0" + "@babel/template" "^7.8.6" + "@babel/traverse" "^7.9.0" + "@babel/types" "^7.9.0" + convert-source-map "^1.7.0" debug "^4.1.0" - json5 "^2.1.0" - lodash "^4.17.11" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.13" resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.1.3": - version "7.1.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.1.3.tgz#2103ec9c42d9bdad9190a6ad5ff2d456fd7b8673" - integrity sha512-ZoCZGcfIJFJuZBqxcY9OjC1KW2lWK64qrX1o4UYL3yshVhwKFYgzpWZ0vvtGMNJdTlvkw0W+HR1VnYN8q3QPFQ== +"@babel/generator@^7.9.0", "@babel/generator@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.5.tgz#27f0917741acc41e6eaaced6d68f96c3fa9afaf9" dependencies: - "@babel/types" "^7.1.3" + "@babel/types" "^7.9.5" jsesc "^2.5.1" - lodash "^4.17.10" + lodash "^4.17.13" source-map "^0.5.0" - trim-right "^1.0.1" -"@babel/generator@^7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.4.tgz#9aa48c1989257877a9d971296e5b73bfe72e446e" - integrity sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg== +"@babel/helper-annotate-as-pure@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" dependencies: - "@babel/types" "^7.3.4" - jsesc "^2.5.1" - lodash "^4.17.11" - source-map "^0.5.0" - trim-right "^1.0.1" + "@babel/types" "^7.8.3" -"@babel/helper-annotate-as-pure@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" - integrity sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz#c84097a427a061ac56a1c30ebf54b7b22d241503" dependencies: - "@babel/types" "^7.0.0" + "@babel/helper-explode-assignable-expression" "^7.8.3" + "@babel/types" "^7.8.3" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f" - integrity sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w== +"@babel/helper-compilation-targets@^7.8.7": + version "7.8.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz#dac1eea159c0e4bd46e309b5a1b04a66b53c1dde" dependencies: - "@babel/helper-explode-assignable-expression" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/compat-data" "^7.8.6" + browserslist "^4.9.1" + invariant "^2.2.4" + levenary "^1.1.1" + semver "^5.5.0" -"@babel/helper-call-delegate@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz#6a957f105f37755e8645343d3038a22e1449cc4a" - integrity sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ== +"@babel/helper-create-regexp-features-plugin@^7.8.3", "@babel/helper-create-regexp-features-plugin@^7.8.8": + version "7.8.8" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz#5d84180b588f560b7864efaeea89243e58312087" dependencies: - "@babel/helper-hoist-variables" "^7.0.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-regex" "^7.8.3" + regexpu-core "^4.7.0" -"@babel/helper-define-map@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz#3b74caec329b3c80c116290887c0dd9ae468c20c" - integrity sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg== +"@babel/helper-define-map@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz#a0655cad5451c3760b726eba875f1cd8faa02c15" dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/types" "^7.0.0" - lodash "^4.17.10" + "@babel/helper-function-name" "^7.8.3" + "@babel/types" "^7.8.3" + lodash "^4.17.13" -"@babel/helper-explode-assignable-expression@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6" - integrity sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA== +"@babel/helper-explode-assignable-expression@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz#a728dc5b4e89e30fc2dfc7d04fa28a930653f982" dependencies: - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" -"@babel/helper-function-name@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" - integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw== +"@babel/helper-function-name@^7.8.3", "@babel/helper-function-name@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c" dependencies: - "@babel/helper-get-function-arity" "^7.0.0" - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.9.5" -"@babel/helper-get-function-arity@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" - integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== +"@babel/helper-get-function-arity@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" dependencies: - "@babel/types" "^7.0.0" + "@babel/types" "^7.8.3" -"@babel/helper-hoist-variables@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0.tgz#46adc4c5e758645ae7a45deb92bab0918c23bb88" - integrity sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w== +"@babel/helper-hoist-variables@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz#1dbe9b6b55d78c9b4183fc8cdc6e30ceb83b7134" dependencies: - "@babel/types" "^7.0.0" + "@babel/types" "^7.8.3" -"@babel/helper-member-expression-to-functions@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz#8cd14b0a0df7ff00f009e7d7a436945f47c7a16f" - integrity sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg== +"@babel/helper-member-expression-to-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" dependencies: - "@babel/types" "^7.0.0" + "@babel/types" "^7.8.3" -"@babel/helper-module-imports@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" - integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A== +"@babel/helper-module-imports@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498" dependencies: - "@babel/types" "^7.0.0" + "@babel/types" "^7.8.3" -"@babel/helper-module-transforms@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.1.0.tgz#470d4f9676d9fad50b324cdcce5fbabbc3da5787" - integrity sha512-0JZRd2yhawo79Rcm4w0LwSMILFmFXjugG3yqf+P/UsKsRS1mJCmMwwlHDlMg7Avr9LrvSpp4ZSULO9r8jpCzcw== +"@babel/helper-module-transforms@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz#43b34dfe15961918707d247327431388e9fe96e5" dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-simple-access" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.0.0" - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" - lodash "^4.17.10" + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.6" + "@babel/helper-simple-access" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/template" "^7.8.6" + "@babel/types" "^7.9.0" + lodash "^4.17.13" -"@babel/helper-optimise-call-expression@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz#a2920c5702b073c15de51106200aa8cad20497d5" - integrity sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g== +"@babel/helper-optimise-call-expression@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" dependencies: - "@babel/types" "^7.0.0" + "@babel/types" "^7.8.3" -"@babel/helper-plugin-utils@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" - integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" -"@babel/helper-regex@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.0.0.tgz#2c1718923b57f9bbe64705ffe5640ac64d9bdb27" - integrity sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg== +"@babel/helper-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.8.3.tgz#139772607d51b93f23effe72105b319d2a4c6965" dependencies: - lodash "^4.17.10" + lodash "^4.17.13" -"@babel/helper-remap-async-to-generator@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz#361d80821b6f38da75bd3f0785ece20a88c5fe7f" - integrity sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg== +"@babel/helper-remap-async-to-generator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz#273c600d8b9bf5006142c1e35887d555c12edd86" dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-wrap-function" "^7.1.0" - "@babel/template" "^7.1.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-wrap-function" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" -"@babel/helper-replace-supers@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.1.0.tgz#5fc31de522ec0ef0899dc9b3e7cf6a5dd655f362" - integrity sha512-BvcDWYZRWVuDeXTYZWxekQNO5D4kO55aArwZOTFXw6rlLQA8ZaDicJR1sO47h+HrnCiDFiww0fSPV0d713KBGQ== +"@babel/helper-replace-supers@^7.8.3", "@babel/helper-replace-supers@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz#5ada744fd5ad73203bf1d67459a27dcba67effc8" dependencies: - "@babel/helper-member-expression-to-functions" "^7.0.0" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/helper-member-expression-to-functions" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/traverse" "^7.8.6" + "@babel/types" "^7.8.6" -"@babel/helper-replace-supers@^7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.3.4.tgz#a795208e9b911a6eeb08e5891faacf06e7013e13" - integrity sha512-pvObL9WVf2ADs+ePg0jrqlhHoxRXlOa+SHRHzAXIz2xkYuOHfGl+fKxPMaS4Fq+uje8JQPobnertBBvyrWnQ1A== +"@babel/helper-simple-access@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae" dependencies: - "@babel/helper-member-expression-to-functions" "^7.0.0" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/traverse" "^7.3.4" - "@babel/types" "^7.3.4" + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" -"@babel/helper-simple-access@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" - integrity sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w== +"@babel/helper-split-export-declaration@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" dependencies: - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/types" "^7.8.3" -"@babel/helper-split-export-declaration@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz#3aae285c0311c2ab095d997b8c9a94cad547d813" - integrity sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag== - dependencies: - "@babel/types" "^7.0.0" +"@babel/helper-validator-identifier@^7.9.0", "@babel/helper-validator-identifier@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80" -"@babel/helper-wrap-function@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.1.0.tgz#8cf54e9190706067f016af8f75cb3df829cc8c66" - integrity sha512-R6HU3dete+rwsdAfrOzTlE9Mcpk4RjU3aX3gi9grtmugQY0u79X7eogUvfXA5sI81Mfq1cn6AgxihfN33STjJA== +"@babel/helper-wrap-function@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/template" "^7.1.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/helper-function-name" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" -"@babel/helpers@^7.2.0": - version "7.3.1" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.3.1.tgz#949eec9ea4b45d3210feb7dc1c22db664c9e44b9" - integrity sha512-Q82R3jKsVpUV99mgX50gOPCWwco9Ec5Iln/8Vyu4osNIOQgSrd9RFrQeUvmvddFNoLwMyOUWU+5ckioEKpDoGA== +"@babel/helpers@^7.9.0": + version "7.9.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.2.tgz#b42a81a811f1e7313b88cba8adc66b3d9ae6c09f" dependencies: - "@babel/template" "^7.1.2" - "@babel/traverse" "^7.1.5" - "@babel/types" "^7.3.0" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.9.0" + "@babel/types" "^7.9.0" -"@babel/highlight@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" - integrity sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw== +"@babel/highlight@^7.8.3": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079" dependencies: + "@babel/helper-validator-identifier" "^7.9.0" chalk "^2.0.0" - esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.1.2", "@babel/parser@^7.1.3": - version "7.1.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.1.3.tgz#2c92469bac2b7fbff810b67fca07bd138b48af77" - integrity sha512-gqmspPZOMW3MIRb9HlrnbZHXI1/KHTOroBwN1NcLL6pWxzqzEKGvRTq0W/PxS45OtQGbaFikSQpkS5zbnsQm2w== +"@babel/parser@^7.8.6", "@babel/parser@^7.9.0": + version "7.9.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" -"@babel/parser@^7.2.2", "@babel/parser@^7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.4.tgz#a43357e4bbf4b92a437fb9e465c192848287f27c" - integrity sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ== +"@babel/plugin-proposal-async-generator-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-remap-async-to-generator" "^7.8.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" -"@babel/plugin-proposal-async-generator-functions@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" - integrity sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ== +"@babel/plugin-proposal-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz#38c4fe555744826e97e2ae930b0fb4cc07e66054" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.1.0" - "@babel/plugin-syntax-async-generators" "^7.2.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" -"@babel/plugin-proposal-json-strings@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317" - integrity sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg== +"@babel/plugin-proposal-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz#da5216b238a98b58a1e05d6852104b10f9a70d6b" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-json-strings" "^7.2.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.0" -"@babel/plugin-proposal-object-rest-spread@^7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.4.tgz#47f73cf7f2a721aad5c0261205405c642e424654" - integrity sha512-j7VQmbbkA+qrzNqbKHrBsW3ddFnOeva6wzSe/zB7T+xaxGc+RCpwo44wCmRixAIGRoIpmVgvzFzNJqQcO3/9RA== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-optional-catch-binding@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" - integrity sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g== +"@babel/plugin-proposal-numeric-separator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz#5d6769409699ec9b3b68684cd8116cedff93bad8" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" -"@babel/plugin-proposal-unicode-property-regex@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.2.0.tgz#abe7281fe46c95ddc143a65e5358647792039520" - integrity sha512-LvRVYb7kikuOtIoUeWTkOxQEV1kYvL5B6U3iWEGCzPNRus1MzJweFqORTj+0jkxozkTSYNJozPOddxmqdqsRpw== +"@babel/plugin-proposal-object-rest-spread@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.5.tgz#3fd65911306d8746014ec0d0cf78f0e39a149116" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.0.0" - regexpu-core "^4.2.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-transform-parameters" "^7.9.5" -"@babel/plugin-syntax-async-generators@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" - integrity sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg== +"@babel/plugin-proposal-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz#9dee96ab1650eed88646ae9734ca167ac4a9c5c9" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" -"@babel/plugin-syntax-json-strings@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz#72bd13f6ffe1d25938129d2a186b11fd62951470" - integrity sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg== +"@babel/plugin-proposal-optional-chaining@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz#31db16b154c39d6b8a645292472b98394c292a58" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-syntax-object-rest-spread@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" - integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA== +"@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": + version "7.8.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz#ee3a95e90cdc04fe8cd92ec3279fa017d68a0d1d" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-create-regexp-features-plugin" "^7.8.8" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-optional-catch-binding@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c" - integrity sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w== +"@babel/plugin-syntax-async-generators@^7.8.0": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-transform-arrow-functions@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" - integrity sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg== +"@babel/plugin-syntax-dynamic-import@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-transform-async-to-generator@^7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.3.4.tgz#4e45408d3c3da231c0e7b823f407a53a7eb3048c" - integrity sha512-Y7nCzv2fw/jEZ9f678MuKdMo99MFDJMT/PvD9LisrR5JDFcJH6vYeH6RnjVt3p5tceyGRvTtEN0VOlU+rgHZjA== +"@babel/plugin-syntax-json-strings@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.1.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-transform-block-scoped-functions@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190" - integrity sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w== +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-transform-block-scoping@^7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.3.4.tgz#5c22c339de234076eee96c8783b2fed61202c5c4" - integrity sha512-blRr2O8IOZLAOJklXLV4WhcEzpYafYQKSGT3+R26lWG41u/FODJuBggehtOwilVAcFu393v3OFj+HmaE6tVjhA== +"@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz#0e3fb63e09bea1b11e96467271c8308007e7c41f" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - lodash "^4.17.11" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-classes@^7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.3.4.tgz#dc173cb999c6c5297e0b5f2277fdaaec3739d0cc" - integrity sha512-J9fAvCFBkXEvBimgYxCjvaVDzL6thk0j0dBvCeZmIUDBwyt+nv6HfbImsSrWsYXfDNDivyANgJlFXDUWRTZBuA== +"@babel/plugin-syntax-object-rest-spread@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-define-map" "^7.1.0" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.3.4" - "@babel/helper-split-export-declaration" "^7.0.0" - globals "^11.1.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-transform-computed-properties@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da" - integrity sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA== +"@babel/plugin-syntax-optional-catch-binding@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-transform-destructuring@^7.2.0": - version "7.3.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.3.2.tgz#f2f5520be055ba1c38c41c0e094d8a461dd78f2d" - integrity sha512-Lrj/u53Ufqxl/sGxyjsJ2XNtNuEjDyjpqdhMNh5aZ+XFOdThL46KBj27Uem4ggoezSYBxKWAil6Hu8HtwqesYw== +"@babel/plugin-syntax-optional-chaining@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-transform-dotall-regex@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.2.0.tgz#f0aabb93d120a8ac61e925ea0ba440812dbe0e49" - integrity sha512-sKxnyHfizweTgKZf7XsXu/CNupKhzijptfTM+bozonIuyVrLWVUvYjE2bhuSBML8VQeMxq4Mm63Q9qvcvUcciQ== +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz#3acdece695e6b13aaf57fc291d1a800950c71391" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.0.0" - regexpu-core "^4.1.3" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-duplicate-keys@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz#d952c4930f312a4dbfff18f0b2914e60c35530b3" - integrity sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw== +"@babel/plugin-transform-arrow-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz#82776c2ed0cd9e1a49956daeb896024c9473b8b6" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-exponentiation-operator@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008" - integrity sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A== +"@babel/plugin-transform-async-to-generator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz#4308fad0d9409d71eafb9b1a6ee35f9d64b64086" dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-remap-async-to-generator" "^7.8.3" -"@babel/plugin-transform-for-of@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.2.0.tgz#ab7468befa80f764bb03d3cb5eef8cc998e1cad9" - integrity sha512-Kz7Mt0SsV2tQk6jG5bBv5phVbkd0gd27SgYD4hH1aLMJRchM0dzHaXvrWhVZ+WxAlDoAKZ7Uy3jVTW2mKXQ1WQ== +"@babel/plugin-transform-block-scoped-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz#437eec5b799b5852072084b3ae5ef66e8349e8a3" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-function-name@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.2.0.tgz#f7930362829ff99a3174c39f0afcc024ef59731a" - integrity sha512-kWgksow9lHdvBC2Z4mxTsvc7YdY7w/V6B2vy9cTIPtLEE9NhwoWivaxdNM/S37elu5bqlLP/qOY906LukO9lkQ== +"@babel/plugin-transform-block-scoping@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz#97d35dab66857a437c166358b91d09050c868f3a" dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" + lodash "^4.17.13" -"@babel/plugin-transform-literals@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz#690353e81f9267dad4fd8cfd77eafa86aba53ea1" - integrity sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg== +"@babel/plugin-transform-classes@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.5.tgz#800597ddb8aefc2c293ed27459c1fcc935a26c2c" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-define-map" "^7.8.3" + "@babel/helper-function-name" "^7.9.5" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.6" + "@babel/helper-split-export-declaration" "^7.8.3" + globals "^11.1.0" -"@babel/plugin-transform-modules-amd@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz#82a9bce45b95441f617a24011dc89d12da7f4ee6" - integrity sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw== +"@babel/plugin-transform-computed-properties@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz#96d0d28b7f7ce4eb5b120bb2e0e943343c86f81b" dependencies: - "@babel/helper-module-transforms" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-modules-commonjs@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.2.0.tgz#c4f1933f5991d5145e9cfad1dfd848ea1727f404" - integrity sha512-V6y0uaUQrQPXUrmj+hgnks8va2L0zcZymeU7TtWEgdRLNkceafKXEduv7QzgQAE4lT+suwooG9dC7LFhdRAbVQ== +"@babel/plugin-transform-destructuring@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.9.5.tgz#72c97cf5f38604aea3abf3b935b0e17b1db76a50" dependencies: - "@babel/helper-module-transforms" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-simple-access" "^7.1.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-modules-systemjs@^7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.3.4.tgz#813b34cd9acb6ba70a84939f3680be0eb2e58861" - integrity sha512-VZ4+jlGOF36S7TjKs8g4ojp4MEI+ebCQZdswWb/T9I4X84j8OtFAyjXjt/M16iIm5RIZn0UMQgg/VgIwo/87vw== +"@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" dependencies: - "@babel/helper-hoist-variables" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-modules-umd@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz#7678ce75169f0877b8eb2235538c074268dd01ae" - integrity sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw== +"@babel/plugin-transform-duplicate-keys@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz#8d12df309aa537f272899c565ea1768e286e21f1" dependencies: - "@babel/helper-module-transforms" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-named-capturing-groups-regex@^7.3.0": - version "7.3.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.3.0.tgz#140b52985b2d6ef0cb092ef3b29502b990f9cd50" - integrity sha512-NxIoNVhk9ZxS+9lSoAQ/LM0V2UEvARLttEHUrRDGKFaAxOYQcrkN/nLRE+BbbicCAvZPl7wMP0X60HsHE5DtQw== +"@babel/plugin-transform-exponentiation-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz#581a6d7f56970e06bf51560cd64f5e947b70d7b7" dependencies: - regexp-tree "^0.1.0" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-new-target@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz#ae8fbd89517fa7892d20e6564e641e8770c3aa4a" - integrity sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw== +"@babel/plugin-transform-for-of@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz#0f260e27d3e29cd1bb3128da5e76c761aa6c108e" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-object-super@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz#b35d4c10f56bab5d650047dad0f1d8e8814b6598" - integrity sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg== +"@babel/plugin-transform-function-name@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz#279373cb27322aaad67c2683e776dfc47196ed8b" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.1.0" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-parameters@^7.2.0": - version "7.3.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.3.3.tgz#3a873e07114e1a5bee17d04815662c8317f10e30" - integrity sha512-IrIP25VvXWu/VlBWTpsjGptpomtIkYrN/3aDp4UKm7xK6UxZY88kcJ1UwETbzHAlwN21MnNfwlar0u8y3KpiXw== +"@babel/plugin-transform-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz#aef239823d91994ec7b68e55193525d76dbd5dc1" dependencies: - "@babel/helper-call-delegate" "^7.1.0" - "@babel/helper-get-function-arity" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-regenerator@^7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.3.4.tgz#1601655c362f5b38eead6a52631f5106b29fa46a" - integrity sha512-hvJg8EReQvXT6G9H2MvNPXkv9zK36Vxa1+csAVTpE1J3j0zlHplw76uudEbJxgvqZzAq9Yh45FLD4pk5mKRFQA== +"@babel/plugin-transform-member-expression-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz#963fed4b620ac7cbf6029c755424029fa3a40410" dependencies: - regenerator-transform "^0.13.4" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-runtime@^7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.3.4.tgz#57805ac8c1798d102ecd75c03b024a5b3ea9b431" - integrity sha512-PaoARuztAdd5MgeVjAxnIDAIUet5KpogqaefQvPOmPYCxYoaPhautxDh3aO8a4xHsKgT/b9gSxR0BKK1MIewPA== +"@babel/plugin-transform-modules-amd@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.0.tgz#19755ee721912cf5bb04c07d50280af3484efef4" dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - resolve "^1.8.1" - semver "^5.5.1" + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-shorthand-properties@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0" - integrity sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg== +"@babel/plugin-transform-modules-commonjs@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz#e3e72f4cbc9b4a260e30be0ea59bdf5a39748940" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-simple-access" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-spread@^7.2.0": - version "7.2.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz#3103a9abe22f742b6d406ecd3cd49b774919b406" - integrity sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w== +"@babel/plugin-transform-modules-systemjs@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.0.tgz#e9fd46a296fc91e009b64e07ddaa86d6f0edeb90" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-hoist-variables" "^7.8.3" + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-sticky-regex@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" - integrity sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw== +"@babel/plugin-transform-modules-umd@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz#e909acae276fec280f9b821a5f38e1f08b480697" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.0.0" + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-template-literals@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.2.0.tgz#d87ed01b8eaac7a92473f608c97c089de2ba1e5b" - integrity sha512-FkPix00J9A/XWXv4VoKJBMeSkyY9x/TqIh76wzcdfl57RJJcf8CehQ08uwfhCDNtRQYtHQKBTwKZDEyjE13Lwg== +"@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz#a2a72bffa202ac0e2d0506afd0939c5ecbc48c6c" dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-create-regexp-features-plugin" "^7.8.3" -"@babel/plugin-transform-typeof-symbol@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz#117d2bcec2fbf64b4b59d1f9819894682d29f2b2" - integrity sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw== +"@babel/plugin-transform-new-target@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz#60cc2ae66d85c95ab540eb34babb6434d4c70c43" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-unicode-regex@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.2.0.tgz#4eb8db16f972f8abb5062c161b8b115546ade08b" - integrity sha512-m48Y0lMhrbXEJnVUaYly29jRXbQ3ksxPrS1Tg8t+MHqzXhtBYAvI51euOBaoAlZLPHsieY9XPVMf80a5x0cPcA== +"@babel/plugin-transform-object-super@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz#ebb6a1e7a86ffa96858bd6ac0102d65944261725" dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.0.0" - regexpu-core "^4.1.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.3" -"@babel/polyfill@^7.2.5": - version "7.2.5" - resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.2.5.tgz#6c54b964f71ad27edddc567d065e57e87ed7fa7d" - integrity sha512-8Y/t3MWThtMLYr0YNC/Q76tqN1w30+b0uQMeFUYauG2UGTR19zyUtFrAzT23zNtBxPp+LbE5E/nwV/q/r3y6ug== +"@babel/plugin-transform-parameters@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.5.tgz#173b265746f5e15b2afe527eeda65b73623a0795" dependencies: - core-js "^2.5.7" - regenerator-runtime "^0.12.0" + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/preset-env@^7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.3.4.tgz#887cf38b6d23c82f19b5135298bdb160062e33e1" - integrity sha512-2mwqfYMK8weA0g0uBKOt4FE3iEodiHy9/CW0b+nWXcbL+pGzLx8ESYc+j9IIxr6LTDHWKgPm71i9smo02bw+gA== +"@babel/plugin-transform-property-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz#33194300d8539c1ed28c62ad5087ba3807b98263" dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-async-generator-functions" "^7.2.0" - "@babel/plugin-proposal-json-strings" "^7.2.0" - "@babel/plugin-proposal-object-rest-spread" "^7.3.4" - "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.2.0" - "@babel/plugin-syntax-async-generators" "^7.2.0" - "@babel/plugin-syntax-json-strings" "^7.2.0" - "@babel/plugin-syntax-object-rest-spread" "^7.2.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" - "@babel/plugin-transform-arrow-functions" "^7.2.0" - "@babel/plugin-transform-async-to-generator" "^7.3.4" - "@babel/plugin-transform-block-scoped-functions" "^7.2.0" - "@babel/plugin-transform-block-scoping" "^7.3.4" - "@babel/plugin-transform-classes" "^7.3.4" - "@babel/plugin-transform-computed-properties" "^7.2.0" - "@babel/plugin-transform-destructuring" "^7.2.0" - "@babel/plugin-transform-dotall-regex" "^7.2.0" - "@babel/plugin-transform-duplicate-keys" "^7.2.0" - "@babel/plugin-transform-exponentiation-operator" "^7.2.0" - "@babel/plugin-transform-for-of" "^7.2.0" - "@babel/plugin-transform-function-name" "^7.2.0" - "@babel/plugin-transform-literals" "^7.2.0" - "@babel/plugin-transform-modules-amd" "^7.2.0" - "@babel/plugin-transform-modules-commonjs" "^7.2.0" - "@babel/plugin-transform-modules-systemjs" "^7.3.4" - "@babel/plugin-transform-modules-umd" "^7.2.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.3.0" - "@babel/plugin-transform-new-target" "^7.0.0" - "@babel/plugin-transform-object-super" "^7.2.0" - "@babel/plugin-transform-parameters" "^7.2.0" - "@babel/plugin-transform-regenerator" "^7.3.4" - "@babel/plugin-transform-shorthand-properties" "^7.2.0" - "@babel/plugin-transform-spread" "^7.2.0" - "@babel/plugin-transform-sticky-regex" "^7.2.0" - "@babel/plugin-transform-template-literals" "^7.2.0" - "@babel/plugin-transform-typeof-symbol" "^7.2.0" - "@babel/plugin-transform-unicode-regex" "^7.2.0" - browserslist "^4.3.4" - invariant "^2.2.2" - js-levenshtein "^1.1.3" - semver "^5.3.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/register@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.0.0.tgz#fa634bae1bfa429f60615b754fc1f1d745edd827" - integrity sha512-f/+CRmaCe7rVEvcvPvxeA8j5aJhHC3aJie7YuqcMDhUOuyWLA7J/aNrTaHIzoWPEhpHA54mec4Mm8fv8KBlv3g== +"@babel/plugin-transform-regenerator@^7.8.7": + version "7.8.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz#5e46a0dca2bee1ad8285eb0527e6abc9c37672f8" dependencies: - core-js "^2.5.7" - find-cache-dir "^1.0.0" - home-or-tmp "^3.0.0" - lodash "^4.17.10" - mkdirp "^0.5.1" - pirates "^4.0.0" - source-map-support "^0.5.9" + regenerator-transform "^0.14.2" -"@babel/runtime@^7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.4.tgz#73d12ba819e365fcf7fd152aed56d6df97d21c83" - integrity sha512-IvfvnMdSaLBateu0jfsYIpZTxAc2cKEXEMiezGGN75QcBcecDUKd3PgLAncT0oOgxKy8dd8hrJKj9MfzgfZd6g== +"@babel/plugin-transform-reserved-words@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz#9a0635ac4e665d29b162837dd3cc50745dfdf1f5" dependencies: - regenerator-runtime "^0.12.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/template@^7.1.0", "@babel/template@^7.1.2": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.1.2.tgz#090484a574fef5a2d2d7726a674eceda5c5b5644" - integrity sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag== +"@babel/plugin-transform-runtime@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.9.0.tgz#45468c0ae74cc13204e1d3b1f4ce6ee83258af0b" dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.1.2" - "@babel/types" "^7.1.2" + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + resolve "^1.8.1" + semver "^5.5.1" -"@babel/template@^7.2.2": - version "7.2.2" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907" - integrity sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g== +"@babel/plugin-transform-shorthand-properties@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz#28545216e023a832d4d3a1185ed492bcfeac08c8" + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz#9c8ffe8170fdfb88b114ecb920b82fb6e95fe5e8" + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-sticky-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz#be7a1290f81dae767475452199e1f76d6175b100" + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-regex" "^7.8.3" + +"@babel/plugin-transform-template-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz#7bfa4732b455ea6a43130adc0ba767ec0e402a80" + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-typeof-symbol@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz#ede4062315ce0aaf8a657a920858f1a2f35fc412" + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-unicode-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz#0cef36e3ba73e5c57273effb182f46b91a1ecaad" + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/polyfill@^7.8.7": + version "7.8.7" + resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.8.7.tgz#151ec24c7135481336168c3bd8b8bf0cf91c032f" + dependencies: + core-js "^2.6.5" + regenerator-runtime "^0.13.4" + +"@babel/preset-env@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.5.tgz#8ddc76039bc45b774b19e2fc548f6807d8a8919f" + dependencies: + "@babel/compat-data" "^7.9.0" + "@babel/helper-compilation-targets" "^7.8.7" + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-proposal-async-generator-functions" "^7.8.3" + "@babel/plugin-proposal-dynamic-import" "^7.8.3" + "@babel/plugin-proposal-json-strings" "^7.8.3" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-proposal-numeric-separator" "^7.8.3" + "@babel/plugin-proposal-object-rest-spread" "^7.9.5" + "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" + "@babel/plugin-proposal-optional-chaining" "^7.9.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-numeric-separator" "^7.8.0" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + "@babel/plugin-transform-arrow-functions" "^7.8.3" + "@babel/plugin-transform-async-to-generator" "^7.8.3" + "@babel/plugin-transform-block-scoped-functions" "^7.8.3" + "@babel/plugin-transform-block-scoping" "^7.8.3" + "@babel/plugin-transform-classes" "^7.9.5" + "@babel/plugin-transform-computed-properties" "^7.8.3" + "@babel/plugin-transform-destructuring" "^7.9.5" + "@babel/plugin-transform-dotall-regex" "^7.8.3" + "@babel/plugin-transform-duplicate-keys" "^7.8.3" + "@babel/plugin-transform-exponentiation-operator" "^7.8.3" + "@babel/plugin-transform-for-of" "^7.9.0" + "@babel/plugin-transform-function-name" "^7.8.3" + "@babel/plugin-transform-literals" "^7.8.3" + "@babel/plugin-transform-member-expression-literals" "^7.8.3" + "@babel/plugin-transform-modules-amd" "^7.9.0" + "@babel/plugin-transform-modules-commonjs" "^7.9.0" + "@babel/plugin-transform-modules-systemjs" "^7.9.0" + "@babel/plugin-transform-modules-umd" "^7.9.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" + "@babel/plugin-transform-new-target" "^7.8.3" + "@babel/plugin-transform-object-super" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.9.5" + "@babel/plugin-transform-property-literals" "^7.8.3" + "@babel/plugin-transform-regenerator" "^7.8.7" + "@babel/plugin-transform-reserved-words" "^7.8.3" + "@babel/plugin-transform-shorthand-properties" "^7.8.3" + "@babel/plugin-transform-spread" "^7.8.3" + "@babel/plugin-transform-sticky-regex" "^7.8.3" + "@babel/plugin-transform-template-literals" "^7.8.3" + "@babel/plugin-transform-typeof-symbol" "^7.8.4" + "@babel/plugin-transform-unicode-regex" "^7.8.3" + "@babel/preset-modules" "^0.1.3" + "@babel/types" "^7.9.5" + browserslist "^4.9.1" + core-js-compat "^3.6.2" + invariant "^2.2.2" + levenary "^1.1.1" + semver "^5.5.0" + +"@babel/preset-modules@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.2.2" - "@babel/types" "^7.2.2" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + esutils "^2.0.2" -"@babel/traverse@^7.1.0": - version "7.1.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.1.4.tgz#f4f83b93d649b4b2c91121a9087fa2fa949ec2b4" - integrity sha512-my9mdrAIGdDiSVBuMjpn/oXYpva0/EZwWL3sm3Wcy/AVWO2eXnsoZruOT9jOGNRXU8KbCIu5zsKnXcAJ6PcV6Q== +"@babel/register@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.9.0.tgz#02464ede57548bddbb5e9f705d263b7c3f43d48b" dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.1.3" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.0.0" - "@babel/parser" "^7.1.3" - "@babel/types" "^7.1.3" - debug "^3.1.0" - globals "^11.1.0" - lodash "^4.17.10" + find-cache-dir "^2.0.0" + lodash "^4.17.13" + make-dir "^2.1.0" + pirates "^4.0.0" + source-map-support "^0.5.16" -"@babel/traverse@^7.1.5", "@babel/traverse@^7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.3.4.tgz#1330aab72234f8dea091b08c4f8b9d05c7119e06" - integrity sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ== +"@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": + version "7.9.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06" dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.3.4" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.0.0" - "@babel/parser" "^7.3.4" - "@babel/types" "^7.3.4" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.11" + regenerator-runtime "^0.13.4" -"@babel/types@^7.0.0", "@babel/types@^7.1.2", "@babel/types@^7.1.3": - version "7.1.3" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.1.3.tgz#3a767004567060c2f40fca49a304712c525ee37d" - integrity sha512-RpPOVfK+yatXyn8n4PB1NW6k9qjinrXrRR8ugBN8fD6hCy5RXI6PSbVqpOJBO9oSaY7Nom4ohj35feb0UR9hSA== +"@babel/template@^7.8.3", "@babel/template@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" dependencies: - esutils "^2.0.2" - lodash "^4.17.10" - to-fast-properties "^2.0.0" + "@babel/code-frame" "^7.8.3" + "@babel/parser" "^7.8.6" + "@babel/types" "^7.8.6" -"@babel/types@^7.2.2", "@babel/types@^7.3.0", "@babel/types@^7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.3.4.tgz#bf482eaeaffb367a28abbf9357a94963235d90ed" - integrity sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ== +"@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.5.tgz#6e7c56b44e2ac7011a948c21e283ddd9d9db97a2" dependencies: - esutils "^2.0.2" - lodash "^4.17.11" + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.9.5" + "@babel/helper-function-name" "^7.9.5" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/parser" "^7.9.0" + "@babel/types" "^7.9.5" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.5.tgz#89231f82915a8a566a703b3b20133f73da6b9444" + dependencies: + "@babel/helper-validator-identifier" "^7.9.5" + lodash "^4.17.13" to-fast-properties "^2.0.0" -"@codexteam/shortcuts@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@codexteam/shortcuts/-/shortcuts-1.0.0.tgz#9d66a7c00c93be05b7940d46d2a82af442e8b46d" - integrity sha512-G7047f4qHnPtft2Gj7RsjJdXat/XXswUPjIGPHyHZeoARyIZTfX4/yTkgA3oDXvjFoC4cWN2+mKDDMdOET9/GQ== +"@codexteam/shortcuts@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@codexteam/shortcuts/-/shortcuts-1.1.1.tgz#6aa19ed0476da78045847ddc6d5b311f2f015094" "@csstools/convert-colors@^1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" - integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw== -"@mrmlnc/readdir-enhanced@^2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" - integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== +"@cypress/listr-verbose-renderer@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#a77492f4b11dcc7c446a34b3e28721afd33c642a" + integrity sha1-p3SS9LEdzHxEajSz4ochr9M8ZCo= dependencies: - call-me-maybe "^1.0.1" - glob-to-regexp "^0.3.0" + chalk "^1.1.3" + cli-cursor "^1.0.2" + date-fns "^1.27.2" + figures "^1.7.0" + +"@cypress/request@^2.88.5": + version "2.88.5" + resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.5.tgz#8d7ecd17b53a849cfd5ab06d5abe7d84976375d7" + integrity sha512-TzEC1XMi1hJkywWpRfD2clreTa/Z+lOrXDCxxBTBPEcY5azdPi56A6Xw+O4tWJnaJH3iIE7G5aDXZC6JgRZLcA== + dependencies: + 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.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" -"@nodelib/fs.stat@^1.1.2": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" - integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== +"@cypress/xvfb@^1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@cypress/xvfb/-/xvfb-1.2.4.tgz#2daf42e8275b39f4aa53c14214e557bd14e7748a" + integrity sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q== + dependencies: + debug "^3.1.0" + lodash.once "^4.1.1" + +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + +"@samverschueren/stream-to-observable@^0.3.0": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz#a21117b19ee9be70c379ec1877537ef2e1c63301" + integrity sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ== + dependencies: + any-observable "^0.3.0" + +"@stylelint/postcss-css-in-js@^0.37.1": + version "0.37.1" + resolved "https://registry.yarnpkg.com/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.37.1.tgz#41e5e7660f73d88227610e18c6ebb262d56ac125" + dependencies: + "@babel/core" ">=7.9.0" + +"@stylelint/postcss-markdown@^0.36.1": + version "0.36.1" + resolved "https://registry.yarnpkg.com/@stylelint/postcss-markdown/-/postcss-markdown-0.36.1.tgz#829b87e6c0f108014533d9d7b987dc9efb6632e8" + dependencies: + remark "^12.0.0" + unist-util-find-all-after "^3.0.1" "@types/anymatch@*": version "1.3.1" resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a" - integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA== -"@types/events@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" - integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== +"@types/color-name@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" -"@types/glob@^7.1.1": - version "7.1.1" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" - integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== - dependencies: - "@types/events" "*" - "@types/minimatch" "*" - "@types/node" "*" +"@types/eslint-visitor-keys@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" -"@types/minimatch@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" - integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== +"@types/json-schema@^7.0.3": + version "7.0.4" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" + +"@types/minimist@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6" "@types/node@*": - version "10.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.11.7.tgz#0e75ca9357d646ca754016ca1d68a127ad7e7300" - integrity sha512-yOxFfkN9xUFLyvWaeYj90mlqTJ41CsQzWKS3gXdOMOyPVacUsymejKxJ4/pMW7exouubuEeZLJawGgcNGYlTeg== + version "13.13.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.2.tgz#160d82623610db590a64e8ca81784e11117e5a54" + +"@types/normalize-package-data@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" + +"@types/parse-json@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" "@types/q@^1.5.1": version "1.5.2" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" - integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== + +"@types/sinonjs__fake-timers@^6.0.1": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz#3a84cf5ec3249439015e14049bd3161419bf9eae" + integrity sha512-dIPoZ3g5gcx9zZEszaxLSVTvMReD3xxyyDnQUjA6IYDG9Ba2AV0otMPs+77sG9ojB4Qr2N2Vk5RnKeuA0X/0bg== + +"@types/sizzle@^2.3.2": + version "2.3.2" + resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47" + integrity sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg== "@types/source-list-map@*": version "0.1.2" resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" - integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA== "@types/tapable@*": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.4.tgz#b4ffc7dc97b498c969b360a41eee247f82616370" - integrity sha512-78AdXtlhpCHT0K3EytMpn4JNxaf5tbqbLcbIRoQIHzpTIyjpxLQKRoxU55ujBXAtg3Nl2h/XWvfDa9dsMOd0pQ== + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.5.tgz#9adbc12950582aa65ead76bffdf39fe0c27a3c02" "@types/uglify-js@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.0.3.tgz#801a5ca1dc642861f47c46d14b700ed2d610840b" - integrity sha512-MAT0BW2ruO0LhQKjvlipLGCF/Yx0y/cj+tT67tK3QIQDrM2+9R78HgJ54VlrE8AbfjYJJBCQCEPM5ZblPVTuww== + version "3.9.0" + resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.9.0.tgz#4490a140ca82aa855ad68093829e7fd6ae94ea87" dependencies: source-map "^0.6.1" -"@types/unist@*", "@types/unist@^2.0.0": +"@types/unist@^2.0.0", "@types/unist@^2.0.2": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" - integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== -"@types/vfile-message@*": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@types/vfile-message/-/vfile-message-1.0.1.tgz#e1e9895cc6b36c462d4244e64e6d0b6eaf65355a" - integrity sha512-mlGER3Aqmq7bqR1tTTIVHq8KSAFFRyGbrxuM8C/H82g6k7r2fS+IMEkIu3D7JHzG10NvPdR8DNx0jr0pwpp4dA== - dependencies: - "@types/node" "*" - "@types/unist" "*" +"@types/webpack-env@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.15.2.tgz#927997342bb9f4a5185a86e6579a0a18afc33b0a" -"@types/vfile@^3.0.0": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@types/vfile/-/vfile-3.0.2.tgz#19c18cd232df11ce6fa6ad80259bc86c366b09b9" - integrity sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw== - dependencies: - "@types/node" "*" - "@types/unist" "*" - "@types/vfile-message" "*" - -"@types/webpack-env@^1.13.9": - version "1.13.9" - resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.9.tgz#a67287861c928ebf4159a908d1fb1a2a34d4097a" - integrity sha512-p8zp5xqkly3g4cCmo2mKOHI9+Z/kObmDj0BmjbDDJQlgDTiEGTbm17MEwTAusV6XceCy+bNw9q/ZHXHyKo3zkg== - -"@types/webpack-sources@^0.1.5": - version "0.1.5" - resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-0.1.5.tgz#be47c10f783d3d6efe1471ff7f042611bd464a92" - integrity sha512-zfvjpp7jiafSmrzJ2/i3LqOyTYTuJ7u1KOXlKgDlvsj9Rr0x7ZiYu5lZbXwobL7lmsRNtPXlBfmaUD8eU2Hu8w== +"@types/webpack-sources@*", "@types/webpack-sources@^0.1.5": + version "0.1.7" + resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-0.1.7.tgz#0a330a9456113410c74a5d64180af0cbca007141" dependencies: "@types/node" "*" "@types/source-list-map" "*" source-map "^0.6.1" -"@types/webpack@^4.4.25": - version "4.4.25" - resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.4.25.tgz#c8a1eb968a33a3e6da641f529c5add0d44d34809" - integrity sha512-YaYVbSK1bC3xiAWFLSgDQyVHdCTNq5cLlcx633basmrwSoUxJiv4SZ0SoT1uoF15zWx98afOcCbqA1YHeCdRYA== +"@types/webpack@^4.41.12": + version "4.41.12" + resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.12.tgz#0386ee2a2814368e2f2397abb036c0bf173ff6c3" dependencies: "@types/anymatch" "*" "@types/node" "*" "@types/tapable" "*" "@types/uglify-js" "*" + "@types/webpack-sources" "*" source-map "^0.6.0" -"@webassemblyjs/ast@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" - integrity sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ== - dependencies: - "@webassemblyjs/helper-module-context" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/wast-parser" "1.8.5" - -"@webassemblyjs/floating-point-hex-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz#1ba926a2923613edce496fd5b02e8ce8a5f49721" - integrity sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ== - -"@webassemblyjs/helper-api-error@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz#c49dad22f645227c5edb610bdb9697f1aab721f7" - integrity sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA== - -"@webassemblyjs/helper-buffer@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz#fea93e429863dd5e4338555f42292385a653f204" - integrity sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q== - -"@webassemblyjs/helper-code-frame@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz#9a740ff48e3faa3022b1dff54423df9aa293c25e" - integrity sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ== - dependencies: - "@webassemblyjs/wast-printer" "1.8.5" - -"@webassemblyjs/helper-fsm@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz#ba0b7d3b3f7e4733da6059c9332275d860702452" - integrity sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow== - -"@webassemblyjs/helper-module-context@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz#def4b9927b0101dc8cbbd8d1edb5b7b9c82eb245" - integrity sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g== - dependencies: - "@webassemblyjs/ast" "1.8.5" - mamacro "^0.0.3" - -"@webassemblyjs/helper-wasm-bytecode@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz#537a750eddf5c1e932f3744206551c91c1b93e61" - integrity sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ== - -"@webassemblyjs/helper-wasm-section@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz#74ca6a6bcbe19e50a3b6b462847e69503e6bfcbf" - integrity sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - -"@webassemblyjs/ieee754@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz#712329dbef240f36bf57bd2f7b8fb9bf4154421e" - integrity sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g== +"@typescript-eslint/eslint-plugin@^2.12.0": + version "2.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.29.0.tgz#c9efab7624e3dd6d144a0e4577a541d1bd42c2ac" + dependencies: + "@typescript-eslint/experimental-utils" "2.29.0" + functional-red-black-tree "^1.0.1" + regexpp "^3.0.0" + tsutils "^3.17.1" + +"@typescript-eslint/experimental-utils@2.29.0": + version "2.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.29.0.tgz#3cb8060de9265ba131625a96bbfec31ba6d4a0fe" + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/typescript-estree" "2.29.0" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + +"@typescript-eslint/parser@^2.12.0": + version "2.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.29.0.tgz#6e3c4e21ed6393dc05b9d8b47f0b7e731ef21c9c" + dependencies: + "@types/eslint-visitor-keys" "^1.0.0" + "@typescript-eslint/experimental-utils" "2.29.0" + "@typescript-eslint/typescript-estree" "2.29.0" + eslint-visitor-keys "^1.1.0" + +"@typescript-eslint/typescript-estree@2.29.0": + version "2.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.29.0.tgz#1be6612bb02fc37ac9f466521c1459a4744e8d3a" + dependencies: + debug "^4.1.1" + eslint-visitor-keys "^1.1.0" + glob "^7.1.6" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^6.3.0" + tsutils "^3.17.1" + +"@webassemblyjs/ast@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" + dependencies: + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" + +"@webassemblyjs/floating-point-hex-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" + +"@webassemblyjs/helper-api-error@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" + +"@webassemblyjs/helper-buffer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" + +"@webassemblyjs/helper-code-frame@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" + dependencies: + "@webassemblyjs/wast-printer" "1.9.0" + +"@webassemblyjs/helper-fsm@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" + +"@webassemblyjs/helper-module-context@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" + dependencies: + "@webassemblyjs/ast" "1.9.0" + +"@webassemblyjs/helper-wasm-bytecode@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" + +"@webassemblyjs/helper-wasm-section@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + +"@webassemblyjs/ieee754@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.8.5.tgz#044edeb34ea679f3e04cd4fd9824d5e35767ae10" - integrity sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A== +"@webassemblyjs/leb128@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.8.5.tgz#a8bf3b5d8ffe986c7c1e373ccbdc2a0915f0cedc" - integrity sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw== - -"@webassemblyjs/wasm-edit@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz#962da12aa5acc1c131c81c4232991c82ce56e01a" - integrity sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/helper-wasm-section" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - "@webassemblyjs/wasm-opt" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" - "@webassemblyjs/wast-printer" "1.8.5" - -"@webassemblyjs/wasm-gen@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz#54840766c2c1002eb64ed1abe720aded714f98bc" - integrity sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/ieee754" "1.8.5" - "@webassemblyjs/leb128" "1.8.5" - "@webassemblyjs/utf8" "1.8.5" - -"@webassemblyjs/wasm-opt@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz#b24d9f6ba50394af1349f510afa8ffcb8a63d264" - integrity sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" - -"@webassemblyjs/wasm-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz#21576f0ec88b91427357b8536383668ef7c66b8d" - integrity sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-api-error" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/ieee754" "1.8.5" - "@webassemblyjs/leb128" "1.8.5" - "@webassemblyjs/utf8" "1.8.5" - -"@webassemblyjs/wast-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz#e10eecd542d0e7bd394f6827c49f3df6d4eefb8c" - integrity sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/floating-point-hex-parser" "1.8.5" - "@webassemblyjs/helper-api-error" "1.8.5" - "@webassemblyjs/helper-code-frame" "1.8.5" - "@webassemblyjs/helper-fsm" "1.8.5" +"@webassemblyjs/utf8@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" + +"@webassemblyjs/wasm-edit@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/helper-wasm-section" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-opt" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + "@webassemblyjs/wast-printer" "1.9.0" + +"@webassemblyjs/wasm-gen@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" + +"@webassemblyjs/wasm-opt@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + +"@webassemblyjs/wasm-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" + +"@webassemblyjs/wast-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/floating-point-hex-parser" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-code-frame" "1.9.0" + "@webassemblyjs/helper-fsm" "1.9.0" "@xtuc/long" "4.2.2" -"@webassemblyjs/wast-printer@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz#114bbc481fd10ca0e23b3560fa812748b0bae5bc" - integrity sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg== +"@webassemblyjs/wast-printer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/wast-parser" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" "@xtuc/long" "4.2.2" "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== "@xtuc/long@4.2.2": version "4.2.2" resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +acorn-jsx@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe" -acorn-dynamic-import@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" - integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== +acorn@^6.4.1: + version "6.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" -acorn-jsx@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" - integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== +acorn@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf" -acorn@^6.0.5, acorn@^6.0.7: - version "6.1.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" - integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== +aggregate-error@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" ajv-errors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.0.tgz#ecf021fa108fd17dfb5e6b383f2dd233e31ffc59" - integrity sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk= + version "1.0.1" + resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" -ajv-keywords@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" - integrity sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo= +ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" ajv@^5.0.0: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= dependencies: co "^4.6.0" fast-deep-equal "^1.0.0" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" -ajv@^6.1.0, ajv@^6.5.3: - version "6.5.5" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.5.tgz#cf97cdade71c6399a92c6d6c4177381291b781a1" - integrity sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg== +ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.0: + version "6.12.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" dependencies: - fast-deep-equal "^2.0.1" + fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^6.9.1: - version "6.10.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" - integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== +ajv@^6.12.3: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: - fast-deep-equal "^2.0.1" + fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.4.1" uri-js "^4.2.2" @@ -1029,13 +1095,18 @@ ajv@^6.9.1: alphanum-sort@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" - integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= -ansi-escapes@^3.2.0: +ansi-escapes@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== +ansi-escapes@^4.2.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" + dependencies: + type-fest "^0.11.0" + ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -1049,7 +1120,10 @@ ansi-regex@^3.0.0: ansi-regex@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" ansi-styles@^2.2.1: version "2.2.1" @@ -1059,202 +1133,213 @@ ansi-styles@^2.2.1: ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" +ansi-styles@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + +any-observable@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" + integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog== + anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== dependencies: micromatch "^3.1.4" normalize-path "^2.1.1" -aproba@^1.0.3, aproba@^1.1.1: +aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" +arch@^2.1.2: + version "2.2.0" + resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" + integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= -array-find-index@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= - -array-union@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= +array-includes@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348" dependencies: - array-uniq "^1.0.1" + define-properties "^1.1.3" + es-abstract "^1.17.0" + is-string "^1.0.5" -array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +array.prototype.flat@^1.2.1: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz#0de82b426b0318dbfdb940089e38b043d37f6c7b" + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== dependencies: bn.js "^4.0.0" inherits "^2.0.1" minimalistic-assert "^1.0.0" +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + assert@^1.1.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" - integrity sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE= + version "1.5.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" dependencies: + object-assign "^4.1.1" util "0.10.3" assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= astral-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== -async-each@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - integrity sha1-GdOGodntxufByF04iu28xW0zYC0= +async-each@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" async@^1.3.0: version "1.5.2" - resolved "http://registry.npmjs.org/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" async@^2.4.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" - integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== + version "2.6.3" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" dependencies: - lodash "^4.17.10" + lodash "^4.17.14" + +async@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720" + integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== -atob@^2.1.1: +atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -autoprefixer@^9.0.0: - version "9.3.1" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.3.1.tgz#71b622174de2b783d5fd99f9ad617b7a3c78443e" - integrity sha512-DY9gOh8z3tnCbJ13JIWaeQsoYncTGdsrgCceBaQSIL4nvdrLxgbRSBPevg2XbX7u4QCSfLheSJEEIUUSlkbx6Q== +autoprefixer@^9.6.1, autoprefixer@^9.7.6: + version "9.7.6" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.6.tgz#63ac5bbc0ce7934e6997207d5bb00d68fa8293a4" dependencies: - browserslist "^4.3.3" - caniuse-lite "^1.0.30000898" + browserslist "^4.11.1" + caniuse-lite "^1.0.30001039" + chalk "^2.4.2" normalize-range "^0.1.2" num2fraction "^1.2.2" - postcss "^7.0.5" - postcss-value-parser "^3.3.1" + postcss "^7.0.27" + postcss-value-parser "^4.0.3" -autoprefixer@^9.4.9: - version "9.4.10" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.4.10.tgz#e1be61fc728bacac8f4252ed242711ec0dcc6a7b" - integrity sha512-XR8XZ09tUrrSzgSlys4+hy5r2/z4Jp7Ag3pHm31U4g/CTccYPOVe19AkaJ4ey/vRd1sfj+5TtuD6I0PXtutjvQ== - dependencies: - browserslist "^4.4.2" - caniuse-lite "^1.0.30000940" - normalize-range "^0.1.2" - num2fraction "^1.2.2" - postcss "^7.0.14" - postcss-value-parser "^3.3.1" +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= -babel-code-frame@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" +aws4@^1.8.0: + version "1.10.1" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428" + integrity sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA== -babel-loader@^8.0.5: - version "8.0.5" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.5.tgz#225322d7509c2157655840bba52e46b6c2f2fe33" - integrity sha512-NTnHnVRd2JnRqPC0vW+iOQWU5pchDbYXsG2E6DMXEpMfUcQKclF9gmf3G3ZMhzG7IG9ji4coL0cm+FxeWxDpnw== +babel-loader@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3" dependencies: - find-cache-dir "^2.0.0" - loader-utils "^1.0.2" - mkdirp "^0.5.1" - util.promisify "^1.0.0" + find-cache-dir "^2.1.0" + loader-utils "^1.4.0" + mkdirp "^0.5.3" + pify "^4.0.1" + schema-utils "^2.6.5" babel-plugin-add-module-exports@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-1.0.0.tgz#72b5424d941a336c6a35357f373d8b8366263031" - integrity sha512-m0sMxPL4FaN2K69GQgaRJa4Ny15qKSdoknIcpN+gz+NaJlAW9pge/povs13tPYsKDboflrEQC+/3kfIsONBTaw== + version "1.0.2" + resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-1.0.2.tgz#96cd610d089af664f016467fc4567c099cce2d9c" optionalDependencies: chokidar "^2.0.4" babel-plugin-class-display-name@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/babel-plugin-class-display-name/-/babel-plugin-class-display-name-2.1.0.tgz#198ff12b9eabd33e011ee13f2f9898985608b4d1" - integrity sha1-GY/xK56r0z4BHuE/L5iYmFYItNE= + +babel-plugin-dynamic-import-node@^2.3.0: + version "2.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + dependencies: + object.assign "^4.1.0" bail@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.3.tgz#63cfb9ddbac829b02a3128cd53224be78e6c21a3" - integrity sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg== + version "1.0.5" + resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= base64-js@^1.0.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" - integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== + version "1.3.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== dependencies: cache-base "^1.0.1" class-utils "^0.3.5" @@ -1264,48 +1349,55 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" -big.js@^3.1.3: - version "3.2.0" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" - integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== binary-extensions@^1.0.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14" - integrity sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg== + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" -bluebird@^3.5.1: - version "3.5.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.2.tgz#1be0908e054a751754549c270489c1505d4ab15a" - integrity sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg== +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + dependencies: + file-uri-to-path "1.0.0" + +blob-util@2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb" + integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ== + +bluebird@^3.5.5, bluebird@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== + version "4.11.9" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" + integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== boolbase@^1.0.0, boolbase@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^2.3.0, braces@^2.3.1: +braces@^2.3.1, braces@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== dependencies: arr-flatten "^1.1.0" array-unique "^0.3.2" @@ -1318,6 +1410,12 @@ braces@^2.3.0, braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" +braces@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + dependencies: + fill-range "^7.0.1" + brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" @@ -1325,8 +1423,7 @@ brorand@^1.0.1: browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.2.0" - resolved "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" dependencies: buffer-xor "^1.0.3" cipher-base "^1.0.0" @@ -1338,7 +1435,6 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4: browserify-cipher@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== dependencies: browserify-aes "^1.0.4" browserify-des "^1.0.0" @@ -1347,7 +1443,6 @@ browserify-cipher@^1.0.0: browserify-des@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== dependencies: cipher-base "^1.0.1" des.js "^1.0.0" @@ -1356,8 +1451,7 @@ browserify-des@^1.0.0: browserify-rsa@^4.0.0: version "4.0.1" - resolved "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" dependencies: bn.js "^4.1.0" randombytes "^2.0.1" @@ -1365,7 +1459,6 @@ browserify-rsa@^4.0.0: browserify-sign@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" - integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= dependencies: bn.js "^4.1.1" browserify-rsa "^4.0.0" @@ -1378,81 +1471,93 @@ browserify-sign@^4.0.0: browserify-zlib@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== dependencies: pako "~1.0.5" -browserslist@^4.0.0, browserslist@^4.3.4, browserslist@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.4.2.tgz#6ea8a74d6464bb0bd549105f659b41197d8f0ba2" - integrity sha512-ISS/AIAiHERJ3d45Fz0AVYKkgcy+F/eJHzKEvv1j0wwKGKD9T3BrwKr/5g45L+Y4XIK5PlTqefHciRFcfE1Jxg== +browserslist@^4.0.0, browserslist@^4.11.1, browserslist@^4.6.4, browserslist@^4.8.5, browserslist@^4.9.1: + version "4.12.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.0.tgz#06c6d5715a1ede6c51fc39ff67fd647f740b656d" dependencies: - caniuse-lite "^1.0.30000939" - electron-to-chromium "^1.3.113" - node-releases "^1.1.8" + caniuse-lite "^1.0.30001043" + electron-to-chromium "^1.3.413" + node-releases "^1.1.53" + pkg-up "^2.0.0" -browserslist@^4.3.3: - version "4.3.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.3.4.tgz#4477b737db6a1b07077275b24791e680d4300425" - integrity sha512-u5iz+ijIMUlmV8blX82VGFrB9ecnUg5qEt55CMZ/YJEhha+d8qpBfOFuutJ6F/VKRXjZoD33b6uvarpPxcl3RA== - dependencies: - caniuse-lite "^1.0.30000899" - electron-to-chromium "^1.3.82" - node-releases "^1.0.1" +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= buffer@^4.3.0: - version "4.9.1" - resolved "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" - integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" isarray "^1.0.0" -builtin-modules@^1.0.0, builtin-modules@^1.1.1: +builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= -cacache@^11.0.2: - version "11.3.1" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.1.tgz#d09d25f6c4aca7a6d305d141ae332613aa1d515f" - integrity sha512-2PEw4cRRDu+iQvBTTuttQifacYjLPhET+SYO/gEFMy8uhi+jlJREDAjSF5FWSdV/Aw5h18caHA7vMTw2c+wDzA== +cacache@^12.0.2: + version "12.0.4" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" dependencies: - bluebird "^3.5.1" - chownr "^1.0.1" - figgy-pudding "^3.1.0" - glob "^7.1.2" - graceful-fs "^4.1.11" - lru-cache "^4.1.3" + 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.2" - ssri "^6.0.0" - unique-filename "^1.1.0" + rimraf "^2.6.3" + ssri "^6.0.1" + unique-filename "^1.1.1" y18n "^4.0.0" +cacache@^13.0.1: + version "13.0.1" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-13.0.1.tgz#a8000c21697089082f85287a1aec6e382024a71c" + dependencies: + chownr "^1.1.2" + figgy-pudding "^3.5.1" + fs-minipass "^2.0.0" + glob "^7.1.4" + graceful-fs "^4.2.2" + infer-owner "^1.0.4" + lru-cache "^5.1.1" + minipass "^3.0.0" + minipass-collect "^1.0.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.2" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + p-map "^3.0.0" + promise-inflight "^1.0.1" + rimraf "^2.7.1" + ssri "^7.0.0" + unique-filename "^1.1.1" + cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== dependencies: collection-visit "^1.0.0" component-emitter "^1.2.1" @@ -1464,63 +1569,76 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" -call-me-maybe@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" - integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= +cachedir@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8" + integrity sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw== -callsites@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.0.0.tgz#fb7eb569b72ad7a45812f93fd9430a3e410b3dd3" - integrity sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw== +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + dependencies: + callsites "^2.0.0" -camelcase-keys@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77" - integrity sha1-oqpfsa9oh1glnDLBQUJteJI7m3c= +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" dependencies: - camelcase "^4.1.0" - map-obj "^2.0.0" - quick-lru "^1.0.0" + caller-callsite "^2.0.0" -camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" -camelcase@^5.0.0, camelcase@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.2.0.tgz#e7522abda5ed94cc0489e1b8466610e88404cf45" - integrity sha512-IXFsBS2pC+X0j0N/GE7Dm7j3bsEBp+oTpb7F50dwEVX7rf3IgwO9XatnegTsDtniKCUtEJH4fSU6Asw7uoVLfQ== +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + +camelcase-keys@^6.1.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" + dependencies: + camelcase "^5.3.1" + map-obj "^4.0.0" + quick-lru "^4.0.1" + +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" caniuse-api@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" - integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== dependencies: browserslist "^4.0.0" caniuse-lite "^1.0.0" lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000898, caniuse-lite@^1.0.30000899: - version "1.0.30000906" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000906.tgz#7c44e498a2504f7a5db3b4f91285bbc821157a77" - integrity sha512-ME7JFX6h0402om/nC/8Lw+q23QvPe2ust9U0ntLmkX9F2zaGwq47fZkjlyHKirFBuq1EM+T/LXBcDdW4bvkCTA== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001039, caniuse-lite@^1.0.30001043: + version "1.0.30001048" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001048.tgz#4bb4f1bc2eb304e5e1154da80b93dee3f1cf447e" -caniuse-lite@^1.0.30000939, caniuse-lite@^1.0.30000940: - version "1.0.30000947" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000947.tgz#c30305e9701449c22e97f4e9837cea3d76aa3273" - integrity sha512-ubgBUfufe5Oi3W1+EHyh2C3lfBIEcZ6bTuvl5wNOpIuRB978GF/Z+pQ7pGGUpeYRB0P+8C7i/3lt6xkeu2hwnA== +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= ccount@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.3.tgz#f1cec43f332e2ea5a569fd46f9f5bde4e6102aff" - integrity sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw== + version "1.0.5" + resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.5.tgz#ac82a944905a65ce204eb03023157edf29425c17" -chalk@^1.1.3: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^1.0.0, chalk@^1.1.3: version "1.1.3" - resolved "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= dependencies: ansi-styles "^2.2.1" @@ -1529,53 +1647,56 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" - integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.0.0.tgz#6e98081ed2d17faab615eb52ac66ec1fe6209e72" dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" + ansi-styles "^4.1.0" + supports-color "^7.1.0" -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== +chalk@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" + ansi-styles "^4.1.0" + supports-color "^7.1.0" character-entities-html4@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.2.tgz#c44fdde3ce66b52e8d321d6c1bf46101f0150610" - integrity sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw== + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.4.tgz#0e64b0a3753ddbf1fdc044c5fd01d0199a02e125" character-entities-legacy@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz#7c6defb81648498222c9855309953d05f4d63a9c" - integrity sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA== + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" character-entities@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.2.tgz#58c8f371c0774ef0ba9b2aca5f00d8f100e6e363" - integrity sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ== + version "1.2.4" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" character-reference-invalid@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz#21e421ad3d84055952dab4a43a04e73cd425d3ed" - integrity sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ== + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + +check-more-types@^2.24.0: + version "2.24.0" + resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" + integrity sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA= cheerio@^0.19.0: version "0.19.0" - resolved "http://registry.npmjs.org/cheerio/-/cheerio-0.19.0.tgz#772e7015f2ee29965096d71ea4175b75ab354925" - integrity sha1-dy5wFfLuKZZQltcepBdbdas1SSU= + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.19.0.tgz#772e7015f2ee29965096d71ea4175b75ab354925" dependencies: css-select "~1.0.0" dom-serializer "~0.1.0" @@ -1583,42 +1704,42 @@ cheerio@^0.19.0: htmlparser2 "~3.8.1" lodash "^3.2.0" -chokidar@^2.0.2, chokidar@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" - integrity sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ== +chokidar@^2.0.4, chokidar@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" dependencies: anymatch "^2.0.0" - async-each "^1.0.0" - braces "^2.3.0" + async-each "^1.0.1" + braces "^2.3.2" glob-parent "^3.1.0" - inherits "^2.0.1" + inherits "^2.0.3" is-binary-path "^1.0.0" is-glob "^4.0.0" - lodash.debounce "^4.0.8" - normalize-path "^2.1.1" + normalize-path "^3.0.0" path-is-absolute "^1.0.0" - readdirp "^2.0.0" - upath "^1.0.5" + readdirp "^2.2.1" + upath "^1.1.1" optionalDependencies: - fsevents "^1.2.2" + fsevents "^1.2.7" -chownr@^1.0.1, chownr@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" - integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== +chownr@^1.1.1, chownr@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" -chrome-trace-event@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz#45a91bd2c20c9411f0963b5aaeb9a1b95e09cc48" - integrity sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A== +chrome-trace-event@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" dependencies: tslib "^1.9.0" +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -1626,51 +1747,79 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== dependencies: arr-union "^3.1.0" define-property "^0.2.5" isobject "^3.0.0" static-extend "^0.1.1" -cli-cursor@^2.1.0: +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + +cli-cursor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" + integrity sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc= + dependencies: + restore-cursor "^1.0.1" + +cli-cursor@^2.0.0, cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= dependencies: restore-cursor "^2.0.0" +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + dependencies: + restore-cursor "^3.1.0" + +cli-table3@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.0.tgz#b7b1bc65ca8e7b5cef9124e13dc2b21e2ce4faee" + integrity sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ== + dependencies: + object-assign "^4.1.0" + string-width "^4.2.0" + optionalDependencies: + colors "^1.1.2" + +cli-truncate@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" + integrity sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ= + dependencies: + slice-ansi "0.0.4" + string-width "^1.0.1" + cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" -cliui@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" - integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" dependencies: - string-width "^2.1.1" - strip-ansi "^4.0.0" - wrap-ansi "^2.0.0" + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" -clone-regexp@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-1.0.1.tgz#051805cd33173375d82118fc0918606da39fd60f" - integrity sha512-Fcij9IwRW27XedRIJnSOEupS7RVcXtObJXbcUOX93UCLqqOdRpkvzKywOOSizmEK/Is3S/RHX9dLdfo6R1Q1mw== +clone-regexp@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-2.2.0.tgz#7d65e00885cd8796405c35a737e7a86b7429e36f" dependencies: - is-regexp "^1.0.0" - is-supported-regexp-flag "^1.0.0" + is-regexp "^2.0.0" co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= coa@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" - integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== dependencies: "@types/q" "^1.5.1" chalk "^2.4.1" @@ -1681,20 +1830,22 @@ code-point-at@^1.0.0: resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= -codex-notifier@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/codex-notifier/-/codex-notifier-1.1.1.tgz#0fad9876781b793da316bed7f0cd11454a3f3393" - integrity sha512-IAcSO8O9i+limw4XknDXvBTOI3bXwGy3xNauBCYx4F1+hfNMhhkL3lzDnmAEcvwgiuY4P7W5hWB05sNi9W+31Q== +codex-notifier@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/codex-notifier/-/codex-notifier-1.1.2.tgz#a733079185f4c927fa296f1d71eb8753fe080895" + +codex-tooltip@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/codex-tooltip/-/codex-tooltip-1.0.1.tgz#f6e4f39d81507f9c455b667f1287746d14ee8056" + integrity sha512-1xLb1NZbxguNtf02xBRhDphq/EXvMMeEbY0ievjQTHqf8UjXsD41evGk9rqcbjpl+JOjNgtwnp1OaU/X/h6fhQ== collapse-white-space@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.4.tgz#ce05cf49e54c3277ae573036a26851ba430a0091" - integrity sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw== + version "1.0.6" + resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287" collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= dependencies: map-visit "^1.0.0" object-visit "^1.0.0" @@ -1702,65 +1853,82 @@ collection-visit@^1.0.0: color-convert@^1.9.0, color-convert@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + dependencies: + color-name "~1.1.4" + color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -color-name@^1.0.0: +color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== color-string@^1.5.2: version "1.5.3" resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" - integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" color@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/color/-/color-3.1.0.tgz#d8e9fb096732875774c84bf922815df0308d0ffc" - integrity sha512-CwyopLkuRYO5ei2EpzpIh6LqJMt6Mt+jZhO5VI5f/wJLZriXQE32/SSqzmrh+QB+AZT81Cj8yv+7zwToW8ahZg== + version "3.1.2" + resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" dependencies: color-convert "^1.9.1" color-string "^1.5.2" -commander@^2.12.1, commander@^2.19.0, commander@^2.8.1: - version "2.19.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" - integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== +colors@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +commander@^2.12.1, commander@^2.20.0, commander@^2.8.1: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + +commander@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + +comment-parser@^0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-0.7.2.tgz#baf6d99b42038678b81096f15b630d18142f4b8a" -commander@~2.17.1: - version "2.17.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" - integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== +common-tags@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" + integrity sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw== commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= component-emitter@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@^1.5.0: +concat-stream@^1.5.0, concat-stream@^1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== dependencies: buffer-from "^1.0.0" inherits "^2.0.3" @@ -1768,33 +1936,26 @@ concat-stream@^1.5.0: typedarray "^0.0.6" console-browserify@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= - dependencies: - date-now "^0.1.4" - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= -convert-source-map@^1.1.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== +contains-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + +convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" dependencies: safe-buffer "~5.1.1" copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" - integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== dependencies: aproba "^1.1.1" fs-write-stream-atomic "^1.0.8" @@ -1806,49 +1967,55 @@ copy-concurrently@^1.0.0: copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -core-js@^2.5.7: - version "2.5.7" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" - integrity sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw== +core-js-compat@^3.6.2: + version "3.6.5" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c" + dependencies: + browserslist "^4.8.5" + semver "7.0.0" + +core-js@3.6.5: + version "3.6.5" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" + +core-js@^2.6.5: + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" -core-util-is@~1.0.0: +core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cosmiconfig@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" - integrity sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ== +cosmiconfig@^5.0.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" dependencies: + import-fresh "^2.0.0" is-directory "^0.3.1" - js-yaml "^3.9.0" + js-yaml "^3.13.1" parse-json "^4.0.0" - require-from-string "^2.0.1" -cosmiconfig@^5.0.0: - version "5.0.6" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.6.tgz#dca6cf680a0bd03589aff684700858c81abeeb39" - integrity sha512-6DWfizHriCrFWURP1/qyhsiFvYdlJzbCzmtFWh744+KyWsJo5+kPzUZZaMRSSItoYc0pxFX7gEO7ZC1/gN/7AQ== +cosmiconfig@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" dependencies: - is-directory "^0.3.1" - js-yaml "^3.9.0" - parse-json "^4.0.0" + "@types/parse-json" "^4.0.0" + import-fresh "^3.1.0" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.7.2" create-ecdh@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" - integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== dependencies: bn.js "^4.1.0" elliptic "^6.0.0" create-hash@^1.1.0, create-hash@^1.1.2: version "1.2.0" - resolved "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" dependencies: cipher-base "^1.0.1" inherits "^2.0.1" @@ -1858,8 +2025,7 @@ create-hash@^1.1.0, create-hash@^1.1.2: create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: version "1.1.7" - resolved "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" dependencies: cipher-base "^1.0.3" create-hash "^1.1.0" @@ -1868,10 +2034,9 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" -cross-spawn@^6.0.0, cross-spawn@^6.0.5: +cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== dependencies: nice-try "^1.0.4" path-key "^2.0.1" @@ -1879,10 +2044,18 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" +cross-spawn@^7.0.0: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== dependencies: browserify-cipher "^1.0.0" browserify-sign "^4.0.0" @@ -1899,19 +2072,16 @@ crypto-browserify@^3.11.0: css-blank-pseudo@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5" - integrity sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w== dependencies: postcss "^7.0.5" css-color-names@0.0.4, css-color-names@^0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" - integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= css-declaration-sorter@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" - integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== dependencies: postcss "^7.0.1" timsort "^0.3.0" @@ -1919,115 +2089,93 @@ css-declaration-sorter@^4.0.1: css-has-pseudo@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz#3c642ab34ca242c59c41a125df9105841f6966ee" - integrity sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ== dependencies: postcss "^7.0.6" postcss-selector-parser "^5.0.0-rc.4" -css-loader@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-2.1.1.tgz#d8254f72e412bb2238bb44dd674ffbef497333ea" - integrity sha512-OcKJU/lt232vl1P9EEDamhoO9iKY3tIjY5GU+XDLblAykTdgs6Ux9P1hTHve8nFKy5KPpOXOsVI/hIwi3841+w== +css-loader@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.5.3.tgz#95ac16468e1adcd95c844729e0bb167639eb0bcf" dependencies: - camelcase "^5.2.0" - icss-utils "^4.1.0" + camelcase "^5.3.1" + cssesc "^3.0.0" + icss-utils "^4.1.1" loader-utils "^1.2.3" normalize-path "^3.0.0" - postcss "^7.0.14" + postcss "^7.0.27" postcss-modules-extract-imports "^2.0.0" - postcss-modules-local-by-default "^2.0.6" - postcss-modules-scope "^2.1.0" - postcss-modules-values "^2.0.0" - postcss-value-parser "^3.3.0" - schema-utils "^1.0.0" + postcss-modules-local-by-default "^3.0.2" + postcss-modules-scope "^2.2.0" + postcss-modules-values "^3.0.0" + postcss-value-parser "^4.0.3" + schema-utils "^2.6.6" + semver "^6.3.0" css-prefers-color-scheme@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz#6f830a2714199d4f0d0d0bb8a27916ed65cff1f4" - integrity sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg== dependencies: postcss "^7.0.5" css-select-base-adapter@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" - integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== css-select@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.0.2.tgz#ab4386cec9e1f668855564b17c3733b43b2a5ede" - integrity sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" dependencies: boolbase "^1.0.0" - css-what "^2.1.2" + css-what "^3.2.1" domutils "^1.7.0" nth-check "^1.0.2" css-select@~1.0.0: version "1.0.0" - resolved "http://registry.npmjs.org/css-select/-/css-select-1.0.0.tgz#b1121ca51848dd264e2244d058cee254deeb44b0" - integrity sha1-sRIcpRhI3SZOIkTQWM7iVN7rRLA= + resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.0.0.tgz#b1121ca51848dd264e2244d058cee254deeb44b0" dependencies: boolbase "~1.0.0" css-what "1.0" domutils "1.4" nth-check "~1.0.0" -css-tree@1.0.0-alpha.28: - version "1.0.0-alpha.28" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.28.tgz#8e8968190d886c9477bc8d61e96f61af3f7ffa7f" - integrity sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w== +css-tree@1.0.0-alpha.37: + version "1.0.0-alpha.37" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" dependencies: - mdn-data "~1.1.0" - source-map "^0.5.3" + mdn-data "2.0.4" + source-map "^0.6.1" -css-tree@1.0.0-alpha.29: - version "1.0.0-alpha.29" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" - integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg== +css-tree@1.0.0-alpha.39: + version "1.0.0-alpha.39" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.39.tgz#2bff3ffe1bb3f776cf7eefd91ee5cba77a149eeb" dependencies: - mdn-data "~1.1.0" - source-map "^0.5.3" - -css-unit-converter@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" - integrity sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY= - -css-url-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/css-url-regex/-/css-url-regex-1.1.0.tgz#83834230cc9f74c457de59eebd1543feeb83b7ec" - integrity sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w= + mdn-data "2.0.6" + source-map "^0.6.1" css-what@1.0: version "1.0.0" - resolved "http://registry.npmjs.org/css-what/-/css-what-1.0.0.tgz#d7cc2df45180666f99d2b14462639469e00f736c" - integrity sha1-18wt9FGAZm+Z0rFEYmOUaeAPc2w= + resolved "https://registry.yarnpkg.com/css-what/-/css-what-1.0.0.tgz#d7cc2df45180666f99d2b14462639469e00f736c" -css-what@^2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" - integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== +css-what@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" -cssdb@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.3.0.tgz#2e1229900616f80c66ff2d568ea2b4f92db1c78c" - integrity sha512-VHPES/+c9s+I0ryNj+PXvp84nz+ms843z/efpaEINwP/QfGsINL3gpLp5qjapzDNzNzbXxur8uxKxSXImrg4ag== +cssdb@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0" cssesc@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" - integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== cssnano-preset-default@^4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76" - integrity sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA== dependencies: css-declaration-sorter "^4.0.1" cssnano-util-raw-cache "^4.0.1" @@ -2063,63 +2211,99 @@ cssnano-preset-default@^4.0.7: cssnano-util-get-arguments@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" - integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= cssnano-util-get-match@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" - integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= cssnano-util-raw-cache@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" - integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== dependencies: postcss "^7.0.0" cssnano-util-same-parent@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" - integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== cssnano@^4.1.10: version "4.1.10" resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2" - integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ== dependencies: cosmiconfig "^5.0.0" cssnano-preset-default "^4.0.7" is-resolvable "^1.0.0" postcss "^7.0.0" -csso@^3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" - integrity sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg== +csso@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.3.tgz#0d9985dc852c7cc2b2cacfbbe1079014d1a8e903" dependencies: - css-tree "1.0.0-alpha.29" + css-tree "1.0.0-alpha.39" -currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= - dependencies: - array-find-index "^1.0.1" +cyclist@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" -cyclist@~0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" - integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA= +cypress@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-5.5.0.tgz#1da0355794a43247f8a80cb7f505e83e1cf847cb" + integrity sha512-UHEiTca8AUTevbT2pWkHQlxoHtXmbq+h6Eiu/Mz8DqpNkF98zjTBLv/HFiKJUU5rQzp9EwSWtms33p5TWCJ8tQ== + dependencies: + "@cypress/listr-verbose-renderer" "^0.4.1" + "@cypress/request" "^2.88.5" + "@cypress/xvfb" "^1.2.4" + "@types/sinonjs__fake-timers" "^6.0.1" + "@types/sizzle" "^2.3.2" + arch "^2.1.2" + blob-util "2.0.2" + bluebird "^3.7.2" + cachedir "^2.3.0" + chalk "^4.1.0" + check-more-types "^2.24.0" + cli-table3 "~0.6.0" + commander "^4.1.1" + common-tags "^1.8.0" + debug "^4.1.1" + eventemitter2 "^6.4.2" + execa "^4.0.2" + executable "^4.1.1" + extract-zip "^1.7.0" + fs-extra "^9.0.1" + getos "^3.2.1" + is-ci "^2.0.0" + is-installed-globally "^0.3.2" + lazy-ass "^1.6.0" + listr "^0.14.3" + lodash "^4.17.19" + log-symbols "^4.0.0" + minimist "^1.2.5" + moment "^2.27.0" + ospath "^1.2.2" + pretty-bytes "^5.4.1" + ramda "~0.26.1" + request-progress "^3.0.0" + supports-color "^7.2.0" + tmp "~0.2.1" + untildify "^4.0.0" + url "^0.11.0" + yauzl "^2.10.0" -date-now@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" -debug@^2.1.2, debug@^2.2.0, debug@^2.3.3: +date-fns@^1.27.2: + version "1.30.1" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" + integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== + +debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" @@ -2130,24 +2314,15 @@ debug@^3.1.0: dependencies: ms "^2.1.1" -debug@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.0.tgz#373687bffa678b38b1cd91f861b63850035ddc87" - integrity sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg== - dependencies: - ms "^2.1.1" - -debug@^4.0.1, debug@^4.1.0: +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== dependencies: ms "^2.1.1" -decamelize-keys@^1.0.0: +decamelize-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" - integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= dependencies: decamelize "^1.1.0" map-obj "^1.0.0" @@ -2155,61 +2330,48 @@ decamelize-keys@^1.0.0: decamelize@^1.1.0, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== dependencies: object-keys "^1.0.12" define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== dependencies: is-descriptor "^1.0.2" isobject "^3.0.1" -delegates@^1.0.0: +delayed-stream@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= des.js@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" - integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" @@ -2217,94 +2379,85 @@ des.js@^1.0.0: detect-file@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" - integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= - -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= -diff@^3.2.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" diffie-hellman@^5.0.0: version "5.0.3" - resolved "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" dependencies: bn.js "^4.1.0" miller-rabin "^4.0.0" randombytes "^2.0.0" -dir-glob@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" - integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw== +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" dependencies: - path-type "^3.0.0" + path-type "^4.0.0" + +doctrine@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== dependencies: esutils "^2.0.2" -dom-serializer@0, dom-serializer@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" - integrity sha1-BzxpdUbOB4DOI75KKOKT5AvDDII= +dom-serializer@0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" dependencies: - domelementtype "~1.1.1" - entities "~1.1.1" + domelementtype "^2.0.1" + entities "^2.0.0" + +dom-serializer@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" + dependencies: + domelementtype "^1.3.0" + entities "^1.1.1" domain-browser@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== -domelementtype@1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.2.1.tgz#578558ef23befac043a1abb0db07635509393479" - integrity sha512-SQVCLFS2E7G5CRCMdn6K9bIhRj1bS6QBWZfF0TUPh4V/BbqrQ619IdSS3/izn0FZ+9l+uODzaZjb08fjOfablA== - -domelementtype@^1.3.1: +domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== -domelementtype@~1.1.1: - version "1.1.3" - resolved "http://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" - integrity sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs= +domelementtype@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" domhandler@2.3: version "2.3.0" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738" - integrity sha1-LeWaCCLVAn+r/28DLCsloqir5zg= dependencies: domelementtype "1" domhandler@^2.3.0: version "2.4.2" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== dependencies: domelementtype "1" domutils@1.4: version "1.4.3" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.4.3.tgz#0865513796c6b306031850e175516baf80b72a6f" - integrity sha1-CGVRN5bGswYDGFDhdVFrr4C3Km8= dependencies: domelementtype "1" domutils@1.5: version "1.5.1" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" - integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= dependencies: dom-serializer "0" domelementtype "1" @@ -2312,42 +2465,46 @@ domutils@1.5: domutils@^1.5.1, domutils@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== dependencies: dom-serializer "0" domelementtype "1" -dot-prop@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" - integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== +dot-prop@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" dependencies: - is-obj "^1.0.0" + is-obj "^2.0.0" duplexify@^3.4.2, duplexify@^3.6.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.6.1.tgz#b1a7a29c4abfd639585efaecce80d666b1e34125" - integrity sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA== + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" dependencies: end-of-stream "^1.0.0" inherits "^2.0.1" readable-stream "^2.0.0" stream-shift "^1.0.0" -electron-to-chromium@^1.3.113: - version "1.3.116" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.116.tgz#1dbfee6a592a0c14ade77dbdfe54fef86387d702" - integrity sha512-NKwKAXzur5vFCZYBHpdWjTMO8QptNLNP80nItkSIgUOapPAo9Uia+RvkCaZJtO7fhQaVElSvBPWEc2ku6cKsPA== +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +electron-to-chromium@^1.3.413: + version "1.3.418" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.418.tgz#840021191f466b803a873e154113620c9f53cec6" -electron-to-chromium@^1.3.82: - version "1.3.83" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.83.tgz#74584eb0972bb6777811c5d68d988c722f5e6666" - integrity sha512-DqJoDarxq50dcHsOOlMLNoy+qQitlMNbYb6wwbE0oUw2veHdRkpNrhmngiUYKMErdJ8SJ48rpJsZTQgy5SoEAA== +elegant-spinner@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" + integrity sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4= elliptic@^6.0.0: - version "6.4.1" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" - integrity sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ== + version "6.5.3" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" + integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2360,80 +2517,84 @@ elliptic@^6.0.0: emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= + +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" end-of-stream@^1.0.0, end-of-stream@^1.1.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" dependencies: once "^1.4.0" -enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: +enhanced-resolve@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" - integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== dependencies: graceful-fs "^4.1.2" memory-fs "^0.4.0" tapable "^1.0.0" +enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz#2937e2b8066cd0fe7ce0990a98f0d71a35189f66" + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.5.0" + tapable "^1.0.0" + entities@1.0: version "1.0.0" - resolved "http://registry.npmjs.org/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" - integrity sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY= + resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" entities@^1.1.1, entities@~1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== + +entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" errno@^0.1.3, errno@~0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== dependencies: prr "~1.0.1" -error-ex@^1.3.1: +error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" -es-abstract@^1.12.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" - integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== +es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.5: + version "1.17.5" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9" dependencies: - es-to-primitive "^1.2.0" + es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-keys "^1.0.12" - -es-abstract@^1.5.1: - version "1.12.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" - integrity sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA== - dependencies: - 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@^1.1.1, es-to-primitive@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== + has-symbols "^1.0.1" + is-callable "^1.1.5" + is-regex "^1.0.5" + object-inspect "^1.7.0" + object-keys "^1.1.1" + object.assign "^4.1.0" + string.prototype.trimleft "^2.1.1" + string.prototype.trimright "^2.1.1" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" dependencies: is-callable "^1.1.4" is-date-object "^1.0.1" @@ -2441,168 +2602,288 @@ es-to-primitive@^1.1.1, es-to-primitive@^1.2.0: es6-promise@^2.3.0: version "2.3.0" - resolved "http://registry.npmjs.org/es6-promise/-/es6-promise-2.3.0.tgz#96edb9f2fdb01995822b263dd8aadab6748181bc" - integrity sha1-lu258v2wGZWCKyY92KratnSBgbw= + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-2.3.0.tgz#96edb9f2fdb01995822b263dd8aadab6748181bc" escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -eslint-loader@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/eslint-loader/-/eslint-loader-2.1.2.tgz#453542a1230d6ffac90e4e7cb9cadba9d851be68" - integrity sha512-rA9XiXEOilLYPOIInvVH5S/hYfyTPyxag6DZhoQOduM+3TkghAEQ3VcFO8VnX4J4qg/UIBzp72aOf/xvYmpmsg== +eslint-config-codex@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/eslint-config-codex/-/eslint-config-codex-1.3.3.tgz#639ec0f6500c3f5bd10465f06f8fc0645a1ae064" dependencies: - loader-fs-cache "^1.0.0" - loader-utils "^1.0.2" - object-assign "^4.0.1" - object-hash "^1.1.4" - rimraf "^2.6.1" + "@typescript-eslint/eslint-plugin" "^2.12.0" + "@typescript-eslint/parser" "^2.12.0" + eslint-config-standard "14.1.0" + eslint-plugin-import "2.19.1" + eslint-plugin-jsdoc "^22.1.0" + eslint-plugin-node "10.0.0" + eslint-plugin-promise "4.2.1" + eslint-plugin-standard "4.0.1" + typescript "^3.7.3" -eslint-scope@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" - integrity sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA== +eslint-config-standard@14.1.0: + version "14.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-14.1.0.tgz#b23da2b76fe5a2eba668374f246454e7058f15d4" + +eslint-import-resolver-node@^0.3.2: + version "0.3.3" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz#dbaa52b6b2816b50bc6711af75422de808e98404" + dependencies: + debug "^2.6.9" + resolve "^1.13.1" + +eslint-loader@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/eslint-loader/-/eslint-loader-4.0.2.tgz#386a1e21bcb613b3cf2d252a3b708023ccfb41ec" + dependencies: + find-cache-dir "^3.3.1" + fs-extra "^8.1.0" + loader-utils "^2.0.0" + object-hash "^2.0.3" + schema-utils "^2.6.5" + +eslint-module-utils@^2.4.1: + version "2.6.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz#579ebd094f56af7797d19c9866c9c9486629bfa6" + dependencies: + debug "^2.6.9" + pkg-dir "^2.0.0" + +eslint-plugin-cypress@^2.11.2: + version "2.11.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-cypress/-/eslint-plugin-cypress-2.11.2.tgz#a8f3fe7ec840f55e4cea37671f93293e6c3e76a0" + integrity sha512-1SergF1sGbVhsf7MYfOLiBhdOg6wqyeV9pXUAIDIffYTGMN3dTBQS9nFAzhLsHhO+Bn0GaVM1Ecm71XUidQ7VA== + dependencies: + globals "^11.12.0" + +eslint-plugin-es@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-2.0.0.tgz#0f5f5da5f18aa21989feebe8a73eadefb3432976" + dependencies: + eslint-utils "^1.4.2" + regexpp "^3.0.0" + +eslint-plugin-import@2.19.1: + version "2.19.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.19.1.tgz#5654e10b7839d064dd0d46cd1b88ec2133a11448" + dependencies: + array-includes "^3.0.3" + array.prototype.flat "^1.2.1" + contains-path "^0.1.0" + debug "^2.6.9" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.2" + eslint-module-utils "^2.4.1" + has "^1.0.3" + minimatch "^3.0.4" + object.values "^1.1.0" + read-pkg-up "^2.0.0" + resolve "^1.12.0" + +eslint-plugin-jsdoc@^22.1.0: + version "22.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-22.2.0.tgz#b89159e01ed8eeee4f6512101e96cac6a2999461" + dependencies: + comment-parser "^0.7.2" + debug "^4.1.1" + jsdoctypeparser "^6.1.0" + lodash "^4.17.15" + regextras "^0.7.0" + semver "^6.3.0" + spdx-expression-parse "^3.0.0" + +eslint-plugin-node@10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-10.0.0.tgz#fd1adbc7a300cf7eb6ac55cf4b0b6fc6e577f5a6" + dependencies: + eslint-plugin-es "^2.0.0" + eslint-utils "^1.4.2" + ignore "^5.1.1" + minimatch "^3.0.4" + resolve "^1.10.1" + semver "^6.1.0" + +eslint-plugin-promise@4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a" + +eslint-plugin-standard@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz#ff0519f7ffaff114f76d1bd7c3996eef0f6e20b4" + +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-scope@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.2.tgz#5f10cd6cabb1965bf479fa65745673439e21cb0e" - integrity sha512-5q1+B/ogmHl8+paxtOKx38Z8LtWkVGuNt3+GQNErqwLl6ViNp/gdJGMCjZNxZ8j/VYjDNZ2Fo+eQc1TAVPIzbg== +eslint-scope@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-utils@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512" - integrity sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q== +eslint-utils@^1.4.2, eslint-utils@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" + dependencies: + eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" - integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== +eslint-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd" + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-visitor-keys@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" -eslint@^5.15.1: - version "5.15.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.15.1.tgz#8266b089fd5391e0009a047050795b1d73664524" - integrity sha512-NTcm6vQ+PTgN3UBsALw5BMhgO6i5EpIjQF/Xb5tIh3sk9QhrFafujUOczGz4J24JBlzWclSB9Vmx8d+9Z6bFCg== +eslint@^6.8.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" dependencies: "@babel/code-frame" "^7.0.0" - ajv "^6.9.1" + ajv "^6.10.0" chalk "^2.1.0" cross-spawn "^6.0.5" debug "^4.0.1" doctrine "^3.0.0" - eslint-scope "^4.0.2" - eslint-utils "^1.3.1" - eslint-visitor-keys "^1.0.0" - espree "^5.0.1" + eslint-scope "^5.0.0" + eslint-utils "^1.4.3" + eslint-visitor-keys "^1.1.0" + espree "^6.1.2" esquery "^1.0.1" esutils "^2.0.2" file-entry-cache "^5.0.1" functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^11.7.0" + glob-parent "^5.0.0" + globals "^12.1.0" ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^6.2.2" - js-yaml "^3.12.0" + inquirer "^7.0.0" + is-glob "^4.0.0" + js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" - lodash "^4.17.11" + lodash "^4.17.14" minimatch "^3.0.4" mkdirp "^0.5.1" natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.2" + optionator "^0.8.3" progress "^2.0.0" regexpp "^2.0.1" - semver "^5.5.1" - strip-ansi "^4.0.0" - strip-json-comments "^2.0.1" + semver "^6.1.2" + strip-ansi "^5.2.0" + strip-json-comments "^3.0.1" table "^5.2.3" text-table "^0.2.0" + v8-compile-cache "^2.0.3" -espree@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" - integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== +espree@^6.1.2: + version "6.2.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a" dependencies: - acorn "^6.0.7" - acorn-jsx "^5.0.0" - eslint-visitor-keys "^1.0.0" + acorn "^7.1.1" + acorn-jsx "^5.2.0" + eslint-visitor-keys "^1.1.0" esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" - integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== + version "1.3.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" dependencies: - estraverse "^4.0.0" + estraverse "^5.1.0" esrecurse@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== dependencies: estraverse "^4.1.0" -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= +estraverse@^4.1.0, estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + +estraverse@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.1.0.tgz#374309d39fd935ae500e7b92e8a6b4c720e59642" esutils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" -events@^1.0.0: - version "1.1.1" - resolved "http://registry.npmjs.org/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= +eventemitter2@^6.4.2: + version "6.4.3" + resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.3.tgz#35c563619b13f3681e7eb05cbdaf50f56ba58820" + integrity sha512-t0A2msp6BzOf+QAcI6z9XMktLj52OjGQg+8SJH6v5+3uxNpWYRR3wQmfA+6xtMU9kOC59qk9licus5dYcrYkMQ== + +events@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.1.0.tgz#84279af1b34cb75aa88bf5ff291f6d0bd9b31a59" evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== dependencies: md5.js "^1.3.4" safe-buffer "^5.1.1" -execa@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" - integrity sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw== +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" dependencies: cross-spawn "^6.0.0" - get-stream "^3.0.0" + get-stream "^4.0.0" is-stream "^1.1.0" npm-run-path "^2.0.0" p-finally "^1.0.0" signal-exit "^3.0.0" strip-eof "^1.0.0" -execall@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execall/-/execall-1.0.0.tgz#73d0904e395b3cab0658b08d09ec25307f29bb73" - integrity sha1-c9CQTjlbPKsGWLCNCewlMH8pu3M= +execa@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.3.tgz#0a34dabbad6d66100bd6f2c576c8669403f317f2" + integrity sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + +execall@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/execall/-/execall-2.0.0.tgz#16a06b5fe5099df7d00be5d9c06eecded1663b45" + dependencies: + clone-regexp "^2.1.0" + +executable@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" + integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg== dependencies: - clone-regexp "^1.0.0" + pify "^2.2.0" + +exit-hook@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" + integrity sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g= expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= dependencies: debug "^2.3.3" define-property "^0.2.5" @@ -2615,34 +2896,29 @@ expand-brackets@^2.1.4: expand-tilde@^2.0.0, expand-tilde@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" - integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= dependencies: homedir-polyfill "^1.0.1" extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= dependencies: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@^3.0.0: +extend@^3.0.0, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== external-editor@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" - integrity sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" dependencies: chardet "^0.7.0" iconv-lite "^0.4.24" @@ -2651,7 +2927,6 @@ external-editor@^3.0.3: extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== dependencies: array-unique "^0.3.2" define-property "^1.0.0" @@ -2665,49 +2940,83 @@ extglob@^2.0.4: extract-text-webpack-plugin@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz#5f043eaa02f9750a9258b78c0a6e0dc1408fb2f7" - integrity sha512-bt/LZ4m5Rqt/Crl2HiKuAl/oqg0psx1tsTLkvWbJen1CtD+fftkZhMaQ9HOtY2gWsl2Wq+sABmMVi9z3DhKWQQ== dependencies: async "^2.4.1" loader-utils "^1.1.0" schema-utils "^0.3.0" webpack-sources "^1.0.1" +extract-zip@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" + integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA== + dependencies: + concat-stream "^1.6.2" + debug "^2.6.9" + mkdirp "^0.5.4" + yauzl "^2.10.0" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + fast-deep-equal@^1.0.0: version "1.1.0" - resolved "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" -fast-deep-equal@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= +fast-deep-equal@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" -fast-glob@^2.2.6: - version "2.2.6" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.6.tgz#a5d5b697ec8deda468d85a74035290a025a95295" - integrity sha512-0BvMaZc1k9F+MeWWMe8pL6YltFzZYcJsYU7D4JyDA6PAczaXvxqQQ/z+mDF7/4Mw01DeUc+i3CTKajnkANkV4w== +fast-glob@^3.1.1: + version "3.2.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d" dependencies: - "@mrmlnc/readdir-enhanced" "^2.2.1" - "@nodelib/fs.stat" "^1.1.2" - glob-parent "^3.1.0" - is-glob "^4.0.0" - merge2 "^1.2.3" - micromatch "^3.1.10" + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" -fast-levenshtein@~2.0.4: +fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= -figgy-pudding@^3.1.0, figgy-pudding@^3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" - integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== +fastq@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.7.0.tgz#fcd79a08c5bd7ec5b55cd3f5c4720db551929801" + dependencies: + reusify "^1.0.4" + +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= + dependencies: + pend "~1.2.0" + +figgy-pudding@^3.5.1: + version "3.5.2" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" + +figures@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= + dependencies: + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" figures@^2.0.0: version "2.0.0" @@ -2716,147 +3025,162 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -file-entry-cache@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-4.0.0.tgz#633567d15364aefe0b299e1e217735e8f3a9f6e8" - integrity sha512-AVSwsnbV8vH/UVbvgEhf3saVQXORNv0ZzSkvkhQIaia5Tia+JhGTaa/ePUSVoPHQyGayQNmYfkzFi3WZV5zcpA== +figures@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" dependencies: - flat-cache "^2.0.1" + escape-string-regexp "^1.0.5" file-entry-cache@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== dependencies: flat-cache "^2.0.1" +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= dependencies: extend-shallow "^2.0.1" is-number "^3.0.0" repeat-string "^1.6.1" to-regex-range "^2.1.0" -find-cache-dir@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" - integrity sha1-yN765XyKUqinhPnjHFfHQumToLk= - dependencies: - commondir "^1.0.1" - mkdirp "^0.5.1" - pkg-dir "^1.0.0" - -find-cache-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f" - integrity sha1-kojj6ePMN0hxfTnq3hfPcfww7m8= +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" dependencies: - commondir "^1.0.1" - make-dir "^1.0.0" - pkg-dir "^2.0.0" + to-regex-range "^5.0.1" -find-cache-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.0.0.tgz#4c1faed59f45184530fb9d7fa123a4d04a98472d" - integrity sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA== +find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" dependencies: commondir "^1.0.1" - make-dir "^1.0.0" + make-dir "^2.0.0" pkg-dir "^3.0.0" -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= +find-cache-dir@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= dependencies: locate-path "^2.0.0" find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== dependencies: locate-path "^3.0.0" -findup-sync@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" - integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw= +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +findup-sync@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" dependencies: detect-file "^1.0.0" - is-glob "^3.1.0" + is-glob "^4.0.0" micromatch "^3.0.4" resolve-dir "^1.0.1" flat-cache@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== dependencies: flatted "^2.0.0" rimraf "2.6.3" write "1.0.3" flatted@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" - integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg== + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" flatten@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" - integrity sha1-2uRqnXj74lKSJYzB54CkHZXAN4I= + version "1.0.3" + resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" flush-write-stream@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz#c5d586ef38af6097650b49bc41b55fabb19f35bd" - integrity sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw== + version "1.1.1" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" dependencies: - inherits "^2.0.1" - readable-stream "^2.0.4" + inherits "^2.0.3" + readable-stream "^2.3.6" for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= dependencies: map-cache "^0.2.2" from2@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" - integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= dependencies: inherits "^2.0.1" readable-stream "^2.0.0" -fs-minipass@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" - integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc" + integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^1.0.0" + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" dependencies: - minipass "^2.2.1" + minipass "^3.0.0" fs-write-stream-atomic@^1.0.8: version "1.0.10" resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" - integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= dependencies: graceful-fs "^4.1.2" iferr "^0.1.5" @@ -2866,77 +3190,81 @@ fs-write-stream-atomic@^1.0.8: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@^1.2.2: - version "1.2.4" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" - integrity sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg== +fsevents@^1.2.7: + version "1.2.12" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.12.tgz#db7e0d8ec3b0b45724fd4d83d43554a8f1f0de5c" dependencies: - nan "^2.9.2" - node-pre-gyp "^0.10.0" + bindings "^1.5.0" + nan "^2.12.1" function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - 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" +gensync@^1.0.0-beta.1: + version "1.0.0-beta.1" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" -get-caller-file@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" -get-stdin@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" - integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== +get-stdin@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-7.0.0.tgz#8d5de98f15171a125c5e516643c7a6d0ea8a96f6" -get-stream@^3.0.0: - version "3.0.0" - resolved "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + dependencies: + pump "^3.0.0" + +get-stream@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +getos@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/getos/-/getos-3.2.1.tgz#0134d1f4e00eb46144c5a9c0ac4dc087cbb27dc5" + integrity sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q== + dependencies: + async "^3.2.0" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= dependencies: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-to-regexp@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" - integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= +glob-parent@^5.0.0, glob-parent@^5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + dependencies: + is-glob "^4.0.1" -glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== +glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -2945,26 +3273,30 @@ glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" +global-dirs@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.0.1.tgz#acdf3bb6685bcd55cb35e8a052266569e9469201" + integrity sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A== + dependencies: + ini "^1.3.5" + +global-modules@2.0.0, global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + dependencies: + global-prefix "^3.0.0" + global-modules@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" - integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== dependencies: global-prefix "^1.0.1" is-windows "^1.0.1" resolve-dir "^1.0.0" -global-modules@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" - integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== - dependencies: - global-prefix "^3.0.0" - global-prefix@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" - integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= dependencies: expand-tilde "^2.0.2" homedir-polyfill "^1.0.1" @@ -2975,52 +3307,62 @@ global-prefix@^1.0.1: global-prefix@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" - integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== dependencies: ini "^1.3.5" kind-of "^6.0.2" which "^1.3.1" -globals@^11.1.0: - version "11.8.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.8.0.tgz#c1ef45ee9bed6badf0663c5cb90e8d1adec1321d" - integrity sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA== - -globals@^11.7.0: - version "11.11.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.11.0.tgz#dcf93757fa2de5486fbeed7118538adf789e9c2e" - integrity sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw== - -globby@^9.0.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-9.1.0.tgz#e90f4d5134109e6d855abdd31bdb1b085428592e" - integrity sha512-VtYjhHr7ncls724Of5W6Kaahz0ag7dB4G62/2HsN+xEKG6SrPzM1AJMerGxQTwJGnN9reeyxdvXbuZYpfssCvg== - dependencies: - "@types/glob" "^7.1.1" - array-union "^1.0.2" - dir-glob "^2.2.1" - fast-glob "^2.2.6" - glob "^7.1.3" - ignore "^4.0.3" - pify "^4.0.1" - slash "^2.0.0" +globals@^11.1.0, globals@^11.12.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + +globals@^12.1.0: + version "12.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" + dependencies: + type-fest "^0.8.1" + +globby@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.0.tgz#56fd0e9f0d4f8fb0c456f1ab0dee96e1380bc154" + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" globjoin@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43" - integrity sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM= -gonzales-pe@^4.2.3: +gonzales-pe@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.3.0.tgz#fe9dec5f3c557eead09ff868c65826be54d067b3" + dependencies: + minimist "^1.2.5" + +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2: version "4.2.3" - resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.2.3.tgz#41091703625433285e0aee3aa47829fc1fbeb6f2" - integrity sha512-Kjhohco0esHQnOiqqdJeNz/5fyPkOMD/d6XVjwTAoPGUFh0mCollPUTUTa2OZy4dYNAqlPIQdTiNzJTWdd9Htw== + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== dependencies: - minimist "1.1.x" + ajv "^6.12.3" + har-schema "^2.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.2: - version "4.1.15" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" - integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== +hard-rejection@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" has-ansi@^2.0.0: version "2.0.0" @@ -3032,22 +3374,18 @@ has-ansi@^2.0.0: has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= -has-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= +has-symbols@^1.0.0, has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= dependencies: get-value "^2.0.3" has-values "^0.1.4" @@ -3056,7 +3394,6 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= dependencies: get-value "^2.0.6" has-values "^1.0.0" @@ -3065,35 +3402,31 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= has-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= dependencies: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.0, has@^1.0.1, has@^1.0.3: +has@^1.0.0, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" hash-base@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.5" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.5.tgz#e38ab4b85dfb1e0c40fe9265c0e9b54854c23812" - integrity sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA== + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.1" @@ -3101,7 +3434,6 @@ hash.js@^1.0.0, hash.js@^1.0.3: hex-color-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" - integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== hmac-drbg@^1.0.0: version "1.0.1" @@ -3112,52 +3444,39 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -home-or-tmp@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-3.0.0.tgz#57a8fe24cf33cdd524860a15821ddc25c86671fb" - integrity sha1-V6j+JM8zzdUkhgoVgh3cJchmcfs= - homedir-polyfill@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc" - integrity sha1-TCu8inWJmP7r9e1oWA921GdotLw= + version "1.0.3" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" dependencies: parse-passwd "^1.0.0" hosted-git-info@^2.1.4: - version "2.7.1" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" - integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== + version "2.8.8" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" hsl-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" - integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= hsla-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" - integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= html-comment-regex@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" - integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== html-janitor@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/html-janitor/-/html-janitor-2.0.4.tgz#ae5a115cdf3331cd5501edd7b5471b18ea44cdbb" - integrity sha512-92J5h9jNZRk30PMHapjHEJfkrBWKCOy0bq3oW2pBungky6lzYSoboBGPMvxl1XRKB2q+kniQmsLsPbdpY7RM2g== -html-tags@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-2.0.0.tgz#10b30a386085f43cede353cc8fa7cb0deeea668b" - integrity sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos= +html-tags@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" htmlparser2@^3.10.0: version "3.10.1" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" - integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== dependencies: domelementtype "^1.3.1" domhandler "^2.3.0" @@ -3168,8 +3487,7 @@ htmlparser2@^3.10.0: htmlparser2@~3.8.1: version "3.8.3" - resolved "http://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068" - integrity sha1-mWwosZFRaovoZQGn15dX5ccMEGg= + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068" dependencies: domelementtype "1" domhandler "2.3" @@ -3177,68 +3495,68 @@ htmlparser2@~3.8.1: entities "1.0" readable-stream "1.1" +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= -iconv-lite@^0.4.24, iconv-lite@^0.4.4: +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + +iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" -icss-replace-symbols@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" - integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0= - -icss-utils@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.0.tgz#339dbbffb9f8729a243b701e1c29d4cc58c52f0e" - integrity sha512-3DEun4VOeMvSczifM3F2cKQrDQ5Pj6WKhkOq6HD4QTnDUAq8MQRxy5TX6Sy1iY6WPBe4gQ3p5vTECjbIkglkkQ== +icss-utils@^4.0.0, icss-utils@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" dependencies: postcss "^7.0.14" ieee754@^1.1.4: - version "1.1.12" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" - integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA== + version "1.1.13" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" iferr@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" - integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= - -ignore-walk@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" - integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== - dependencies: - minimatch "^3.0.4" -ignore@^4.0.3, ignore@^4.0.6: +ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.0.4: - version "5.0.5" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.0.5.tgz#c663c548d6ce186fb33616a8ccb5d46e56bdbbf9" - integrity sha512-kOC8IUb8HSDMVcYrDVezCxpJkzSQWTAzf3olpKM6o9rM5zpojx23O0Fl8Wr4+qJ6ZbPEHqf1fdwev/DS7v7pmA== +ignore@^5.1.1, ignore@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" import-cwd@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" - integrity sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk= dependencies: import-from "^2.1.0" -import-fresh@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.0.0.tgz#a3d897f420cab0e671236897f75bc14b4885c390" - integrity sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ== +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + +import-fresh@^3.0.0, import-fresh@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" @@ -3246,19 +3564,16 @@ import-fresh@^3.0.0: import-from@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" - integrity sha1-M1238qev/VOqpHHUuAId7ja387E= dependencies: resolve-from "^3.0.0" -import-lazy@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-3.1.0.tgz#891279202c8a2280fdbd6674dbd8da1a1dfc67cc" - integrity sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ== +import-lazy@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153" -import-local@^2.0.0: +import-local@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" - integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== dependencies: pkg-dir "^3.0.0" resolve-cwd "^2.0.0" @@ -3266,115 +3581,108 @@ import-local@^2.0.0: imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= indent-string@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + indexes-of@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" - integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= -indexof@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= +infer-owner@^1.0.3, infer-owner@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= +inherits@2, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== inherits@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= -ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" -inquirer@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.2.tgz#46941176f65c9eb20804627149b743a218f25406" - integrity sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA== +ini@^1.3.4, ini@^1.3.5: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +inquirer@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.1.0.tgz#1298a01859883e17c7264b82870ae1034f92dd29" dependencies: - ansi-escapes "^3.2.0" - chalk "^2.4.2" - cli-cursor "^2.1.0" + ansi-escapes "^4.2.1" + chalk "^3.0.0" + cli-cursor "^3.1.0" cli-width "^2.0.0" external-editor "^3.0.3" - figures "^2.0.0" - lodash "^4.17.11" - mute-stream "0.0.7" - run-async "^2.2.0" - rxjs "^6.4.0" - string-width "^2.1.0" - strip-ansi "^5.0.0" + figures "^3.0.0" + lodash "^4.17.15" + mute-stream "0.0.8" + run-async "^2.4.0" + rxjs "^6.5.3" + string-width "^4.1.0" + strip-ansi "^6.0.0" through "^2.3.6" -interpret@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" - integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ= +interpret@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" -invariant@^2.2.2: +invariant@^2.2.2, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== dependencies: loose-envify "^1.0.0" invert-kv@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" - integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== is-absolute-url@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" - integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= dependencies: kind-of "^3.0.2" is-accessor-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== dependencies: kind-of "^6.0.0" is-alphabetical@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.2.tgz#1fa6e49213cb7885b75d15862fb3f3d96c884f41" - integrity sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg== + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" is-alphanumeric@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz#4a9cef71daf4c001c1d81d63d140cf53fd6889f4" - integrity sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ= is-alphanumerical@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz#1138e9ae5040158dc6ff76b820acd6b7a181fd40" - integrity sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg== + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" dependencies: is-alphabetical "^1.0.0" is-decimal "^1.0.0" @@ -3382,46 +3690,39 @@ is-alphanumerical@^1.0.0: is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= is-arrayish@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" - integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= dependencies: binary-extensions "^1.0.0" is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-buffer@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" - integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" -is-builtin-module@^1.0.0: - version "1.0.0" - resolved "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" - integrity sha1-VAVy0096wxGfj3bDDLwbHgN6/74= - dependencies: - builtin-modules "^1.0.0" +is-callable@^1.1.4, is-callable@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" -is-callable@^1.1.3, is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" is-color-stop@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" - integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= dependencies: css-color-names "^0.0.4" hex-color-regex "^1.1.0" @@ -3433,31 +3734,26 @@ is-color-stop@^1.0.0: is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= dependencies: kind-of "^3.0.2" is-data-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== dependencies: kind-of "^6.0.0" is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= - -is-decimal@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.2.tgz#894662d6a8709d307f3a276ca4339c8fa5dff0ff" - integrity sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg== + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + +is-decimal@^1.0.0, is-decimal@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== dependencies: is-accessor-descriptor "^0.1.6" is-data-descriptor "^0.1.4" @@ -3466,7 +3762,6 @@ is-descriptor@^0.1.0: is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== dependencies: is-accessor-descriptor "^1.0.0" is-data-descriptor "^1.0.0" @@ -3475,24 +3770,20 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-directory@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= is-extendable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== dependencies: is-plain-object "^2.0.4" is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-fullwidth-code-point@^1.0.0: version "1.0.0" @@ -3504,321 +3795,410 @@ is-fullwidth-code-point@^1.0.0: is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= dependencies: is-extglob "^2.1.0" -is-glob@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" - integrity sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A= +is-glob@^4.0.0, is-glob@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" dependencies: is-extglob "^2.1.1" is-hexadecimal@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz#b6e710d7d07bb66b98cb8cece5c9b4921deeb835" - integrity sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A== + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" + +is-installed-globally@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141" + integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g== + dependencies: + global-dirs "^2.0.1" + is-path-inside "^3.0.1" is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= dependencies: kind-of "^3.0.2" -is-obj@^1.0.0: - version "1.0.1" - resolved "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + +is-observable@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e" + integrity sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA== + dependencies: + symbol-observable "^1.1.0" + +is-path-inside@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" + integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg== is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= -is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: +is-plain-obj@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= + version "2.2.2" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" -is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= +is-regex@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" dependencies: - has "^1.0.1" + has "^1.0.3" -is-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" - integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= +is-regexp@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-2.1.0.tgz#cd734a56864e23b956bf4e7c66c396a4c0b22c2d" is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= -is-supported-regexp-flag@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.1.tgz#21ee16518d2c1dd3edd3e9a0d57e50207ac364ca" - integrity sha512-3vcJecUUrpgCqc/ca0aWeNu64UGgxcvO60K/Fkr1N6RSvfGCTU60UKN68JDmKokgba0rFFJs12EnzOQa14ubKQ== +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + +is-string@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" is-svg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" - integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ== dependencies: html-comment-regex "^1.1.0" is-symbol@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" dependencies: - has-symbols "^1.0.0" + has-symbols "^1.0.1" + +is-typedarray@^1.0.0, is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" is-whitespace-character@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz#ede53b4c6f6fb3874533751ec9280d01928d03ed" - integrity sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ== + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7" is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== is-word-character@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.2.tgz#46a5dac3f2a1840898b91e576cd40d493f3ae553" - integrity sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA== + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.4.tgz#ce0e73216f98599060592f62ff31354ddbeb0230" + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= -js-levenshtein@^1.1.3: - version "1.1.4" - resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.4.tgz#3a56e3cbf589ca0081eb22cd9ba0b1290a16d26e" - integrity sha512-PxfGzSs0ztShKrUYPIn5r0MtyAhYcCwmndozzpz8YObbPnD1jFxzlBGbRnX2mIu6Z13xN6+PTu05TQFnZFlzow== +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +jest-worker@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.4.0.tgz#ee0e2ceee5a36ecddf5172d6d7e0ab00df157384" + dependencies: + merge-stream "^2.0.0" + supports-color "^7.0.0" "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= - -js-yaml@^3.12.0: - version "3.12.2" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.2.tgz#ef1d067c5a9d9cb65bd72f285b5d8105c77f14fc" - integrity sha512-QHn/Lh/7HhZ/Twc7vJYQTkjuCa0kaCcDcjK5Zlk2rvnUpy7DxMJ23+Jc2dcyvltwQVg1nygAVlB2oRDFHoRS5Q== +js-yaml@^3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" dependencies: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^3.7.0, js-yaml@^3.9.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" - integrity sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +jsdoctypeparser@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsdoctypeparser/-/jsdoctypeparser-6.1.0.tgz#acfb936c26300d98f1405cb03e20b06748e512a8" jsesc@^2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" - integrity sha1-5CGiqOINawgZ3yiQj3glJrlt0f4= + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= -json5@^0.5.0: - version "0.5.1" - resolved "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== dependencies: minimist "^1.2.0" -json5@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850" - integrity sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ== +json5@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" dependencies: - minimist "^1.2.0" + minimist "^1.2.5" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179" + integrity sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg== + dependencies: + universalify "^1.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= dependencies: is-buffer "^1.1.5" kind-of@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" -known-css-properties@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.11.0.tgz#0da784f115ea77c76b81536d7052e90ee6c86a8a" - integrity sha512-bEZlJzXo5V/ApNNa5z375mJC6Nrz4vG43UgcSCrg2OHC+yuB6j0iDSrY7RQ/+PRofFB03wNIIt9iXIVLr4wc7w== +known-css-properties@^0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.18.0.tgz#d6e00b56ee1d5b0d171fd86df1583cfb012c521f" + +lazy-ass@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" + integrity sha1-eZllXoZGwX8In90YfRUNMyTVRRM= lcid@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" - integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== dependencies: invert-kv "^2.0.0" -leven@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" - integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA= +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + +levenary@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77" + dependencies: + leven "^3.1.0" levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" -license-webpack-plugin@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/license-webpack-plugin/-/license-webpack-plugin-2.1.1.tgz#f0ab760f7f301c76f5af52e480f320656b5721bb" - integrity sha512-TiarZIg5vkQ2rGdYJn2+5YxO/zqlqjpK5IVglr7OfmrN1sBCakS+PQrsP2uC5gtve1ZDb9WMSUMlmHDQ0FoW4w== +license-webpack-plugin@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/license-webpack-plugin/-/license-webpack-plugin-2.1.4.tgz#c5529a4bb87cc9b4489b486d054ba7cae43a554e" dependencies: "@types/webpack-sources" "^0.1.5" webpack-sources "^1.2.0" -load-json-file@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + +listr-silent-renderer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" + integrity sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4= + +listr-update-renderer@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz#4ea8368548a7b8aecb7e06d8c95cb45ae2ede6a2" + integrity sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA== dependencies: - graceful-fs "^4.1.2" - parse-json "^4.0.0" - pify "^3.0.0" - strip-bom "^3.0.0" + chalk "^1.1.3" + cli-truncate "^0.2.1" + elegant-spinner "^1.0.1" + figures "^1.7.0" + indent-string "^3.0.0" + log-symbols "^1.0.2" + log-update "^2.3.0" + strip-ansi "^3.0.1" -loader-fs-cache@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/loader-fs-cache/-/loader-fs-cache-1.0.1.tgz#56e0bf08bd9708b26a765b68509840c8dec9fdbc" - integrity sha1-VuC/CL2XCLJqdltoUJhAyN7J/bw= +listr-verbose-renderer@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz#f1132167535ea4c1261102b9f28dac7cba1e03db" + integrity sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw== dependencies: - find-cache-dir "^0.1.1" - mkdirp "0.5.1" + chalk "^2.4.1" + cli-cursor "^2.1.0" + date-fns "^1.27.2" + figures "^2.0.0" -loader-runner@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.1.tgz#026f12fe7c3115992896ac02ba022ba92971b979" - integrity sha512-By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw== +listr@^0.14.3: + version "0.14.3" + resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" + integrity sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA== + dependencies: + "@samverschueren/stream-to-observable" "^0.3.0" + is-observable "^1.1.0" + is-promise "^2.1.0" + is-stream "^1.1.0" + listr-silent-renderer "^1.1.1" + listr-update-renderer "^0.5.0" + listr-verbose-renderer "^0.5.0" + p-map "^2.0.0" + rxjs "^6.3.3" -loader-utils@^1.0.2, loader-utils@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd" - integrity sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0= +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" dependencies: - big.js "^3.1.3" - emojis-list "^2.0.0" - json5 "^0.5.0" + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +loader-runner@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" -loader-utils@^1.2.3: +loader-utils@1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" - integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== dependencies: big.js "^5.2.2" emojis-list "^2.0.0" json5 "^1.0.1" +loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^1.0.1" + +loader-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= dependencies: p-locate "^2.0.0" path-exists "^3.0.0" @@ -3826,209 +4206,232 @@ locate-path@^2.0.0: locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== dependencies: p-locate "^3.0.0" path-exists "^3.0.0" -lodash._reinterpolate@~3.0.0: +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + dependencies: + p-locate "^4.1.0" + +lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= -lodash.template@^4.2.4: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0" - integrity sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A= +lodash.once@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= + +lodash.template@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" dependencies: - lodash._reinterpolate "~3.0.0" + lodash._reinterpolate "^3.0.0" lodash.templatesettings "^4.0.0" lodash.templatesettings@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz#2b4d4e95ba440d915ff08bc899e4553666713316" - integrity sha1-K01OlbpEDZFf8IvImeRVNmZxMxY= + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" dependencies: - lodash._reinterpolate "~3.0.0" + lodash._reinterpolate "^3.0.0" lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= lodash@^3.2.0: version "3.10.1" - resolved "http://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" - integrity sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y= + resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" -lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4: - version "4.17.11" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" - integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== +lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" -log-symbols@^2.0.0: +lodash@^4.17.19: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + +log-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" + integrity sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg= + dependencies: + chalk "^1.0.0" + +log-symbols@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== dependencies: chalk "^2.0.1" +log-symbols@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + dependencies: + chalk "^2.4.2" + +log-symbols@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" + integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== + dependencies: + chalk "^4.0.0" + +log-update@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708" + integrity sha1-iDKP19HOeTiykoN0bwsbwSayRwg= + dependencies: + ansi-escapes "^3.0.0" + cli-cursor "^2.0.0" + wrap-ansi "^3.0.1" + longest-streak@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.2.tgz#2421b6ba939a443bb9ffebf596585a50b4c38e2e" - integrity sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA== + version "2.0.4" + resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" loose-envify@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" -loud-rejection@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.0" + yallist "^3.0.2" -lru-cache@^4.1.3: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== +make-dir@^2.0.0, make-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" + pify "^4.0.1" + semver "^5.6.0" -make-dir@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" - integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== +make-dir@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" dependencies: - pify "^3.0.0" - -mamacro@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4" - integrity sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA== + semver "^6.0.0" map-age-cleaner@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz#098fb15538fd3dbe461f12745b0ca8568d4e3f74" - integrity sha512-UN1dNocxQq44IhJyMI4TU8phc2m9BddacHRPRjKGLYaF0jqd3xLz0jS0skpAU9WgYyoR4gHtUpzytNBS385FWQ== + version "0.1.3" + resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" dependencies: p-defer "^1.0.0" map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= map-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= -map-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" - integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk= +map-obj@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.1.0.tgz#b91221b542734b9f14256c0132c897c5d7256fd5" map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= dependencies: object-visit "^1.0.0" markdown-escapes@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.2.tgz#e639cbde7b99c841c0bacc8a07982873b46d2122" - integrity sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA== + version "1.0.4" + resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" -markdown-table@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.2.tgz#c78db948fa879903a41bce522e3b96f801c63786" - integrity sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw== +markdown-table@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-2.0.0.tgz#194a90ced26d31fe753d8b9434430214c011865b" + dependencies: + repeat-string "^1.0.0" -mathml-tag-names@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.0.tgz#490b70e062ee24636536e3d9481e333733d00f2c" - integrity sha512-3Zs9P/0zzwTob2pdgT0CHZuMbnSUSp8MB1bddfm+HDmnFWHGT4jvEZRf+2RuPoa+cjdn/z25SEt5gFTqdhvJAg== +mathml-tag-names@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== dependencies: hash-base "^3.0.0" inherits "^2.0.1" safe-buffer "^5.1.2" -mdast-util-compact@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/mdast-util-compact/-/mdast-util-compact-1.0.2.tgz#c12ebe16fffc84573d3e19767726de226e95f649" - integrity sha512-d2WS98JSDVbpSsBfVvD9TaDMlqPRz7ohM/11G0rp5jOBb5q96RJ6YLszQ/09AAixyzh23FeIpCGqfaamEADtWg== +mdast-util-compact@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-compact/-/mdast-util-compact-2.0.1.tgz#cabc69a2f43103628326f35b1acf735d55c99490" dependencies: - unist-util-visit "^1.1.0" + unist-util-visit "^2.0.0" -mdn-data@~1.1.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" - integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA== +mdn-data@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" + +mdn-data@2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.6.tgz#852dc60fcaa5daa2e8cf6c9189c440ed3e042978" mem@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-4.0.0.tgz#6437690d9471678f6cc83659c00cbafcd6b0cdaf" - integrity sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA== + version "4.3.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" dependencies: map-age-cleaner "^0.1.1" - mimic-fn "^1.0.0" - p-is-promise "^1.1.0" + mimic-fn "^2.0.0" + p-is-promise "^2.0.0" -memory-fs@^0.4.0, memory-fs@~0.4.1: +memory-fs@^0.4.0, memory-fs@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= dependencies: errno "^0.1.3" readable-stream "^2.0.1" -meow@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4" - integrity sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig== - dependencies: - camelcase-keys "^4.0.0" - decamelize-keys "^1.0.0" - loud-rejection "^1.0.0" - minimist-options "^3.0.1" - normalize-package-data "^2.3.4" - read-pkg-up "^3.0.0" - redent "^2.0.0" - trim-newlines "^2.0.0" - yargs-parser "^10.0.0" - -merge2@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" - integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA== +memory-fs@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +meow@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-6.1.0.tgz#4ff4641818d3502afcddc631f94cb6971a581cb3" + dependencies: + "@types/minimist" "^1.2.0" + camelcase-keys "^6.1.1" + decamelize-keys "^1.1.0" + hard-rejection "^2.0.0" + minimist-options "^4.0.1" + normalize-package-data "^2.5.0" + read-pkg-up "^7.0.0" + redent "^3.0.0" + trim-newlines "^3.0.0" + type-fest "^0.8.1" + yargs-parser "^18.1.1" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + +merge2@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" -micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8: +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -4044,19 +4447,45 @@ micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8: snapdragon "^0.8.1" to-regex "^3.0.2" +micromatch@^4.0.0, micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== dependencies: bn.js "^4.0.0" brorand "^1.0.1" +mime-db@1.44.0: + version "1.44.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" + integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== + +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.27" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" + integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== + dependencies: + mime-db "1.44.0" + mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== +mimic-fn@^2.0.0, mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + +min-indent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.0.tgz#cfc45c37e9ec0d8f0a0ec3dd4ef7f7c3abe39256" + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -4070,52 +4499,47 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" -minimist-options@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" - integrity sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ== +minimist-options@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.0.2.tgz#29c4021373ded40d546186725e57761e4b1984a7" dependencies: arrify "^1.0.1" is-plain-obj "^1.1.0" -minimist@0.0.8: - version "0.0.8" - resolved "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= +minimist@^1.2.0, minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" -minimist@1.1.x: - version "1.1.3" - resolved "http://registry.npmjs.org/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8" - integrity sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag= +minipass-collect@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" + dependencies: + minipass "^3.0.0" -minimist@^1.2.0: - version "1.2.0" - resolved "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= +minipass-flush@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" + dependencies: + minipass "^3.0.0" -minipass@^2.2.1, minipass@^2.3.4: - version "2.3.5" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" - integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== +minipass-pipeline@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.2.tgz#3dcb6bb4a546e32969c7ad710f2c79a86abba93a" dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" + minipass "^3.0.0" -minizlib@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.1.tgz#6734acc045a46e61d596a43bb9d9cd326e19cc42" - integrity sha512-TrfjCjk4jLhcJyGMYymBH6oTXcWjYbUAXTHDbtnWHjZC25h0cdajHuPE1zxb4DVmu8crfh+HwH/WMuyLG0nHBg== +minipass@^3.0.0, minipass@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.1.tgz#7607ce778472a185ad6d89082aa2070f79cedcd5" dependencies: - minipass "^2.2.1" + yallist "^4.0.0" mississippi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" - integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== dependencies: concat-stream "^1.5.0" duplexify "^3.4.2" @@ -4129,24 +4553,31 @@ mississippi@^3.0.0: through2 "^2.0.0" mixin-deep@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" - integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ== + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" dependencies: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: - version "0.5.1" - resolved "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= +mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.4, mkdirp@~0.5.1: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" dependencies: - minimist "0.0.8" + minimist "^1.2.5" + +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +moment@^2.27.0: + version "2.29.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" + integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" - integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= dependencies: aproba "^1.1.1" copy-concurrently "^1.0.0" @@ -4158,27 +4589,22 @@ move-concurrently@^1.0.1: ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= ms@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" -nan@^2.9.2: - version "2.11.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766" - integrity sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA== +nan@^2.12.1: + version "2.14.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -4195,31 +4621,18 @@ nanomatch@^1.2.9: natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= - -needle@^2.2.1: - version "2.2.4" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" - integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== - dependencies: - debug "^2.1.2" - iconv-lite "^0.4.4" - sax "^1.2.4" -neo-async@^2.5.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835" - integrity sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA== +neo-async@^2.5.0, neo-async@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -node-libs-browser@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df" - integrity sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg== +node-libs-browser@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" dependencies: assert "^1.1.1" browserify-zlib "^0.2.0" @@ -4228,10 +4641,10 @@ node-libs-browser@^2.0.0: constants-browserify "^1.0.0" crypto-browserify "^3.11.0" domain-browser "^1.1.1" - events "^1.0.0" + events "^3.0.0" https-browserify "^1.0.0" os-browserify "^0.3.0" - path-browserify "0.0.0" + path-browserify "0.0.1" process "^0.11.10" punycode "^1.2.4" querystring-es3 "^0.2.0" @@ -4242,199 +4655,153 @@ node-libs-browser@^2.0.0: timers-browserify "^2.0.4" tty-browserify "0.0.0" url "^0.11.0" - util "^0.10.3" - vm-browserify "0.0.4" + util "^0.11.0" + vm-browserify "^1.0.1" node-modules-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" - integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= - -node-pre-gyp@^0.10.0: - version "0.10.3" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" - integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - -node-releases@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.0.3.tgz#3414ed84595096459c251699bfcb47d88324a9e4" - integrity sha512-ZaZWMsbuDcetpHmYeKWPO6e63pSXLb50M7lJgCbcM2nC/nQC3daNifmtp5a2kp7EWwYfhuvH6zLPWkrF8IiDdw== - dependencies: - semver "^5.3.0" - -node-releases@^1.1.8: - version "1.1.10" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.10.tgz#5dbeb6bc7f4e9c85b899e2e7adcc0635c9b2adf7" - integrity sha512-KbUPCpfoBvb3oBkej9+nrU0/7xPlVhmhhUJ1PZqwIP5/1dJkRWKWD3OONjo6M2J7tSCBtDCumLwwqeI+DWWaLQ== - dependencies: - semver "^5.3.0" -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" +node-releases@^1.1.53: + version "1.1.53" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.53.tgz#2d821bfa499ed7c5dffc5e2f28c88e78a08ee3f4" -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: - version "2.4.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" - integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw== +normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" dependencies: hosted-git-info "^2.1.4" - is-builtin-module "^1.0.0" + resolve "^1.10.0" semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= dependencies: remove-trailing-separator "^1.0.1" normalize-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== normalize-range@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= normalize-selector@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03" - integrity sha1-0LFF62kRicY6eNIB3E/bEpPvDAM= normalize-url@^3.0.0: version "3.3.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" - integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== - -npm-bundled@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" - integrity sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g== - -npm-packlist@^1.1.6: - version "1.1.12" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.12.tgz#22bde2ebc12e72ca482abd67afc51eb49377243a" - integrity sha512-WJKFOVMeAlsU/pjXuqVdzU0WfgtIBCupkEVwn+1Y0ERAbUfWw8R4GjgVbaKnUjRoD2FoQbHOCbOyT5Mbs9Lw4g== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= dependencies: path-key "^2.0.0" -npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== +npm-run-path@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" + path-key "^3.0.0" nth-check@^1.0.2, nth-check@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== dependencies: boolbase "~1.0.0" num2fraction@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" - integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= -object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= dependencies: copy-descriptor "^0.1.0" define-property "^0.2.5" kind-of "^3.0.3" -object-hash@^1.1.4: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.0.tgz#76d9ba6ff113cf8efc0d996102851fe6723963e2" - integrity sha512-05KzQ70lSeGSrZJQXE5wNDiTkBJDlUT/myi6RX9dVIvz7a7Qh4oH93BQdiPMn27nldYvVQCKMUaM83AfizZlsQ== +object-hash@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.0.3.tgz#d12db044e03cd2ca3d77c0570d87225b02e1e6ea" + +object-inspect@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" -object-keys@^1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" - integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag== +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= dependencies: isobject "^3.0.0" -object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= +object.assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" dependencies: define-properties "^1.1.2" - es-abstract "^1.5.1" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.getownpropertydescriptors@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= dependencies: isobject "^3.0.1" object.values@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" - integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" dependencies: define-properties "^1.1.3" - es-abstract "^1.12.0" + es-abstract "^1.17.0-next.1" function-bind "^1.1.1" has "^1.0.3" once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" +onetime@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k= + onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" @@ -4442,139 +4809,137 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" -optionator@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + dependencies: + mimic-fn "^2.1.0" + +optionator@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" dependencies: deep-is "~0.1.3" - fast-levenshtein "~2.0.4" + fast-levenshtein "~2.0.6" levn "~0.3.0" prelude-ls "~1.1.2" type-check "~0.3.2" - wordwrap "~1.0.0" + word-wrap "~1.2.3" os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -os-locale@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.0.1.tgz#3b014fbf01d87f60a1e5348d80fe870dc82c4620" - integrity sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw== +os-locale@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" dependencies: - execa "^0.10.0" + execa "^1.0.0" lcid "^2.0.0" mem "^4.0.0" -os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: +os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" +ospath@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b" + integrity sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs= p-defer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" - integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= -p-is-promise@^1.1.0: - version "1.1.0" - resolved "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" - integrity sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4= +p-is-promise@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== dependencies: p-try "^1.0.0" -p-limit@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec" - integrity sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A== +p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" dependencies: p-try "^2.0.0" p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= dependencies: p-limit "^1.1.0" p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== dependencies: p-limit "^2.0.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + dependencies: + p-limit "^2.2.0" + +p-map@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== + +p-map@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + dependencies: + aggregate-error "^3.0.0" + p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= p-try@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" - integrity sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ== + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" pako@~1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" - integrity sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg== + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" parallel-transform@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06" - integrity sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY= + version "1.2.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" dependencies: - cyclist "~0.2.2" + cyclist "^1.0.1" inherits "^2.0.3" readable-stream "^2.1.5" parent-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.0.tgz#df250bdc5391f4a085fb589dad761f5ad6b865b5" - integrity sha512-8Mf5juOMmiE4FcmzYc4IaiS9L3+9paz2KOiXzkRviCP6aDmN49Hz6EMWz0lGNp9pX80GvvAuLADtyGfW/Em3TA== + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" dependencies: callsites "^3.0.0" parse-asn1@^5.0.0: - version "5.1.1" - resolved "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" - integrity sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw== + version "5.1.5" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" dependencies: asn1.js "^4.0.0" browserify-aes "^1.0.0" create-hash "^1.1.0" evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" -parse-entities@^1.0.2, parse-entities@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.0.tgz#9deac087661b2e36814153cb78d7e54a4c5fd6f4" - integrity sha512-XXtDdOPLSB0sHecbEapQi6/58U/ODj/KWfIXmmMCJF/eRn8laX6LZbOyioMoETOOJoWRW8/qTSl5VQkUIfKM5g== +parse-entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" dependencies: character-entities "^1.0.0" character-entities-legacy "^1.0.0" @@ -4583,77 +4948,82 @@ parse-entities@^1.0.2, parse-entities@^1.1.0: is-decimal "^1.0.0" is-hexadecimal "^1.0.0" +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= dependencies: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse-json@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + lines-and-columns "^1.1.6" + parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -path-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" - integrity sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo= +path-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= - dependencies: - pinkie-promise "^2.0.0" path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= -path-parse@^1.0.5, path-parse@^1.0.6: +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== -path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" dependencies: - pify "^3.0.0" + pify "^2.0.0" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" pbkdf2@^3.0.3: version "3.0.17" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" - integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== dependencies: create-hash "^1.1.2" create-hmac "^1.1.4" @@ -4661,96 +5031,87 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" -pify@^2.3.0: - version "2.3.0" - resolved "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -pify@^4.0.0, pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== +picomatch@^2.0.5, picomatch@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" +pify@^2.0.0, pify@^2.2.0, pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" pirates@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.0.tgz#850b18781b4ac6ec58a43c9ed9ec5fe6796addbd" - integrity sha512-8t5BsXy1LUIjn3WWOlOuFDuKswhQb/tkak641lvBgmPOBUQHXveORtlMCp6OdPV1dtuTaEahKA8VNz6uLfKBtA== + version "4.0.1" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" dependencies: node-modules-regexp "^1.0.0" -pkg-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" - integrity sha1-ektQio1bstYp1EcFb/TpyTFM89Q= - dependencies: - find-up "^1.0.0" - pkg-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= dependencies: find-up "^2.1.0" pkg-dir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== dependencies: find-up "^3.0.0" +pkg-dir@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + dependencies: + find-up "^4.0.0" + +pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" + dependencies: + find-up "^2.1.0" + posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= postcss-apply@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/postcss-apply/-/postcss-apply-0.12.0.tgz#11a47b271b14d81db97ed7f51a6c409d025a9c34" - integrity sha512-u8qZLyA9P86cD08IhqjSVV8tf1eGiKQ4fPvjcG3Ic/eOU65EAkDQClp8We7d15TG+RIWRVPSy9v7cJ2D9OReqw== dependencies: balanced-match "^1.0.0" postcss "^7.0.14" postcss-attribute-case-insensitive@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.1.tgz#b2a721a0d279c2f9103a36331c88981526428cc7" - integrity sha512-L2YKB3vF4PetdTIthQVeT+7YiSzMoNMLLYxPXXppOOP7NoazEAy45sh2LvJ8leCQjfBcfkYQs8TtCcQjeZTp8A== + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz#d93e46b504589e94ac7277b0463226c68041a880" dependencies: postcss "^7.0.2" - postcss-selector-parser "^5.0.0" + postcss-selector-parser "^6.0.2" postcss-calc@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" - integrity sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ== + version "7.0.2" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.2.tgz#504efcd008ca0273120568b0792b16cdcde8aac1" dependencies: - css-unit-converter "^1.1.1" - postcss "^7.0.5" - postcss-selector-parser "^5.0.0-rc.4" - postcss-value-parser "^3.3.1" + postcss "^7.0.27" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.0.2" postcss-color-functional-notation@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz#5efd37a88fbabeb00a2966d1e53d98ced93f74e0" - integrity sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g== dependencies: postcss "^7.0.2" postcss-values-parser "^2.0.0" @@ -4758,24 +5119,21 @@ postcss-color-functional-notation@^2.0.1: postcss-color-gray@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz#532a31eb909f8da898ceffe296fdc1f864be8547" - integrity sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw== dependencies: "@csstools/convert-colors" "^1.4.0" postcss "^7.0.5" postcss-values-parser "^2.0.0" -postcss-color-hex-alpha@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.2.tgz#e9b1886bb038daed33f6394168c210b40bb4fdb6" - integrity sha512-8bIOzQMGdZVifoBQUJdw+yIY00omBd2EwkJXepQo9cjp1UOHHHoeRDeSzTP6vakEpaRc6GAIOfvcQR7jBYaG5Q== +postcss-color-hex-alpha@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz#a8d9ca4c39d497c9661e374b9c51899ef0f87388" dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" + postcss "^7.0.14" + postcss-values-parser "^2.0.1" postcss-color-mod-function@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz#816ba145ac11cc3cb6baa905a75a49f903e4d31d" - integrity sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ== dependencies: "@csstools/convert-colors" "^1.4.0" postcss "^7.0.2" @@ -4784,7 +5142,6 @@ postcss-color-mod-function@^3.0.3: postcss-color-rebeccapurple@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz#c7a89be872bb74e45b1e3022bfe5748823e6de77" - integrity sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g== dependencies: postcss "^7.0.2" postcss-values-parser "^2.0.0" @@ -4792,7 +5149,6 @@ postcss-color-rebeccapurple@^4.0.1: postcss-colormin@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" - integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== dependencies: browserslist "^4.0.0" color "^3.0.0" @@ -4803,30 +5159,26 @@ postcss-colormin@^4.0.3: postcss-convert-values@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" - integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== dependencies: postcss "^7.0.0" postcss-value-parser "^3.0.0" -postcss-custom-media@^7.0.7: - version "7.0.7" - resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-7.0.7.tgz#bbc698ed3089ded61aad0f5bfb1fb48bf6969e73" - integrity sha512-bWPCdZKdH60wKOTG4HKEgxWnZVjAIVNOJDvi3lkuTa90xo/K0YHa2ZnlKLC5e2qF8qCcMQXt0yzQITBp8d0OFA== +postcss-custom-media@^7.0.8: + version "7.0.8" + resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz#fffd13ffeffad73621be5f387076a28b00294e0c" dependencies: - postcss "^7.0.5" + postcss "^7.0.14" -postcss-custom-properties@^8.0.9: - version "8.0.9" - resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-8.0.9.tgz#8943870528a6eae4c8e8d285b6ccc9fd1f97e69c" - integrity sha512-/Lbn5GP2JkKhgUO2elMs4NnbUJcvHX4AaF5nuJDaNkd2chYW1KA5qtOGGgdkBEWcXtKSQfHXzT7C6grEVyb13w== +postcss-custom-properties@^8.0.11: + version "8.0.11" + resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz#2d61772d6e92f22f5e0d52602df8fae46fa30d97" dependencies: - postcss "^7.0.5" - postcss-values-parser "^2.0.0" + postcss "^7.0.17" + postcss-values-parser "^2.0.1" postcss-custom-selectors@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz#64858c6eb2ecff2fb41d0b28c9dd7b3db4de7fba" - integrity sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w== dependencies: postcss "^7.0.2" postcss-selector-parser "^5.0.0-rc.3" @@ -4834,7 +5186,6 @@ postcss-custom-selectors@^5.1.2: postcss-dir-pseudo-class@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz#6e3a4177d0edb3abcc85fdb6fbb1c26dabaeaba2" - integrity sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw== dependencies: postcss "^7.0.2" postcss-selector-parser "^5.0.0-rc.3" @@ -4842,35 +5193,30 @@ postcss-dir-pseudo-class@^5.0.0: postcss-discard-comments@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" - integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== dependencies: postcss "^7.0.0" postcss-discard-duplicates@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" - integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== dependencies: postcss "^7.0.0" postcss-discard-empty@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" - integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== dependencies: postcss "^7.0.0" postcss-discard-overridden@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" - integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== dependencies: postcss "^7.0.0" postcss-double-position-gradients@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz#fc927d52fddc896cb3a2812ebc5df147e110522e" - integrity sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA== dependencies: postcss "^7.0.5" postcss-values-parser "^2.0.0" @@ -4878,7 +5224,6 @@ postcss-double-position-gradients@^1.0.0: postcss-env-function@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-2.0.2.tgz#0f3e3d3c57f094a92c2baf4b6241f0b0da5365d7" - integrity sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw== dependencies: postcss "^7.0.2" postcss-values-parser "^2.0.0" @@ -4886,42 +5231,36 @@ postcss-env-function@^2.0.2: postcss-focus-visible@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz#477d107113ade6024b14128317ade2bd1e17046e" - integrity sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g== dependencies: postcss "^7.0.2" postcss-focus-within@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz#763b8788596cee9b874c999201cdde80659ef680" - integrity sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w== dependencies: postcss "^7.0.2" postcss-font-variant@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-4.0.0.tgz#71dd3c6c10a0d846c5eda07803439617bbbabacc" - integrity sha512-M8BFYKOvCrI2aITzDad7kWuXXTm0YhGdP9Q8HanmN4EF1Hmcgs1KK5rSHylt/lUJe8yLxiSwWAHdScoEiIxztg== dependencies: postcss "^7.0.2" postcss-gap-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz#431c192ab3ed96a3c3d09f2ff615960f902c1715" - integrity sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg== dependencies: postcss "^7.0.2" postcss-html@^0.36.0: version "0.36.0" resolved "https://registry.yarnpkg.com/postcss-html/-/postcss-html-0.36.0.tgz#b40913f94eaacc2453fd30a1327ad6ee1f88b204" - integrity sha512-HeiOxGcuwID0AFsNAL0ox3mW6MHH5cstWN1Z3Y+n6H+g12ih7LHdYxWwEA/QmrebctLjo79xz9ouK3MroHwOJw== dependencies: htmlparser2 "^3.10.0" postcss-image-set-function@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz#28920a2f29945bed4c3198d7df6496d410d3f288" - integrity sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw== dependencies: postcss "^7.0.2" postcss-values-parser "^2.0.0" @@ -4929,7 +5268,6 @@ postcss-image-set-function@^3.0.1: postcss-import@^12.0.1: version "12.0.1" resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-12.0.1.tgz#cf8c7ab0b5ccab5649024536e565f841928b7153" - integrity sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw== dependencies: postcss "^7.0.1" postcss-value-parser "^3.2.3" @@ -4937,48 +5275,36 @@ postcss-import@^12.0.1: resolve "^1.1.7" postcss-initial@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.0.tgz#1772512faf11421b791fb2ca6879df5f68aa0517" - integrity sha512-WzrqZ5nG9R9fUtrA+we92R4jhVvEB32IIRTzfIG/PLL8UV4CvbF1ugTEHEFX6vWxl41Xt5RTCJPEZkuWzrOM+Q== + version "3.0.2" + resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.2.tgz#f018563694b3c16ae8eaabe3c585ac6319637b2d" dependencies: - lodash.template "^4.2.4" + lodash.template "^4.5.0" postcss "^7.0.2" -postcss-jsx@^0.36.0: - version "0.36.0" - resolved "https://registry.yarnpkg.com/postcss-jsx/-/postcss-jsx-0.36.0.tgz#b7685ed3d070a175ef0aa48f83d9015bd772c82d" - integrity sha512-/lWOSXSX5jlITCKFkuYU2WLFdrncZmjSVyNpHAunEgirZXLwI8RjU556e3Uz4mv0WVHnJA9d3JWb36lK9Yx99g== - dependencies: - "@babel/core" ">=7.1.0" - postcss-lab-function@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz#bb51a6856cd12289ab4ae20db1e3821ef13d7d2e" - integrity sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg== dependencies: "@csstools/convert-colors" "^1.4.0" postcss "^7.0.2" postcss-values-parser "^2.0.0" -postcss-less@^3.1.0: - version "3.1.3" - resolved "https://registry.yarnpkg.com/postcss-less/-/postcss-less-3.1.3.tgz#c827617861dddc029f55fcc5d4143dcd6fc8c5cd" - integrity sha512-S0LYoO278GVmyT1uCgr1h95L19dkmzuJDMdpSMCtv+bj15OoJXtFX6c/2AlyL4OEOauGTC7nuqfudVd5kzFtuA== +postcss-less@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/postcss-less/-/postcss-less-3.1.4.tgz#369f58642b5928ef898ffbc1a6e93c958304c5ad" dependencies: postcss "^7.0.14" postcss-load-config@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.0.0.tgz#f1312ddbf5912cd747177083c5ef7a19d62ee484" - integrity sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.0.tgz#c84d692b7bb7b41ddced94ee62e8ab31b417b003" dependencies: - cosmiconfig "^4.0.0" + cosmiconfig "^5.0.0" import-cwd "^2.0.0" postcss-loader@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-3.0.0.tgz#6b97943e47c72d845fa9e03f273773d4e8dd6c2d" - integrity sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA== dependencies: loader-utils "^1.1.0" postcss "^7.0.0" @@ -4988,34 +5314,22 @@ postcss-loader@^3.0.0: postcss-logical@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-3.0.0.tgz#2495d0f8b82e9f262725f75f9401b34e7b45d5b5" - integrity sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA== dependencies: postcss "^7.0.2" -postcss-markdown@^0.36.0: - version "0.36.0" - resolved "https://registry.yarnpkg.com/postcss-markdown/-/postcss-markdown-0.36.0.tgz#7f22849ae0e3db18820b7b0d5e7833f13a447560" - integrity sha512-rl7fs1r/LNSB2bWRhyZ+lM/0bwKv9fhl38/06gF6mKMo/NPnp55+K1dSTosSVjFZc0e1ppBlu+WT91ba0PMBfQ== - dependencies: - remark "^10.0.1" - unist-util-find-all-after "^1.0.2" - postcss-media-minmax@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz#b75bb6cbc217c8ac49433e12f22048814a4f5ed5" - integrity sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw== dependencies: postcss "^7.0.2" postcss-media-query-parser@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244" - integrity sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ= postcss-merge-longhand@^4.0.11: version "4.0.11" resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" - integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== dependencies: css-color-names "0.0.4" postcss "^7.0.0" @@ -5025,7 +5339,6 @@ postcss-merge-longhand@^4.0.11: postcss-merge-rules@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" - integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== dependencies: browserslist "^4.0.0" caniuse-api "^3.0.0" @@ -5037,7 +5350,6 @@ postcss-merge-rules@^4.0.3: postcss-minify-font-values@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" - integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== dependencies: postcss "^7.0.0" postcss-value-parser "^3.0.0" @@ -5045,7 +5357,6 @@ postcss-minify-font-values@^4.0.2: postcss-minify-gradients@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" - integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== dependencies: cssnano-util-get-arguments "^4.0.0" is-color-stop "^1.0.0" @@ -5055,7 +5366,6 @@ postcss-minify-gradients@^4.0.2: postcss-minify-params@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" - integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== dependencies: alphanum-sort "^1.0.0" browserslist "^4.0.0" @@ -5067,7 +5377,6 @@ postcss-minify-params@^4.0.2: postcss-minify-selectors@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" - integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== dependencies: alphanum-sort "^1.0.0" has "^1.0.0" @@ -5077,70 +5386,62 @@ postcss-minify-selectors@^4.0.2: postcss-modules-extract-imports@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" - integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== dependencies: postcss "^7.0.5" -postcss-modules-local-by-default@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.6.tgz#dd9953f6dd476b5fd1ef2d8830c8929760b56e63" - integrity sha512-oLUV5YNkeIBa0yQl7EYnxMgy4N6noxmiwZStaEJUSe2xPMcdNc8WmBQuQCx18H5psYbVxz8zoHk0RAAYZXP9gA== +postcss-modules-local-by-default@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz#e8a6561be914aaf3c052876377524ca90dbb7915" dependencies: - postcss "^7.0.6" - postcss-selector-parser "^6.0.0" - postcss-value-parser "^3.3.1" + icss-utils "^4.1.1" + postcss "^7.0.16" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.0.0" -postcss-modules-scope@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz#ad3f5bf7856114f6fcab901b0502e2a2bc39d4eb" - integrity sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A== +postcss-modules-scope@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" dependencies: postcss "^7.0.6" postcss-selector-parser "^6.0.0" -postcss-modules-values@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz#479b46dc0c5ca3dc7fa5270851836b9ec7152f64" - integrity sha512-Ki7JZa7ff1N3EIMlPnGTZfUMe69FFwiQPnVSXC9mnn3jozCRBYIxiZd44yJOV2AmabOo4qFf8s0dC/+lweG7+w== +postcss-modules-values@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" dependencies: - icss-replace-symbols "^1.1.0" + icss-utils "^4.0.0" postcss "^7.0.6" postcss-nested-ancestors@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-nested-ancestors/-/postcss-nested-ancestors-2.0.0.tgz#957ef27fb9e37cb082786d95b5e310d4b47470fe" - integrity sha512-r8WbA1XLqbDuOGdCWpQ5nXdHvL4eKdnCEcDAnUlIAUHk7ZIQAESqPdxrWGPlq70ZB+FKw4wPbX1850dgFuxUKQ== dependencies: escape-string-regexp "^1.0.5" postcss "^6.0.0" postcss-resolve-nested-selector "^0.1.1" postcss-nested@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-4.1.2.tgz#8e0570f736bfb4be5136e31901bf2380b819a561" - integrity sha512-9bQFr2TezohU3KRSu9f6sfecXmf/x6RXDedl8CHF6fyuyVW7UqgNMRdWMHZQWuFY6Xqs2NYk+Fj4Z4vSOf7PQg== + version "4.2.1" + resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-4.2.1.tgz#4bc2e5b35e3b1e481ff81e23b700da7f82a8b248" dependencies: - postcss "^7.0.14" - postcss-selector-parser "^5.0.0" + postcss "^7.0.21" + postcss-selector-parser "^6.0.2" postcss-nesting@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-7.0.0.tgz#6e26a770a0c8fcba33782a6b6f350845e1a448f6" - integrity sha512-WSsbVd5Ampi3Y0nk/SKr5+K34n52PqMqEfswu6RtU4r7wA8vSD+gM8/D9qq4aJkHImwn1+9iEFTbjoWsQeqtaQ== + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-7.0.1.tgz#b50ad7b7f0173e5b5e3880c3501344703e04c052" dependencies: postcss "^7.0.2" postcss-normalize-charset@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" - integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== dependencies: postcss "^7.0.0" postcss-normalize-display-values@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" - integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== dependencies: cssnano-util-get-match "^4.0.0" postcss "^7.0.0" @@ -5149,7 +5450,6 @@ postcss-normalize-display-values@^4.0.2: postcss-normalize-positions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" - integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== dependencies: cssnano-util-get-arguments "^4.0.0" has "^1.0.0" @@ -5159,7 +5459,6 @@ postcss-normalize-positions@^4.0.2: postcss-normalize-repeat-style@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" - integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== dependencies: cssnano-util-get-arguments "^4.0.0" cssnano-util-get-match "^4.0.0" @@ -5169,7 +5468,6 @@ postcss-normalize-repeat-style@^4.0.2: postcss-normalize-string@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" - integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== dependencies: has "^1.0.0" postcss "^7.0.0" @@ -5178,7 +5476,6 @@ postcss-normalize-string@^4.0.2: postcss-normalize-timing-functions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" - integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== dependencies: cssnano-util-get-match "^4.0.0" postcss "^7.0.0" @@ -5187,7 +5484,6 @@ postcss-normalize-timing-functions@^4.0.2: postcss-normalize-unicode@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" - integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== dependencies: browserslist "^4.0.0" postcss "^7.0.0" @@ -5196,7 +5492,6 @@ postcss-normalize-unicode@^4.0.1: postcss-normalize-url@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" - integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== dependencies: is-absolute-url "^2.0.0" normalize-url "^3.0.0" @@ -5206,7 +5501,6 @@ postcss-normalize-url@^4.0.1: postcss-normalize-whitespace@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" - integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== dependencies: postcss "^7.0.0" postcss-value-parser "^3.0.0" @@ -5214,7 +5508,6 @@ postcss-normalize-whitespace@^4.0.2: postcss-ordered-values@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" - integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== dependencies: cssnano-util-get-arguments "^4.0.0" postcss "^7.0.0" @@ -5223,46 +5516,42 @@ postcss-ordered-values@^4.1.2: postcss-overflow-shorthand@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz#31ecf350e9c6f6ddc250a78f0c3e111f32dd4c30" - integrity sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g== dependencies: postcss "^7.0.2" postcss-page-break@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-2.0.0.tgz#add52d0e0a528cabe6afee8b46e2abb277df46bf" - integrity sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ== dependencies: postcss "^7.0.2" postcss-place@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-4.0.1.tgz#e9f39d33d2dc584e46ee1db45adb77ca9d1dcc62" - integrity sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg== dependencies: postcss "^7.0.2" postcss-values-parser "^2.0.0" postcss-preset-env@^6.6.0: - version "6.6.0" - resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-6.6.0.tgz#642e7d962e2bdc2e355db117c1eb63952690ed5b" - integrity sha512-I3zAiycfqXpPIFD6HXhLfWXIewAWO8emOKz+QSsxaUZb9Dp8HbF5kUf+4Wy/AxR33o+LRoO8blEWCHth0ZsCLA== + version "6.7.0" + resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz#c34ddacf8f902383b35ad1e030f178f4cdf118a5" dependencies: - autoprefixer "^9.4.9" - browserslist "^4.4.2" - caniuse-lite "^1.0.30000939" + autoprefixer "^9.6.1" + browserslist "^4.6.4" + caniuse-lite "^1.0.30000981" css-blank-pseudo "^0.1.4" css-has-pseudo "^0.10.0" css-prefers-color-scheme "^3.1.1" - cssdb "^4.3.0" - postcss "^7.0.14" + cssdb "^4.4.0" + postcss "^7.0.17" postcss-attribute-case-insensitive "^4.0.1" postcss-color-functional-notation "^2.0.1" postcss-color-gray "^5.0.0" - postcss-color-hex-alpha "^5.0.2" + postcss-color-hex-alpha "^5.0.3" postcss-color-mod-function "^3.0.3" postcss-color-rebeccapurple "^4.0.1" - postcss-custom-media "^7.0.7" - postcss-custom-properties "^8.0.9" + postcss-custom-media "^7.0.8" + postcss-custom-properties "^8.0.11" postcss-custom-selectors "^5.1.2" postcss-dir-pseudo-class "^5.0.0" postcss-double-position-gradients "^1.0.0" @@ -5288,7 +5577,6 @@ postcss-preset-env@^6.6.0: postcss-pseudo-class-any-link@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz#2ed3eed393b3702879dec4a87032b210daeb04d1" - integrity sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew== dependencies: postcss "^7.0.2" postcss-selector-parser "^5.0.0-rc.3" @@ -5296,7 +5584,6 @@ postcss-pseudo-class-any-link@^6.0.0: postcss-reduce-initial@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" - integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== dependencies: browserslist "^4.0.0" caniuse-api "^3.0.0" @@ -5306,7 +5593,6 @@ postcss-reduce-initial@^4.0.3: postcss-reduce-transforms@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" - integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== dependencies: cssnano-util-get-match "^4.0.0" has "^1.0.0" @@ -5316,51 +5602,44 @@ postcss-reduce-transforms@^4.0.2: postcss-replace-overflow-wrap@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz#61b360ffdaedca84c7c918d2b0f0d0ea559ab01c" - integrity sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw== dependencies: postcss "^7.0.2" -postcss-reporter@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-6.0.0.tgz#44c873129d8c029a430b6d2186210d79c8de88b8" - integrity sha512-5xQXm1UPWuFObjbtyQzWvQaupru8yFcFi4HUlm6OPo1o2bUszYASuqRJ7bVArb3svGCdbYtqdMBKrqR1Aoy+tw== +postcss-reporter@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-6.0.1.tgz#7c055120060a97c8837b4e48215661aafb74245f" dependencies: - chalk "^2.0.1" - lodash "^4.17.4" - log-symbols "^2.0.0" - postcss "^7.0.2" + chalk "^2.4.1" + lodash "^4.17.11" + log-symbols "^2.2.0" + postcss "^7.0.7" postcss-resolve-nested-selector@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz#29ccbc7c37dedfac304e9fff0bf1596b3f6a0e4e" - integrity sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4= -postcss-safe-parser@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-4.0.1.tgz#8756d9e4c36fdce2c72b091bbc8ca176ab1fcdea" - integrity sha512-xZsFA3uX8MO3yAda03QrG3/Eg1LN3EPfjjf07vke/46HERLZyHrTsQ9E1r1w1W//fWEhtYNndo2hQplN2cVpCQ== +postcss-safe-parser@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz#a6d4e48f0f37d9f7c11b2a581bf00f8ba4870b96" dependencies: - postcss "^7.0.0" + postcss "^7.0.26" -postcss-sass@^0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/postcss-sass/-/postcss-sass-0.3.5.tgz#6d3e39f101a53d2efa091f953493116d32beb68c" - integrity sha512-B5z2Kob4xBxFjcufFnhQ2HqJQ2y/Zs/ic5EZbCywCkxKd756Q40cIQ/veRDwSrw1BF6+4wUgmpm0sBASqVi65A== +postcss-sass@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/postcss-sass/-/postcss-sass-0.4.4.tgz#91f0f3447b45ce373227a98b61f8d8f0785285a3" dependencies: - gonzales-pe "^4.2.3" - postcss "^7.0.1" + gonzales-pe "^4.3.0" + postcss "^7.0.21" postcss-scss@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-2.0.0.tgz#248b0a28af77ea7b32b1011aba0f738bda27dea1" - integrity sha512-um9zdGKaDZirMm+kZFKKVsnKPF7zF7qBAtIfTSnZXD1jZ0JNZIxdB6TxQOjCnlSzLRInVl2v3YdBh/M881C4ug== dependencies: postcss "^7.0.0" postcss-selector-matches@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz#71c8248f917ba2cc93037c9637ee09c64436fcff" - integrity sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww== dependencies: balanced-match "^1.0.0" postcss "^7.0.2" @@ -5368,33 +5647,29 @@ postcss-selector-matches@^4.0.0: postcss-selector-not@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-4.0.0.tgz#c68ff7ba96527499e832724a2674d65603b645c0" - integrity sha512-W+bkBZRhqJaYN8XAnbbZPLWMvZD1wKTu0UxtFKdhtGjWYmxhkUneoeOhRJKdAE5V7ZTlnbHfCR+6bNwK9e1dTQ== dependencies: balanced-match "^1.0.0" postcss "^7.0.2" -postcss-selector-parser@^3.0.0, postcss-selector-parser@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" - integrity sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU= +postcss-selector-parser@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz#b310f5c4c0fdaf76f94902bbaa30db6aa84f5270" dependencies: - dot-prop "^4.1.1" + dot-prop "^5.2.0" indexes-of "^1.0.1" uniq "^1.0.1" -postcss-selector-parser@^5.0.0, postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4: +postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4: version "5.0.0" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" - integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== dependencies: cssesc "^2.0.0" indexes-of "^1.0.1" uniq "^1.0.1" -postcss-selector-parser@^6.0.0: +postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" - integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== dependencies: cssesc "^3.0.0" indexes-of "^1.0.1" @@ -5403,7 +5678,6 @@ postcss-selector-parser@^6.0.0: postcss-svgo@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" - integrity sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw== dependencies: is-svg "^3.0.0" postcss "^7.0.0" @@ -5413,26 +5687,26 @@ postcss-svgo@^4.0.2: postcss-syntax@^0.36.2: version "0.36.2" resolved "https://registry.yarnpkg.com/postcss-syntax/-/postcss-syntax-0.36.2.tgz#f08578c7d95834574e5593a82dfbfa8afae3b51c" - integrity sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w== postcss-unique-selectors@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" - integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== dependencies: alphanum-sort "^1.0.0" postcss "^7.0.0" uniqs "^2.0.0" -postcss-value-parser@^3.0.0, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0, postcss-value-parser@^3.3.1: +postcss-value-parser@^3.0.0, postcss-value-parser@^3.2.3: version "3.3.1" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" - integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss-values-parser@^2.0.0: +postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz#651ff4593aa9eda8d5d0d66593a2417aeaeb325d" + +postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz#da8b472d901da1e205b47bdc98637b9e9e550e5f" - integrity sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg== dependencies: flatten "^1.0.2" indexes-of "^1.0.1" @@ -5441,25 +5715,14 @@ postcss-values-parser@^2.0.0: postcss@^6.0.0: version "6.0.23" resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" - integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== dependencies: chalk "^2.4.1" source-map "^0.6.1" supports-color "^5.4.0" -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.2, postcss@^7.0.5: - version "7.0.5" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.5.tgz#70e6443e36a6d520b0fd4e7593fcca3635ee9f55" - integrity sha512-HBNpviAUFCKvEh7NZhw1e8MBPivRszIiUnhrJ+sBFVSYSqubrzwX3KG51mYgcRHX8j/cAgZJedONZcm5jTBdgQ== - dependencies: - chalk "^2.4.1" - source-map "^0.6.1" - supports-color "^5.5.0" - -postcss@^7.0.13, postcss@^7.0.14, postcss@^7.0.6: - version "7.0.14" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.14.tgz#4527ed6b1ca0d82c53ce5ec1a2041c2346bbd6e5" - integrity sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg== +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.21, postcss@^7.0.26, postcss@^7.0.27, postcss@^7.0.5, postcss@^7.0.6, postcss@^7.0.7: + version "7.0.27" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.27.tgz#cc67cdc6b0daa375105b7c424a85567345fc54d9" dependencies: chalk "^2.4.2" source-map "^0.6.1" @@ -5468,47 +5731,44 @@ postcss@^7.0.13, postcss@^7.0.14, postcss@^7.0.6: prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= -private@^0.1.6: +pretty-bytes@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.4.1.tgz#cd89f79bbcef21e3d21eb0da68ffe93f803e884b" + integrity sha512-s1Iam6Gwz3JI5Hweaz4GoCD1WUNUIyzePFy5+Js2hjwGVt2Z79wNN+ZKOZ2vB6C+Xs6njyB84Z1IthQg8d9LxA== + +private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== process-nextick-args@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= progress@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.1.tgz#c9242169342b1c29d275889c95734621b1952e31" - integrity sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg== + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" - integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= +psl@^1.1.28: + version "1.8.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== public-encrypt@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== dependencies: bn.js "^4.1.0" browserify-rsa "^4.0.0" @@ -5520,7 +5780,6 @@ public-encrypt@^4.0.0: pump@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" - integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== dependencies: end-of-stream "^1.1.0" once "^1.3.1" @@ -5528,7 +5787,6 @@ pump@^2.0.0: pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== dependencies: end-of-stream "^1.1.0" once "^1.3.1" @@ -5536,7 +5794,6 @@ pump@^3.0.0: pumpify@^1.3.3: version "1.5.1" resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" - integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== dependencies: duplexify "^3.6.0" inherits "^2.0.3" @@ -5545,99 +5802,102 @@ pumpify@^1.3.3: punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= punycode@^1.2.4: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= -punycode@^2.1.0: +punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== q@^1.1.2: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= + +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= -quick-lru@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" - integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g= +quick-lru@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" + +ramda@~0.26.1: + version "0.26.1" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06" + integrity sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ== randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" - integrity sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A== + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" dependencies: safe-buffer "^5.1.0" randomfill@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== dependencies: randombytes "^2.0.5" safe-buffer "^5.1.0" -raw-loader@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-1.0.0.tgz#3f9889e73dadbda9a424bce79809b4133ad46405" - integrity sha512-Uqy5AqELpytJTRxYT4fhltcKPj0TyaEpzJDcGz7DFJi+pQOOi3GjR/DOdxTkTsF+NzhnldIoG6TORaBlInUuqA== - dependencies: - loader-utils "^1.1.0" - schema-utils "^1.0.0" - -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== +raw-loader@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-4.0.1.tgz#14e1f726a359b68437e183d5a5b7d33a3eba6933" dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" + loader-utils "^2.0.0" + schema-utils "^2.6.5" read-cache@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" - integrity sha1-5mTvMRYRZsl1HNvo28+GtftY93Q= dependencies: pify "^2.3.0" -read-pkg-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" - integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" dependencies: find-up "^2.0.0" - read-pkg "^3.0.0" + read-pkg "^2.0.0" -read-pkg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" - integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= +read-pkg-up@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" dependencies: - load-json-file "^4.0.0" + load-json-file "^2.0.0" normalize-package-data "^2.3.2" - path-type "^3.0.0" + path-type "^2.0.0" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6: - version "2.3.6" - resolved "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -5649,140 +5909,121 @@ read-pkg@^3.0.0: readable-stream@1.1: version "1.1.13" - resolved "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" - integrity sha1-9u73ZPUUyJ4rniMUanW6EGdW0j4= + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" dependencies: core-util-is "~1.0.0" inherits "~2.0.1" isarray "0.0.1" string_decoder "~0.10.x" -"readable-stream@2 || 3": - version "3.0.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.0.6.tgz#351302e4c68b5abd6a2ed55376a7f9a25be3057a" - integrity sha512-9E1oLoOWfhSXHGv6QlwXJim7uNzd9EVlWK+21tCU9Ju/kR0/p2AZYPz4qSchgO8PlLIH4FpZYfzwS+rEksZjIg== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - readable-stream@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.2.0.tgz#de17f229864c120a9f56945756e4f32c4045245d" - integrity sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw== + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" dependencies: inherits "^2.0.3" string_decoder "^1.1.1" util-deprecate "^1.0.1" -readdirp@^2.0.0: +readdirp@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== dependencies: graceful-fs "^4.1.11" micromatch "^3.1.10" readable-stream "^2.0.2" -redent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" - integrity sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo= +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" dependencies: - indent-string "^3.0.0" - strip-indent "^2.0.0" + indent-string "^4.0.0" + strip-indent "^3.0.0" -regenerate-unicode-properties@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz#107405afcc4a190ec5ed450ecaa00ed0cafa7a4c" - integrity sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw== +regenerate-unicode-properties@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" dependencies: regenerate "^1.4.0" regenerate@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== -regenerator-runtime@^0.12.0: - version "0.12.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" - integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== +regenerator-runtime@^0.13.4: + version "0.13.5" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" -regenerator-transform@^0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.4.tgz#18f6763cf1382c69c36df76c6ce122cc694284fb" - integrity sha512-T0QMBjK3J0MtxjPmdIMXm72Wvj2Abb0Bd4HADdfijwMdoIsyQZ6fWC7kDFhk2YinBBEMZDL7Y7wh0J1sGx3S4A== +regenerator-transform@^0.14.2: + version "0.14.4" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.4.tgz#5266857896518d1616a78a0479337a30ea974cc7" dependencies: - private "^0.1.6" + "@babel/runtime" "^7.8.4" + private "^0.1.8" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== dependencies: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexp-tree@^0.1.0: - version "0.1.5" - resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.5.tgz#7cd71fca17198d04b4176efd79713f2998009397" - integrity sha512-nUmxvfJyAODw+0B13hj8CFVAxhe7fDEAgJgaotBu3nnR+IgGgZq59YedJP5VYTlkEfqjuK6TuRpnymKdatLZfQ== - regexpp@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== -regexpu-core@^4.1.3, regexpu-core@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.2.0.tgz#a3744fa03806cffe146dea4421a3e73bdcc47b1d" - integrity sha512-Z835VSnJJ46CNBttalHD/dB+Sj2ezmY6Xp38npwU87peK6mqOzOpV8eYktdkLTEkzzD+JsTcxd84ozd8I14+rw== +regexpp@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" + +regexpu-core@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.0.tgz#fcbf458c50431b0bb7b45d6967b8192d91f3d938" dependencies: regenerate "^1.4.0" - regenerate-unicode-properties "^7.0.0" - regjsgen "^0.4.0" - regjsparser "^0.3.0" + regenerate-unicode-properties "^8.2.0" + regjsgen "^0.5.1" + regjsparser "^0.6.4" unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.0.2" + unicode-match-property-value-ecmascript "^1.2.0" -regjsgen@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.4.0.tgz#c1eb4c89a209263f8717c782591523913ede2561" - integrity sha512-X51Lte1gCYUdlwhF28+2YMO0U6WeN0GLpgpA7LK7mbdDnkQYiwvEpmpe0F/cv5L14EbxgrdayAG3JETBv0dbXA== +regextras@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/regextras/-/regextras-0.7.0.tgz#2298bef8cfb92b1b7e3b9b12aa8f69547b7d71e4" -regjsparser@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.3.0.tgz#3c326da7fcfd69fa0d332575a41c8c0cdf588c96" - integrity sha512-zza72oZBBHzt64G7DxdqrOo/30bhHkwMUoT0WqfGu98XLd7N+1tsy5MJ96Bk4MD0y74n629RhmrGW6XlnLLwCA== +regjsgen@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" + +regjsparser@^0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272" dependencies: jsesc "~0.5.0" -remark-parse@^6.0.0: - version "6.0.3" - resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-6.0.3.tgz#c99131052809da482108413f87b0ee7f52180a3a" - integrity sha512-QbDXWN4HfKTUC0hHa4teU463KclLAnwpn/FBn87j9cKYJWWawbiLgMfP2Q4XwhxxuuuOxHlw+pSN0OKuJwyVvg== +remark-parse@^8.0.0: + version "8.0.2" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-8.0.2.tgz#5999bc0b9c2e3edc038800a64ff103d0890b318b" dependencies: + ccount "^1.0.0" collapse-white-space "^1.0.2" is-alphabetical "^1.0.0" is-decimal "^1.0.0" is-whitespace-character "^1.0.0" is-word-character "^1.0.0" markdown-escapes "^1.0.0" - parse-entities "^1.1.0" + parse-entities "^2.0.0" repeat-string "^1.5.4" state-toggle "^1.0.0" trim "0.0.1" trim-trailing-lines "^1.0.0" unherit "^1.0.4" - unist-util-remove-position "^1.0.0" - vfile-location "^2.0.0" + unist-util-remove-position "^2.0.0" + vfile-location "^3.0.0" xtend "^4.0.1" -remark-stringify@^6.0.0: - version "6.0.4" - resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-6.0.4.tgz#16ac229d4d1593249018663c7bddf28aafc4e088" - integrity sha512-eRWGdEPMVudijE/psbIDNcnJLRVx3xhfuEsTDGgH4GsFF91dVhw5nhmnBppafJ7+NWINW6C7ZwWbi30ImJzqWg== +remark-stringify@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-8.0.0.tgz#33423ab8bf3076fb197f4cf582aaaf866b531625" dependencies: ccount "^1.0.0" is-alphanumeric "^1.0.0" @@ -5790,70 +6031,63 @@ remark-stringify@^6.0.0: is-whitespace-character "^1.0.0" longest-streak "^2.0.1" markdown-escapes "^1.0.0" - markdown-table "^1.1.0" - mdast-util-compact "^1.0.0" - parse-entities "^1.0.2" + markdown-table "^2.0.0" + mdast-util-compact "^2.0.0" + parse-entities "^2.0.0" repeat-string "^1.5.4" state-toggle "^1.0.0" - stringify-entities "^1.0.1" + stringify-entities "^3.0.0" unherit "^1.0.4" xtend "^4.0.1" -remark@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/remark/-/remark-10.0.1.tgz#3058076dc41781bf505d8978c291485fe47667df" - integrity sha512-E6lMuoLIy2TyiokHprMjcWNJ5UxfGQjaMSMhV+f4idM625UjjK4j798+gPs5mfjzDE6vL0oFKVeZM6gZVSVrzQ== +remark@^12.0.0: + version "12.0.0" + resolved "https://registry.yarnpkg.com/remark/-/remark-12.0.0.tgz#d1c145c07341c9232f93b2f8539d56da15a2548c" dependencies: - remark-parse "^6.0.0" - remark-stringify "^6.0.0" - unified "^7.0.0" + remark-parse "^8.0.0" + remark-stringify "^8.0.0" + unified "^9.0.0" remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= repeat-element@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== -repeat-string@^1.5.4, repeat-string@^1.6.1: +repeat-string@^1.0.0, repeat-string@^1.5.4, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= replace-ext@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" - integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= + +request-progress@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-3.0.0.tgz#4ca754081c7fec63f505e4faa825aa06cd669dbe" + integrity sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4= + dependencies: + throttleit "^1.0.0" require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - -require-from-string@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" - integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= dependencies: resolve-from "^3.0.0" resolve-dir@^1.0.0, resolve-dir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" - integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= dependencies: expand-tilde "^2.0.0" global-modules "^1.0.0" @@ -5861,31 +6095,32 @@ resolve-dir@^1.0.0, resolve-dir@^1.0.1: resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.7: - version "1.10.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba" - integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg== +resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3.2, resolve@^1.8.1: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" dependencies: path-parse "^1.0.6" -resolve@^1.3.2, resolve@^1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" - integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA== +restore-cursor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" + integrity sha1-NGYfRohjJ/7SmRR5FSJS35LapUE= dependencies: - path-parse "^1.0.5" + exit-hook "^1.0.0" + onetime "^1.0.0" restore-cursor@^2.0.0: version "2.0.0" @@ -5895,131 +6130,153 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" rgb-regex@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" - integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= rgba-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" - integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= -rimraf@2.6.3, rimraf@^2.6.3: +rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== dependencies: glob "^7.1.3" -rimraf@^2.4.4, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" - integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w== +rimraf@^2.5.4, rimraf@^2.6.3, rimraf@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + dependencies: + glob "^7.1.3" + +rimraf@^3.0.0, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" dependencies: - glob "^7.0.5" + glob "^7.1.3" ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== dependencies: hash-base "^3.0.0" inherits "^2.0.1" -run-async@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= +run-async@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.0.tgz#e59054a5b86876cfae07f431d18cbaddc594f1e8" dependencies: is-promise "^2.1.0" +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" - integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= dependencies: aproba "^1.1.1" -rxjs@^6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.4.0.tgz#f3bb0fe7bda7fb69deac0c16f17b50b0b8790504" - integrity sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw== +rxjs@^6.3.3: + version "6.6.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" + integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== dependencies: tslib "^1.9.0" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +rxjs@^6.5.3: + version "6.5.5" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec" + dependencies: + tslib "^1.9.0" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-regex@^1.1.0: version "1.1.0" - resolved "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3": +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sax@^1.2.4, sax@~1.2.4: +sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== schema-utils@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf" - integrity sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8= dependencies: ajv "^5.0.0" schema-utils@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" - integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== dependencies: ajv "^6.1.0" ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1: - version "5.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" - integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== +schema-utils@^2.6.5, schema-utils@^2.6.6: + version "2.6.6" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.6.tgz#299fe6bd4a3365dc23d99fd446caff8f1d6c330c" + dependencies: + ajv "^6.12.0" + ajv-keywords "^3.4.1" -serialize-javascript@^1.4.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.5.0.tgz#1aa336162c88a890ddad5384baebc93a655161fe" - integrity sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ== +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" -set-blocking@^2.0.0, set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= +semver@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" -set-value@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" - integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.1" - to-object-path "^0.3.0" +semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + +serialize-javascript@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" + +serialize-javascript@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-3.0.0.tgz#492e489a2d77b7b804ad391a5f5d97870952548e" -set-value@^2.0.0: +set-blocking@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" - integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -6029,12 +6286,10 @@ set-value@^2.0.0: setimmediate@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" - resolved "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -6042,43 +6297,47 @@ sha.js@^2.4.0, sha.js@^2.4.8: shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= dependencies: shebang-regex "^1.0.0" +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + version "3.0.3" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" simple-swizzle@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= dependencies: is-arrayish "^0.3.1" -slash@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" - integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" -slice-ansi@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" - integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg== - dependencies: - is-fullwidth-code-point "^2.0.0" +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= slice-ansi@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== dependencies: ansi-styles "^3.2.0" astral-regex "^1.0.0" @@ -6087,7 +6346,6 @@ slice-ansi@^2.1.0: snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== dependencies: define-property "^1.0.0" isobject "^3.0.0" @@ -6096,14 +6354,12 @@ snapdragon-node@^2.0.1: snapdragon-util@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== dependencies: kind-of "^3.2.0" snapdragon@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== dependencies: base "^0.11.1" debug "^2.2.0" @@ -6117,31 +6373,20 @@ snapdragon@^0.8.1: source-list-map@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" dependencies: - atob "^2.1.1" + atob "^2.1.2" decode-uri-component "^0.2.0" resolve-url "^0.2.1" source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.5.9, source-map-support@~0.5.6: - version "0.5.9" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" - integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-support@~0.5.10: - version "0.5.11" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.11.tgz#efac2ce0800355d026326a0ca23e162aeac9a4e2" - integrity sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ== +source-map-support@^0.5.16, source-map-support@~0.5.12: + version "0.5.19" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -6149,90 +6394,97 @@ source-map-support@~0.5.10: source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6: +source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== spdx-correct@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.2.tgz#19bb409e91b47b1ad54159243f7312a858db3c2e" - integrity sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ== + version "3.1.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" spdx-expression-parse@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz#a59efc09784c2a5bada13cfeaf5c75dd214044d2" - integrity sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg== + version "3.0.5" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" specificity@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/specificity/-/specificity-0.4.1.tgz#aab5e645012db08ba182e151165738d00887b019" - integrity sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== dependencies: extend-shallow "^3.0.0" sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= -ssri@^6.0.0: +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + 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@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" - integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== dependencies: figgy-pudding "^3.5.1" +ssri@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-7.1.0.tgz#92c241bf6de82365b5c7fb4bd76e975522e1294d" + dependencies: + figgy-pudding "^3.5.1" + minipass "^3.1.1" + stable@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== state-toggle@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.1.tgz#c3cb0974f40a6a0f8e905b96789eb41afa1cde3a" - integrity sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og== + version "1.0.3" + resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= dependencies: define-property "^0.2.5" object-copy "^0.1.0" stream-browserify@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" - integrity sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds= + version "2.0.2" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" dependencies: inherits "~2.0.1" readable-stream "^2.0.2" @@ -6240,7 +6492,6 @@ stream-browserify@^2.0.1: stream-each@^1.1.0: version "1.2.3" resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" - integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== dependencies: end-of-stream "^1.1.0" stream-shift "^1.0.0" @@ -6248,7 +6499,6 @@ stream-each@^1.1.0: stream-http@^2.7.2: version "2.8.3" resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== dependencies: builtin-status-codes "^3.0.0" inherits "^2.0.1" @@ -6257,9 +6507,8 @@ stream-http@^2.7.2: xtend "^4.0.0" stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= + version "1.0.1" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" string-width@^1.0.1: version "1.0.2" @@ -6270,7 +6519,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: +string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -6278,40 +6527,81 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^3.0.0: +string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== dependencies: emoji-regex "^7.0.1" is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string_decoder@^1.0.0, string_decoder@^1.1.1, string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" dependencies: - safe-buffer "~5.1.0" + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +string.prototype.trimend@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string.prototype.trimleft@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz#4408aa2e5d6ddd0c9a80739b087fbc067c03b3cc" + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + string.prototype.trimstart "^1.0.0" + +string.prototype.trimright@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz#c76f1cef30f21bbad8afeb8db1511496cfb0f2a3" + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + string.prototype.trimend "^1.0.0" + +string.prototype.trimstart@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string_decoder@^1.0.0, string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + dependencies: + safe-buffer "~5.2.0" string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= -stringify-entities@^1.0.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-1.3.2.tgz#a98417e5471fd227b3e45d3db1861c11caf668f7" - integrity sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A== +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + dependencies: + safe-buffer "~5.1.0" + +stringify-entities@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-3.0.0.tgz#455abe501f8b7859ba5726a25a8872333c65b0a7" dependencies: character-entities-html4 "^1.0.0" character-entities-legacy "^1.0.0" is-alphanumerical "^1.0.0" + is-decimal "^1.0.2" is-hexadecimal "^1.0.0" strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" - resolved "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= dependencies: ansi-regex "^2.0.0" @@ -6323,130 +6613,145 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^5.0.0, strip-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.1.0.tgz#55aaa54e33b4c0649a7338a43437b1887d153ec4" - integrity sha512-TjxrkPONqO2Z8QDCpeE2j6n0M6EwxzyDgzEeGp+FbdvaJAt//ClYi6W5my+3ROlC/hZX2KACUwDfK49Ka5eDvg== +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + dependencies: + ansi-regex "^5.0.0" + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= strip-eof@^1.0.0: version "1.0.0" - resolved "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" -strip-indent@^2.0.0: +strip-final-newline@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" - integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== -strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + dependencies: + min-indent "^1.0.0" + +strip-json-comments@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.0.tgz#7638d31422129ecf4457440009fba03f9f9ac180" style-search@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902" - integrity sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI= stylehacks@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" - integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== dependencies: browserslist "^4.0.0" postcss "^7.0.0" postcss-selector-parser "^3.0.0" -stylelint@^9.10.1: - version "9.10.1" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-9.10.1.tgz#5f0ee3701461dff1d68284e1386efe8f0677a75d" - integrity sha512-9UiHxZhOAHEgeQ7oLGwrwoDR8vclBKlSX7r4fH0iuu0SfPwFaLkb1c7Q2j1cqg9P7IDXeAV2TvQML/fRQzGBBQ== +stylelint@^13.3.3: + version "13.3.3" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-13.3.3.tgz#e267a628ebfc1adad6f5a1fe818724c34171402b" dependencies: - autoprefixer "^9.0.0" + "@stylelint/postcss-css-in-js" "^0.37.1" + "@stylelint/postcss-markdown" "^0.36.1" + autoprefixer "^9.7.6" balanced-match "^1.0.0" - chalk "^2.4.1" - cosmiconfig "^5.0.0" - debug "^4.0.0" - execall "^1.0.0" - file-entry-cache "^4.0.0" - get-stdin "^6.0.0" + chalk "^4.0.0" + cosmiconfig "^6.0.0" + debug "^4.1.1" + execall "^2.0.0" + file-entry-cache "^5.0.1" + get-stdin "^7.0.0" global-modules "^2.0.0" - globby "^9.0.0" + globby "^11.0.0" globjoin "^0.1.4" - html-tags "^2.0.0" - ignore "^5.0.4" - import-lazy "^3.1.0" + html-tags "^3.1.0" + ignore "^5.1.4" + import-lazy "^4.0.0" imurmurhash "^0.1.4" - known-css-properties "^0.11.0" - leven "^2.1.0" - lodash "^4.17.4" - log-symbols "^2.0.0" - mathml-tag-names "^2.0.1" - meow "^5.0.0" - micromatch "^3.1.10" + known-css-properties "^0.18.0" + leven "^3.1.0" + lodash "^4.17.15" + log-symbols "^3.0.0" + mathml-tag-names "^2.1.3" + meow "^6.1.0" + micromatch "^4.0.2" normalize-selector "^0.2.0" - pify "^4.0.0" - postcss "^7.0.13" + postcss "^7.0.27" postcss-html "^0.36.0" - postcss-jsx "^0.36.0" - postcss-less "^3.1.0" - postcss-markdown "^0.36.0" + postcss-less "^3.1.4" postcss-media-query-parser "^0.2.3" - postcss-reporter "^6.0.0" + postcss-reporter "^6.0.1" postcss-resolve-nested-selector "^0.1.1" - postcss-safe-parser "^4.0.0" - postcss-sass "^0.3.5" + postcss-safe-parser "^4.0.2" + postcss-sass "^0.4.4" postcss-scss "^2.0.0" - postcss-selector-parser "^3.1.0" + postcss-selector-parser "^6.0.2" postcss-syntax "^0.36.2" - postcss-value-parser "^3.3.0" - resolve-from "^4.0.0" - signal-exit "^3.0.2" - slash "^2.0.0" + postcss-value-parser "^4.0.3" + resolve-from "^5.0.0" + slash "^3.0.0" specificity "^0.4.1" - string-width "^3.0.0" + string-width "^4.2.0" + strip-ansi "^6.0.0" style-search "^0.1.0" sugarss "^2.0.0" svg-tags "^1.0.0" - table "^5.0.0" + table "^5.4.6" + v8-compile-cache "^2.1.0" + write-file-atomic "^3.0.3" sugarss@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d" - integrity sha512-WfxjozUk0UVA4jm+U1d736AUpzSrNsQcIbyOkoE364GrtWmIrFdk5lksEupgWMD4VaT/0kVx1dobpiDumSgmJQ== dependencies: postcss "^7.0.2" +supports-color@6.1.0, supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + dependencies: + has-flag "^3.0.0" + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= -supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0: +supports-color@^5.3.0, supports-color@^5.4.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" -supports-color@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" - integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== +supports-color@^7.0.0, supports-color@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" dependencies: - has-flag "^3.0.0" + has-flag "^4.0.0" + +supports-color@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" svg-sprite-generator@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/svg-sprite-generator/-/svg-sprite-generator-0.0.7.tgz#159777ce3e83e800f255cedd311da761492163e9" - integrity sha1-FZd3zj6D6ADyVc7dMR2nYUkhY+k= dependencies: async "^1.3.0" cheerio "^0.19.0" @@ -6456,21 +6761,18 @@ svg-sprite-generator@^0.0.7: svg-tags@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" - integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= svgo@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.2.0.tgz#305a8fc0f4f9710828c65039bb93d5793225ffc3" - integrity sha512-xBfxJxfk4UeVN8asec9jNxHiv3UAMv/ujwBWGYvQhhMb2u3YTGKkiybPcLFDLq7GLLWE9wa73e0/m8L5nTzQbw== + version "1.3.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" dependencies: chalk "^2.4.1" coa "^2.0.2" css-select "^2.0.0" css-select-base-adapter "^0.1.1" - css-tree "1.0.0-alpha.28" - css-url-regex "^1.1.0" - csso "^3.5.1" - js-yaml "^3.12.0" + css-tree "1.0.0-alpha.37" + csso "^4.0.2" + js-yaml "^3.13.1" mkdirp "~0.5.1" object.values "^1.1.0" sax "~1.2.4" @@ -6478,413 +6780,400 @@ svgo@^1.0.0: unquote "~1.1.1" util.promisify "~1.0.0" -table@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/table/-/table-5.1.0.tgz#69a54644f6f01ad1628f8178715b408dc6bf11f7" - integrity sha512-e542in22ZLhD/fOIuXs/8yDZ9W61ltF8daM88rkRNtgTIct+vI2fTnAyu/Db2TCfEcI8i7mjZz6meLq0nW7TYg== - dependencies: - ajv "^6.5.3" - lodash "^4.17.10" - slice-ansi "1.0.0" - string-width "^2.1.1" +symbol-observable@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" + integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== -table@^5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/table/-/table-5.2.3.tgz#cde0cc6eb06751c009efab27e8c820ca5b67b7f2" - integrity sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ== +table@^5.2.3, table@^5.4.6: + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" dependencies: - ajv "^6.9.1" - lodash "^4.17.11" + ajv "^6.10.2" + lodash "^4.17.14" slice-ansi "^2.1.0" string-width "^3.0.0" -tapable@^1.0.0, tapable@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.0.tgz#0d076a172e3d9ba088fd2272b2668fb8d194b78c" - integrity sha512-IlqtmLVaZA2qab8epUXbVWRn3aB1imbDMJtjB3nu4X0NqPkcY/JH9ZtCBWKHWPxs8Svi9tyo8w2dBoi07qZbBA== - -tar@^4: - version "4.4.7" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.7.tgz#14df45023ffdcd0c233befa2fc01ebb76ee39e7c" - integrity sha512-mR3MzsCdN0IEWjZRuF/J9gaWHnTwOvzjqPTcvi1xXgfKTDQRp39gRETPQEfPByAdEOGmZfx1HrRsn8estaEvtA== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.3.4" - minizlib "^1.1.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.2" +tapable@^1.0.0, tapable@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" -terser-webpack-plugin@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.1.0.tgz#cf7c25a1eee25bf121f4a587bb9e004e3f80e528" - integrity sha512-61lV0DSxMAZ8AyZG7/A4a3UPlrbOBo8NIQ4tJzLPAdGOQ+yoNC7l5ijEow27lBAL2humer01KLS6bGIMYQxKoA== +terser-webpack-plugin@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c" dependencies: - cacache "^11.0.2" - find-cache-dir "^2.0.0" + cacache "^12.0.2" + find-cache-dir "^2.1.0" + is-wsl "^1.1.0" schema-utils "^1.0.0" - serialize-javascript "^1.4.0" + serialize-javascript "^2.1.2" source-map "^0.6.1" - terser "^3.8.1" - webpack-sources "^1.1.0" - worker-farm "^1.5.2" + terser "^4.1.2" + webpack-sources "^1.4.0" + worker-farm "^1.7.0" -terser-webpack-plugin@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.2.3.tgz#3f98bc902fac3e5d0de730869f50668561262ec8" - integrity sha512-GOK7q85oAb/5kE12fMuLdn2btOS9OBZn4VsecpHDywoUC/jLhSAKOiYo0ezx7ss2EXPMzyEWFoE0s1WLE+4+oA== - dependencies: - cacache "^11.0.2" - find-cache-dir "^2.0.0" - schema-utils "^1.0.0" - serialize-javascript "^1.4.0" +terser-webpack-plugin@^2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.6.tgz#a4014b311a61f87c6a1b217ef4f5a75bd0665a69" + dependencies: + cacache "^13.0.1" + find-cache-dir "^3.3.1" + jest-worker "^25.4.0" + p-limit "^2.3.0" + schema-utils "^2.6.6" + serialize-javascript "^3.0.0" source-map "^0.6.1" - terser "^3.16.1" - webpack-sources "^1.1.0" - worker-farm "^1.5.2" - -terser@^3.16.1: - version "3.17.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-3.17.0.tgz#f88ffbeda0deb5637f9d24b0da66f4e15ab10cb2" - integrity sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ== - dependencies: - commander "^2.19.0" - source-map "~0.6.1" - source-map-support "~0.5.10" + terser "^4.6.12" + webpack-sources "^1.4.3" -terser@^3.8.1: - version "3.11.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-3.11.0.tgz#60782893e1f4d6788acc696351f40636d0e37af0" - integrity sha512-5iLMdhEPIq3zFWskpmbzmKwMQixKmTYwY3Ox9pjtSklBLnHiuQ0GKJLhL1HSYtyffHM3/lDIFBnb82m9D7ewwQ== +terser@^4.1.2, terser@^4.6.12: + version "4.6.12" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.12.tgz#44b98aef8703fdb09a3491bf79b43faffc5b4fee" dependencies: - commander "~2.17.1" + commander "^2.20.0" source-map "~0.6.1" - source-map-support "~0.5.6" + source-map-support "~0.5.12" text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +throttleit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c" + integrity sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw= through2@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.4.tgz#e8362dec238b7590f5743b060342f27b452f4450" - integrity sha512-q030OX7royN1Bo549nYMOpKwiGJIzUppv10IgB6ALN6DiJ/XgsRIehiz18x5RWCA3+s4G6ovKqtzgU+pYhjvvg== + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" dependencies: - readable-stream "2 || 3" + readable-stream "~2.3.6" xtend "~4.0.1" through@^2.3.6: version "2.3.8" - resolved "http://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" timers-browserify@^2.0.4: - version "2.0.10" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" - integrity sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg== + version "2.0.11" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" dependencies: setimmediate "^1.0.4" timsort@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" - integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" +tmp@~0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" + to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= dependencies: kind-of "^3.0.2" to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= dependencies: is-number "^3.0.0" repeat-string "^1.6.1" +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + dependencies: + is-number "^7.0.0" + to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== dependencies: define-property "^2.0.2" extend-shallow "^3.0.2" regex-not "^1.0.2" safe-regex "^1.1.0" -trim-newlines@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" - integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA= +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= +trim-newlines@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.0.tgz#79726304a6a898aa8373427298d54c2ee8b1cb30" trim-trailing-lines@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz#e0ec0810fd3c3f1730516b45f49083caaf2774d9" - integrity sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg== + version "1.1.3" + resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.3.tgz#7f0739881ff76657b7776e10874128004b625a94" trim@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" - integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= trough@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.3.tgz#e29bd1614c6458d44869fc28b255ab7857ef7c24" - integrity sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw== + version "1.0.5" + resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" -ts-loader@^5.3.3: - version "5.3.3" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-5.3.3.tgz#8b4af042e773132d86b3c99ef0acf3b4d325f473" - integrity sha512-KwF1SplmOJepnoZ4eRIloH/zXL195F51skt7reEsS6jvDqzgc/YSbz9b8E07GxIUwLXdcD4ssrJu6v8CwaTafA== +ts-loader@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-7.0.1.tgz#ac9ae9eb8f5ebd0aa7b78b44db20691b6e31251b" dependencies: chalk "^2.3.0" enhanced-resolve "^4.0.0" loader-utils "^1.0.2" - micromatch "^3.1.4" - semver "^5.0.1" - -tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" - integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== + micromatch "^4.0.0" + semver "^6.0.0" -tslint-loader@^3.5.4: - version "3.5.4" - resolved "https://registry.yarnpkg.com/tslint-loader/-/tslint-loader-3.5.4.tgz#052af7f0772434451ea1b247bb55407f878a4c40" - integrity sha512-jBHNNppXut6SgZ7CsTBh+6oMwVum9n8azbmcYSeMlsABhWWoHwjq631vIFXef3VSd75cCdX3rc6kstsB7rSVVw== - dependencies: - loader-utils "^1.0.2" - mkdirp "^0.5.1" - object-assign "^4.1.1" - rimraf "^2.4.4" - semver "^5.3.0" +tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0: + version "1.11.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" -tslint@^5.14.0: - version "5.14.0" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.14.0.tgz#be62637135ac244fc9b37ed6ea5252c9eba1616e" - integrity sha512-IUla/ieHVnB8Le7LdQFRGlVJid2T/gaJe5VkjzRVSRR6pA2ODYrnfR1hmxi+5+au9l50jBwpbBL34txgv4NnTQ== +tslint@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.1.tgz#ac03fbd17f85bfefaae348b353b25a88efe10cde" dependencies: - babel-code-frame "^6.22.0" + "@babel/code-frame" "^7.0.0" builtin-modules "^1.1.1" chalk "^2.3.0" commander "^2.12.1" - diff "^3.2.0" + diff "^4.0.1" glob "^7.1.1" - js-yaml "^3.7.0" + js-yaml "^3.13.1" minimatch "^3.0.4" - mkdirp "^0.5.1" + mkdirp "^0.5.3" resolve "^1.3.2" semver "^5.3.0" - tslib "^1.8.0" + tslib "^1.10.0" tsutils "^2.29.0" tsutils@^2.29.0: version "2.29.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" - integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== + dependencies: + tslib "^1.8.1" + +tsutils@^3.17.1: + version "3.17.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" dependencies: tslib "^1.8.1" tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= dependencies: prelude-ls "~1.1.2" +type-fest@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" + +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + dependencies: + is-typedarray "^1.0.0" + typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^3.3.3333: - version "3.3.3333" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.3.3333.tgz#171b2c5af66c59e9431199117a3bcadc66fdcfd6" - integrity sha512-JjSKsAfuHBE/fB2oZ8NxtRTk5iGcg6hkYXMnZ3Wc+b2RSqejEqTaem11mHASMnFilHrax3sLK0GDzcJrekZYLw== +typescript@3.8.3, typescript@^3.7.3: + version "3.8.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061" unherit@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.1.tgz#132748da3e88eab767e08fabfbb89c5e9d28628c" - integrity sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g== + version "1.1.3" + resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.3.tgz#6c9b503f2b41b262330c80e91c8614abdaa69c22" dependencies: - inherits "^2.0.1" - xtend "^4.0.1" + inherits "^2.0.0" + xtend "^4.0.0" unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" - integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== unicode-match-property-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" - integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== dependencies: unicode-canonical-property-names-ecmascript "^1.0.4" unicode-property-aliases-ecmascript "^1.0.4" -unicode-match-property-value-ecmascript@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz#9f1dc76926d6ccf452310564fd834ace059663d4" - integrity sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ== +unicode-match-property-value-ecmascript@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" unicode-property-aliases-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz#5a533f31b4317ea76f17d807fa0d116546111dd0" - integrity sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg== + version "1.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" -unified@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/unified/-/unified-7.1.0.tgz#5032f1c1ee3364bd09da12e27fdd4a7553c7be13" - integrity sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw== +unified@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/unified/-/unified-9.0.0.tgz#12b099f97ee8b36792dbad13d278ee2f696eed1d" dependencies: - "@types/unist" "^2.0.0" - "@types/vfile" "^3.0.0" bail "^1.0.0" extend "^3.0.0" - is-plain-obj "^1.1.0" + is-buffer "^2.0.0" + is-plain-obj "^2.0.0" trough "^1.0.0" - vfile "^3.0.0" - x-is-string "^0.1.0" + vfile "^4.0.0" union-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" - integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" dependencies: arr-union "^3.1.0" get-value "^2.0.6" is-extendable "^0.1.1" - set-value "^0.4.3" + set-value "^2.0.1" uniq@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= uniqs@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" - integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= -unique-filename@^1.1.0: +unique-filename@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" - integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== dependencies: unique-slug "^2.0.0" unique-slug@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.1.tgz#5e9edc6d1ce8fb264db18a507ef9bd8544451ca6" - integrity sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg== + version "2.0.2" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" dependencies: imurmurhash "^0.1.4" -unist-util-find-all-after@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unist-util-find-all-after/-/unist-util-find-all-after-1.0.2.tgz#9be49cfbae5ca1566b27536670a92836bf2f8d6d" - integrity sha512-nDl79mKpffXojLpCimVXnxhlH/jjaTnDuScznU9J4jjsaUtBdDbxmlc109XtcqxY4SDO0SwzngsxxW8DIISt1w== +unist-util-find-all-after@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/unist-util-find-all-after/-/unist-util-find-all-after-3.0.1.tgz#95cc62f48812d879b4685a0512bf1b838da50e9a" dependencies: - unist-util-is "^2.0.0" + unist-util-is "^4.0.0" -unist-util-is@^2.0.0, unist-util-is@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-2.1.2.tgz#1193fa8f2bfbbb82150633f3a8d2eb9a1c1d55db" - integrity sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw== +unist-util-is@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.0.2.tgz#c7d1341188aa9ce5b3cff538958de9895f14a5de" -unist-util-remove-position@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz#86b5dad104d0bbfbeb1db5f5c92f3570575c12cb" - integrity sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q== +unist-util-remove-position@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz#5d19ca79fdba712301999b2b73553ca8f3b352cc" dependencies: - unist-util-visit "^1.1.0" + unist-util-visit "^2.0.0" -unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6" - integrity sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ== +unist-util-stringify-position@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" + dependencies: + "@types/unist" "^2.0.2" -unist-util-visit-parents@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz#63fffc8929027bee04bfef7d2cce474f71cb6217" - integrity sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA== +unist-util-visit-parents@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz#d4076af3011739c71d2ce99d05de37d545f4351d" dependencies: - unist-util-is "^2.1.2" + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" -unist-util-visit@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.0.tgz#1cb763647186dc26f5e1df5db6bd1e48b3cc2fb1" - integrity sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw== +unist-util-visit@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.2.tgz#3843782a517de3d2357b4c193b24af2d9366afb7" dependencies: - unist-util-visit-parents "^2.0.0" + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + unist-util-visit-parents "^3.0.0" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + +universalify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d" + integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug== unquote@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" - integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= dependencies: has-value "^0.3.1" isobject "^3.0.0" -upath@^1.0.5: - version "1.1.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" - integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== +untildify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" + integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== + +upath@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== dependencies: punycode "^2.1.0" urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= url@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= dependencies: punycode "1.3.2" querystring "0.2.0" @@ -6892,251 +7181,267 @@ url@^0.11.0: use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= -util.promisify@^1.0.0, util.promisify@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" - integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== +util.promisify@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" dependencies: - define-properties "^1.1.2" - object.getownpropertydescriptors "^2.0.3" + define-properties "^1.1.3" + es-abstract "^1.17.2" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.0" util@0.10.3: version "0.10.3" - resolved "http://registry.npmjs.org/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" dependencies: inherits "2.0.1" -util@^0.10.3: - version "0.10.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" - integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== +util@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" dependencies: inherits "2.0.3" -v8-compile-cache@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz#a428b28bb26790734c4fc8bc9fa106fccebf6a6c" - integrity sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw== +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +v8-compile-cache@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe" + +v8-compile-cache@^2.0.3, v8-compile-cache@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== dependencies: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" vendors@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.2.tgz#7fcb5eef9f5623b156bcea89ec37d63676f21801" - integrity sha512-w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ== - -vfile-location@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.3.tgz#083ba80e50968e8d420be49dd1ea9a992131df77" - integrity sha512-zM5/l4lfw1CBoPx3Jimxoc5RNDAHHpk6AM6LM0pTIkm5SUSsx8ZekZ0PVdf0WEZ7kjlhSt7ZlqbRL6Cd6dBs6A== + version "1.0.4" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" -vfile-message@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.0.1.tgz#51a2ccd8a6b97a7980bb34efb9ebde9632e93677" - integrity sha512-vSGCkhNvJzO6VcWC6AlJW4NtYOVtS+RgCaqFIYUjoGIlHnFL+i0LbtYvonDWOMcB97uTPT4PRsyYY7REWC9vug== +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= dependencies: - unist-util-stringify-position "^1.1.1" + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" -vfile@^3.0.0: +vfile-location@^3.0.0: version "3.0.1" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-3.0.1.tgz#47331d2abe3282424f4a4bb6acd20a44c4121803" - integrity sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ== + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-3.0.1.tgz#d78677c3546de0f7cd977544c367266764d31bb3" + +vfile-message@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a" dependencies: + "@types/unist" "^2.0.0" + unist-util-stringify-position "^2.0.0" + +vfile@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.1.0.tgz#d79248957f43225d57ff67a56effc67bef08946e" + dependencies: + "@types/unist" "^2.0.0" is-buffer "^2.0.0" replace-ext "1.0.0" - unist-util-stringify-position "^1.0.0" - vfile-message "^1.0.0" + unist-util-stringify-position "^2.0.0" + vfile-message "^2.0.0" -vm-browserify@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" - integrity sha1-XX6kW7755Kb/ZflUOOCofDV9WnM= - dependencies: - indexof "0.0.1" +vm-browserify@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" -watchpack@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" - integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== +watchpack@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.1.tgz#280da0a8718592174010c078c7585a74cd8cd0e2" dependencies: - chokidar "^2.0.2" + chokidar "^2.1.8" graceful-fs "^4.1.2" neo-async "^2.5.0" -webpack-cli@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.2.3.tgz#13653549adfd8ccd920ad7be1ef868bacc22e346" - integrity sha512-Ik3SjV6uJtWIAN5jp5ZuBMWEAaP5E4V78XJ2nI+paFPh8v4HPSwo/myN0r29Xc/6ZKnd2IdrAlpSgNOu2CDQ6Q== - dependencies: - chalk "^2.4.1" - cross-spawn "^6.0.5" - enhanced-resolve "^4.1.0" - findup-sync "^2.0.0" - global-modules "^1.0.0" - import-local "^2.0.0" - interpret "^1.1.0" - loader-utils "^1.1.0" - supports-color "^5.5.0" - v8-compile-cache "^2.0.2" - yargs "^12.0.4" - -webpack-sources@^1.0.1, webpack-sources@^1.1.0, webpack-sources@^1.2.0, webpack-sources@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85" - integrity sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA== +webpack-cli@^3.3.11: + version "3.3.11" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.11.tgz#3bf21889bf597b5d82c38f215135a411edfdc631" + dependencies: + chalk "2.4.2" + cross-spawn "6.0.5" + enhanced-resolve "4.1.0" + findup-sync "3.0.0" + global-modules "2.0.0" + import-local "2.0.0" + interpret "1.2.0" + loader-utils "1.2.3" + supports-color "6.1.0" + v8-compile-cache "2.0.3" + yargs "13.2.4" + +webpack-sources@^1.0.1, webpack-sources@^1.2.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" dependencies: source-list-map "^2.0.0" source-map "~0.6.1" -webpack@^4.29.6: - version "4.29.6" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.29.6.tgz#66bf0ec8beee4d469f8b598d3988ff9d8d90e955" - integrity sha512-MwBwpiE1BQpMDkbnUUaW6K8RFZjljJHArC6tWQJoFm0oQtfoSebtg4Y7/QHnJ/SddtjYLHaKGX64CFjG5rehJw== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-module-context" "1.8.5" - "@webassemblyjs/wasm-edit" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" - acorn "^6.0.5" - acorn-dynamic-import "^4.0.0" - ajv "^6.1.0" - ajv-keywords "^3.1.0" - chrome-trace-event "^1.0.0" +webpack@^4.43.0: + version "4.43.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.43.0.tgz#c48547b11d563224c561dad1172c8aa0b8a678e6" + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/wasm-edit" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + acorn "^6.4.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" + chrome-trace-event "^1.0.2" enhanced-resolve "^4.1.0" - eslint-scope "^4.0.0" + eslint-scope "^4.0.3" json-parse-better-errors "^1.0.2" - loader-runner "^2.3.0" - loader-utils "^1.1.0" - memory-fs "~0.4.1" - micromatch "^3.1.8" - mkdirp "~0.5.0" - neo-async "^2.5.0" - node-libs-browser "^2.0.0" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.3" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" schema-utils "^1.0.0" - tapable "^1.1.0" - terser-webpack-plugin "^1.1.0" - watchpack "^1.5.0" - webpack-sources "^1.3.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.3" + watchpack "^1.6.1" + webpack-sources "^1.4.1" which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= which@^1.2.14, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: - string-width "^1.0.2 || 2" + isexe "^2.0.0" -wordwrap@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= +word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" -worker-farm@^1.5.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.6.0.tgz#aecc405976fab5a95526180846f0dba288f3a4a0" - integrity sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ== +worker-farm@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" dependencies: errno "~0.1.7" -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= +wrap-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba" + integrity sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo= dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" + string-width "^2.1.1" + strip-ansi "^4.0.0" + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write-file-atomic@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" write@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== dependencies: mkdirp "^0.5.1" -x-is-string@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" - integrity sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI= - xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" -"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: +y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" -yallist@^3.0.0, yallist@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" - integrity sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k= +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" -yargs-parser@^10.0.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" - integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== +yaml@^1.7.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.9.2.tgz#f0cfa865f003ab707663e4f04b3956957ea564ed" dependencies: - camelcase "^4.1.0" + "@babel/runtime" "^7.9.2" -yargs-parser@^11.1.1: - version "11.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" - integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ== +yargs-parser@^13.1.0: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" dependencies: camelcase "^5.0.0" decamelize "^1.2.0" -yargs@^12.0.4: - version "12.0.5" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" - integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== +yargs-parser@^18.1.1: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" dependencies: - cliui "^4.0.0" + camelcase "^5.0.0" decamelize "^1.2.0" + +yargs@13.2.4: + version "13.2.4" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" + dependencies: + cliui "^5.0.0" find-up "^3.0.0" - get-caller-file "^1.0.1" - os-locale "^3.0.0" + get-caller-file "^2.0.1" + os-locale "^3.1.0" require-directory "^2.1.1" - require-main-filename "^1.0.1" + require-main-filename "^2.0.0" set-blocking "^2.0.0" - string-width "^2.0.0" + string-width "^3.0.0" which-module "^2.0.0" - y18n "^3.2.1 || ^4.0.0" - yargs-parser "^11.1.1" + y18n "^4.0.0" + yargs-parser "^13.1.0" + +yauzl@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0"