├── .eslintrc.json ├── .gitignore ├── .travis.yml ├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── tasks.json ├── .vscodeignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── coverconfig.json ├── doc ├── navigation.gif ├── sample.gif └── table-mode-status.png ├── e2e └── e2e.code-workspace ├── icons └── icon.png ├── package-lock.json ├── package.json ├── src ├── commands.ts ├── configuration.ts ├── context.ts ├── extension.ts ├── ttMarkdown.ts ├── ttOrg.ts ├── ttTable.ts └── utils.ts ├── test ├── commands.test.ts ├── index.ts ├── runTest.ts ├── table-navigator.test.ts ├── ttMarkdown.test.ts ├── ttOrg.test.ts └── ttTable.test.ts └── tsconfig.json /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "parserOptions": { 5 | "ecmaVersion": 6, 6 | "sourceType": "module" 7 | }, 8 | "plugins": [ 9 | "@typescript-eslint" 10 | ], 11 | "rules": { 12 | "@typescript-eslint/class-name-casing": "warn", 13 | "@typescript-eslint/semi": "warn", 14 | "brace-style": "error", 15 | "curly": ["error", "all"], 16 | "eqeqeq": "warn", 17 | "no-throw-literal": "warn", 18 | "quotes": ["error", "single"], 19 | "semi": "error" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | node_modules 3 | .vscode-test/ 4 | *.vsix 5 | 6 | .DS_Store 7 | coverage/ 8 | e2e/* 9 | !e2e/e2e.code-workspace 10 | 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | os: 3 | - osx 4 | - linux 5 | node_js: 10 6 | 7 | install: 8 | - | 9 | if [ $TRAVIS_OS_NAME == "linux" ]; then 10 | export DISPLAY=':99.0' 11 | /usr/bin/Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & 12 | fi 13 | 14 | script: 15 | - npm install 16 | - npm run vscode:prepublish 17 | - npm run lint 18 | - npm test --silent 19 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "eg2.tslint" 6 | ] 7 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "runtimeExecutable": "${execPath}", 13 | "args": [ 14 | "--extensionDevelopmentPath=${workspaceFolder}" 15 | ], 16 | "outFiles": [ 17 | "${workspaceFolder}/out/**/*.js" 18 | ], 19 | "preLaunchTask": "npm: watch" 20 | }, 21 | { 22 | "name": "Extension Tests", 23 | "type": "extensionHost", 24 | "request": "launch", 25 | "runtimeExecutable": "${execPath}", 26 | "args": [ 27 | "--extensionDevelopmentPath=${workspaceFolder}", 28 | "--extensionTestsPath=${workspaceFolder}/out/test" 29 | ], 30 | "outFiles": [ 31 | "${workspaceFolder}/out/test/**/*.js" 32 | ], 33 | "preLaunchTask": "npm: watch" 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "out": false // set this to true to hide the "out" folder with the compiled JS files 5 | }, 6 | "search.exclude": { 7 | "out": true // set this to false to include "out" folder in search results 8 | }, 9 | "markdownlint.config": { 10 | "MD013": false, 11 | "MD024": false 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "watch", 9 | "problemMatcher": "$tsc-watch", 10 | "isBackground": true, 11 | "presentation": { 12 | "reveal": "never" 13 | }, 14 | "group": { 15 | "kind": "build", 16 | "isDefault": true 17 | } 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | out/test/** 4 | out/**/*.map 5 | src/** 6 | .gitignore 7 | tsconfig.json 8 | vsc-extension-quickstart.md 9 | tslint.json -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 6 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ### Changed 11 | 12 | - Fixed tests when run from command line. 13 | 14 | ## [0.1.5] - 2018-05-03 15 | 16 | ### Added 17 | 18 | - Command `text-tables.nextRow` (`Text Tables: Next row` in command pallete) for jumping on next row and creating new rows if needed. 19 | 20 | ### Changed 21 | 22 | - Command `text-tables.gotoNextCell` (`Text Tables: Go to next cell` in command pallete) inserts new row when applied in last data cell of table. 23 | - Fixed markdown parser for tables with separator row where separator row has less columns than other row (#33). 24 | 25 | ## [0.1.0] - 2018-04-16 26 | 27 | ### Changed 28 | 29 | - Codebase refactor. 30 | - Preview status removed from extension. 31 | 32 | ## [0.0.9] - 2018-04-14 33 | 34 | ### Added 35 | 36 | - Command `Move row down` to move row down in table mode. 37 | - Command `Move row up` to move row up in table mode. 38 | - Command `Move column right` to move column right in table mode. 39 | - Command `Move column left` to move column left in table mode. 40 | 41 | ## [0.0.8] - 2018-04-14 42 | 43 | ### Changed 44 | 45 | - Fixed `Create table` command for markdown (#24). 46 | 47 | ## [0.0.7] - 2018-04-13 48 | 49 | ### Changed 50 | 51 | - Table mode made local to editor (#22). 52 | 53 | ## [0.0.6] - 2018-04-12 54 | 55 | ### Changed 56 | 57 | - Shortcuts readme update 58 | 59 | ## [0.0.5] - 2018-04-12 60 | 61 | ### Added 62 | 63 | - Command `text-tables.enable` (`Text Tables: Enable` in command pallete) for activating extension in any file. 64 | - Command `text-tables.clearCell` (`Text Tables: Clear cell` in command pallete) for clearing cell under cursor. 65 | 66 | ## [0.0.4] - 2018-04-11 67 | 68 | ### Added 69 | 70 | - Setting `text-tables.showStatus` to control whether status item for mode should be visible. 71 | 72 | ## [0.0.3] - 2018-04-07 73 | 74 | ### Changed 75 | 76 | - Navigation now via `Tab` and `Shift`+`Tab` skips separator rows 77 | 78 | ## [0.0.2] - 2018-04-05 79 | 80 | ### Added 81 | 82 | - `Create table` command. 83 | 84 | ### Changed 85 | 86 | - Linting settings. 87 | - Readme file updated with additional badges. 88 | 89 | ## [0.0.1] - 2018-03-24 90 | 91 | - Initial release 92 | 93 | [Unreleased]: https://github.com/rpeshkov/vscode-text-tables/compare/v0.1.5...HEAD 94 | [0.1.5]: https://github.com/rpeshkov/vscode-text-tables/compare/v0.1.0...v0.1.5 95 | [0.1.0]: https://github.com/rpeshkov/vscode-text-tables/compare/v0.0.9...v0.1.0 96 | [0.0.9]: https://github.com/rpeshkov/vscode-text-tables/compare/v0.0.8...v0.0.9 97 | [0.0.8]: https://github.com/rpeshkov/vscode-text-tables/compare/v0.0.7...v0.0.8 98 | [0.0.7]: https://github.com/rpeshkov/vscode-text-tables/compare/v0.0.6...v0.0.7 99 | [0.0.6]: https://github.com/rpeshkov/vscode-text-tables/compare/v0.0.5...v0.0.6 100 | [0.0.5]: https://github.com/rpeshkov/vscode-text-tables/compare/v0.0.4...v0.0.5 101 | [0.0.4]: https://github.com/rpeshkov/vscode-text-tables/compare/v0.0.3...v0.0.4 102 | [0.0.3]: https://github.com/rpeshkov/vscode-text-tables/compare/v0.0.2...v0.0.3 103 | [0.0.2]: https://github.com/rpeshkov/vscode-text-tables/compare/v0.0.1...v0.0.2 104 | [0.0.1]: https://github.com/rpeshkov/vscode-text-tables/releases/tag/v0.0.1 105 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | 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, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | 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. 28 | 29 | 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. 30 | 31 | ## Scope 32 | 33 | 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. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at peshkovroman@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems 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. 38 | 39 | 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. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute to Text Tables 2 | 3 | ## Reporting issues 4 | 5 | In case if you want to report about some issue in functionality of extension or propose new feature, please follow this simple rules: 6 | 7 | * **Ensure that the issue was not raised before** by searching on GitHub in [Issues][issues]. If you found already existing issue, make relevant comments or add your reaction to the issue. 8 | 9 | * **Provide clear information about the issue** by filling following fields: 10 | 11 | * VSCode version 12 | * Text tables extension version 13 | * Information about other extensions installed 14 | * Reproducible steps that cause the issue 15 | * What you expected to see and what you saw instead 16 | 17 | ## Providing patches 18 | 19 | * In case if you want to fix specific issue, **be sure that the issue was assigned to you**. In that case there won't be confusions that 2 or more different people were working on the issue. 20 | 21 | * **Don't provide cosmetic patches** without opening an issue prior to this. If there won't be referenced issue, pull request will be rejected. 22 | 23 | **Thank you!** 24 | 25 | [issues]: https://github.com/rpeshkov/text-tables/issues/ 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Roman Peshkov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Text Tables 2 | 3 | [![version][version-badge]][CHANGELOG] 4 | [![license][license-badge]][LICENSE] 5 | [![Build Status](https://travis-ci.org/rpeshkov/vscode-text-tables.svg?branch=master)](https://travis-ci.org/rpeshkov/vscode-text-tables) 6 | 7 | ![Text tables](icons/icon.png) 8 | 9 | VSCode extension that brings the power of Emacs table editing. 10 | 11 | ![Sample](doc/sample.gif) 12 | 13 | ## Features 14 | 15 | - Tables reformat 16 | - Easy table cells navigation 17 | - Support for [org](https://orgmode.org/manual/Built_002din-table-editor.html#Built_002din-table-editor) and [markdown](https://help.github.com/articles/organizing-information-with-tables/) tables 18 | 19 | ## Activation 20 | 21 | Extension is automatically activated when you open markdown or org file. If you want to use this extension in any other file, just trigger `Text Tables: Enable` command in command pallete. 22 | 23 | ## Commands 24 | 25 | Extension provides several commands that are available in the Command Palette: 26 | 27 | - `Text Tables: Enable` - enable extension. 28 | - `Text Tables: Create table` - create new table in cursor position. 29 | - `Text Tables: Format under cursor` - reformat the table under cursor. 30 | - `Text Tables: Enter table mode` - enter [table mode](#table-mode). 31 | - `Text Tables: Exit table mode` - exit [table mode](#table-mode). 32 | - `Text Tables: Go to next cell` - switch to next cell in current table. 33 | - `Text Tables: Go to previous cell` - switch to previous cell in current table. 34 | - `Text Tables: Clear cell` - clear cell under cursor. 35 | 36 | You can access all of the above commands from the command pallete (Ctrl+Shift+p or Cmd+Shift+p) 37 | 38 | ## Table mode 39 | 40 | Table mode is the mode where some of the default keybindings have another action assigned. 41 | 42 | To enter table mode you may execute command `Text Tables: Enter table mode` from command palette or press Ctrl+q Ctrl+q shortcut to toggle mode. To control whether you're in table mode or not, see the icon in the status bar of Visual Studio Code: 43 | 44 | ![Table mode status](doc/table-mode-status.png) 45 | 46 | When in table mode, Tab and Shift+Tab keybindings will navigate next/previous cell accordingly. 47 | 48 | ![Navigation](doc/navigation.gif) 49 | 50 | ## Keybindings 51 | 52 | - Ctrl+q f - format table under cursor. 53 | - Ctrl+q space - clear cell under cursor. 54 | - Ctrl+q Ctrl+q - toggle table mode. 55 | 56 | ### In table mode 57 | 58 | - Tab - navigate to the next cell in table. 59 | - Shift+Tab - navigate to the previous cell in table. 60 | 61 | ### Custom keybindings 62 | 63 | Extension introduces additional `tableMode` when-clause that you may use to define your own keybindings when in table mode. 64 | 65 | Sample keybinding: 66 | 67 | ```json 68 | { 69 | "key": "tab", 70 | "command": "text-tables.gotoNextCell", 71 | "when": "tableMode" 72 | } 73 | ``` 74 | 75 | ## Settings 76 | 77 | This extension introduces some settings that you may setup in your user settings or workspace settings. 78 | 79 | Available settings: 80 | 81 | - `text-tables.mode` - sets the type of tables. Valid values are: `org` and `markdown`. 82 | - `text-tables.showStatus` - controls whether to show or not status item for table mode. 83 | 84 | ## Contribution 85 | 86 | All contributions are welcome. 87 | 88 | If you found a bug or want to propose new feature for the extension, feel free to create an issue. 89 | 90 | [CHANGELOG]: ./CHANGELOG.md 91 | [LICENSE]: ./LICENSE 92 | [version-badge]: https://img.shields.io/badge/version-0.1.5-blue.svg 93 | [license-badge]: https://img.shields.io/badge/license-MIT-blue.svg 94 | -------------------------------------------------------------------------------- /coverconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "enabled": true, 3 | "relativeSourcePath": "../src", 4 | "relativeCoverageDir": "../../coverage", 5 | "ignorePatterns": [ 6 | "**/node_modules/**" 7 | ], 8 | "includePid": false, 9 | "reports": [ 10 | "html", 11 | "lcov", 12 | "text-summary" 13 | ], 14 | "verbose": false 15 | } 16 | -------------------------------------------------------------------------------- /doc/navigation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rpeshkov/vscode-text-tables/e6502bfc5765286a7a8819ffbb5cf819be23b32f/doc/navigation.gif -------------------------------------------------------------------------------- /doc/sample.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rpeshkov/vscode-text-tables/e6502bfc5765286a7a8819ffbb5cf819be23b32f/doc/sample.gif -------------------------------------------------------------------------------- /doc/table-mode-status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rpeshkov/vscode-text-tables/e6502bfc5765286a7a8819ffbb5cf819be23b32f/doc/table-mode-status.png -------------------------------------------------------------------------------- /e2e/e2e.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rpeshkov/vscode-text-tables/e6502bfc5765286a7a8819ffbb5cf819be23b32f/icons/icon.png -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vscode-text-tables", 3 | "version": "0.1.5", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.8.3", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", 10 | "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", 11 | "dev": true, 12 | "requires": { 13 | "@babel/highlight": "^7.8.3" 14 | } 15 | }, 16 | "@babel/helper-validator-identifier": { 17 | "version": "7.9.5", 18 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", 19 | "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", 20 | "dev": true 21 | }, 22 | "@babel/highlight": { 23 | "version": "7.9.0", 24 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", 25 | "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", 26 | "dev": true, 27 | "requires": { 28 | "@babel/helper-validator-identifier": "^7.9.0", 29 | "chalk": "^2.0.0", 30 | "js-tokens": "^4.0.0" 31 | } 32 | }, 33 | "@types/color-name": { 34 | "version": "1.1.1", 35 | "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", 36 | "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", 37 | "dev": true 38 | }, 39 | "@types/eslint-visitor-keys": { 40 | "version": "1.0.0", 41 | "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", 42 | "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", 43 | "dev": true 44 | }, 45 | "@types/events": { 46 | "version": "3.0.0", 47 | "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", 48 | "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", 49 | "dev": true 50 | }, 51 | "@types/glob": { 52 | "version": "7.1.1", 53 | "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", 54 | "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", 55 | "dev": true, 56 | "requires": { 57 | "@types/events": "*", 58 | "@types/minimatch": "*", 59 | "@types/node": "*" 60 | } 61 | }, 62 | "@types/json-schema": { 63 | "version": "7.0.4", 64 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", 65 | "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==", 66 | "dev": true 67 | }, 68 | "@types/minimatch": { 69 | "version": "3.0.3", 70 | "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", 71 | "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", 72 | "dev": true 73 | }, 74 | "@types/mocha": { 75 | "version": "7.0.2", 76 | "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", 77 | "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", 78 | "dev": true 79 | }, 80 | "@types/node": { 81 | "version": "7.10.11", 82 | "resolved": "https://registry.npmjs.org/@types/node/-/node-7.10.11.tgz", 83 | "integrity": "sha512-uEqP1HlJFhsgD8DOBFdC72/5selvor0mzdQY97zlyo8Q6qPl849cFBWkNpgTXw3jIvb7iNyWsId51/A8HYKzbQ==", 84 | "dev": true 85 | }, 86 | "@types/vscode": { 87 | "version": "1.45.1", 88 | "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.45.1.tgz", 89 | "integrity": "sha512-0NO9qrrEJBO8FsqHCrFMgR2suKnwCsKBWvRSb2OzH5gs4i3QO5AhEMQYrSzDbU/wLPt7N617/rN9lPY213gmwg==", 90 | "dev": true 91 | }, 92 | "@typescript-eslint/eslint-plugin": { 93 | "version": "2.34.0", 94 | "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz", 95 | "integrity": "sha512-4zY3Z88rEE99+CNvTbXSyovv2z9PNOVffTWD2W8QF5s2prBQtwN2zadqERcrHpcR7O/+KMI3fcTAmUUhK/iQcQ==", 96 | "dev": true, 97 | "requires": { 98 | "@typescript-eslint/experimental-utils": "2.34.0", 99 | "functional-red-black-tree": "^1.0.1", 100 | "regexpp": "^3.0.0", 101 | "tsutils": "^3.17.1" 102 | } 103 | }, 104 | "@typescript-eslint/experimental-utils": { 105 | "version": "2.34.0", 106 | "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz", 107 | "integrity": "sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA==", 108 | "dev": true, 109 | "requires": { 110 | "@types/json-schema": "^7.0.3", 111 | "@typescript-eslint/typescript-estree": "2.34.0", 112 | "eslint-scope": "^5.0.0", 113 | "eslint-utils": "^2.0.0" 114 | } 115 | }, 116 | "@typescript-eslint/parser": { 117 | "version": "2.34.0", 118 | "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.34.0.tgz", 119 | "integrity": "sha512-03ilO0ucSD0EPTw2X4PntSIRFtDPWjrVq7C3/Z3VQHRC7+13YB55rcJI3Jt+YgeHbjUdJPcPa7b23rXCBokuyA==", 120 | "dev": true, 121 | "requires": { 122 | "@types/eslint-visitor-keys": "^1.0.0", 123 | "@typescript-eslint/experimental-utils": "2.34.0", 124 | "@typescript-eslint/typescript-estree": "2.34.0", 125 | "eslint-visitor-keys": "^1.1.0" 126 | } 127 | }, 128 | "@typescript-eslint/typescript-estree": { 129 | "version": "2.34.0", 130 | "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz", 131 | "integrity": "sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==", 132 | "dev": true, 133 | "requires": { 134 | "debug": "^4.1.1", 135 | "eslint-visitor-keys": "^1.1.0", 136 | "glob": "^7.1.6", 137 | "is-glob": "^4.0.1", 138 | "lodash": "^4.17.15", 139 | "semver": "^7.3.2", 140 | "tsutils": "^3.17.1" 141 | }, 142 | "dependencies": { 143 | "debug": { 144 | "version": "4.1.1", 145 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 146 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 147 | "dev": true, 148 | "requires": { 149 | "ms": "^2.1.1" 150 | } 151 | }, 152 | "ms": { 153 | "version": "2.1.2", 154 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 155 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 156 | "dev": true 157 | } 158 | } 159 | }, 160 | "acorn": { 161 | "version": "7.2.0", 162 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.2.0.tgz", 163 | "integrity": "sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==", 164 | "dev": true 165 | }, 166 | "acorn-jsx": { 167 | "version": "5.2.0", 168 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", 169 | "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", 170 | "dev": true 171 | }, 172 | "agent-base": { 173 | "version": "4.3.0", 174 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", 175 | "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", 176 | "dev": true, 177 | "requires": { 178 | "es6-promisify": "^5.0.0" 179 | } 180 | }, 181 | "ajv": { 182 | "version": "6.12.2", 183 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", 184 | "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", 185 | "dev": true, 186 | "requires": { 187 | "fast-deep-equal": "^3.1.1", 188 | "fast-json-stable-stringify": "^2.0.0", 189 | "json-schema-traverse": "^0.4.1", 190 | "uri-js": "^4.2.2" 191 | } 192 | }, 193 | "ansi-escapes": { 194 | "version": "4.3.1", 195 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", 196 | "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", 197 | "dev": true, 198 | "requires": { 199 | "type-fest": "^0.11.0" 200 | }, 201 | "dependencies": { 202 | "type-fest": { 203 | "version": "0.11.0", 204 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", 205 | "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", 206 | "dev": true 207 | } 208 | } 209 | }, 210 | "ansi-regex": { 211 | "version": "5.0.0", 212 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 213 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 214 | "dev": true 215 | }, 216 | "ansi-styles": { 217 | "version": "3.2.1", 218 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 219 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 220 | "dev": true, 221 | "requires": { 222 | "color-convert": "^1.9.0" 223 | } 224 | }, 225 | "anymatch": { 226 | "version": "3.1.1", 227 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", 228 | "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", 229 | "dev": true, 230 | "requires": { 231 | "normalize-path": "^3.0.0", 232 | "picomatch": "^2.0.4" 233 | } 234 | }, 235 | "argparse": { 236 | "version": "1.0.10", 237 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 238 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 239 | "dev": true, 240 | "requires": { 241 | "sprintf-js": "~1.0.2" 242 | } 243 | }, 244 | "astral-regex": { 245 | "version": "1.0.0", 246 | "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", 247 | "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", 248 | "dev": true 249 | }, 250 | "balanced-match": { 251 | "version": "1.0.0", 252 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 253 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 254 | "dev": true 255 | }, 256 | "binary-extensions": { 257 | "version": "2.0.0", 258 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", 259 | "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", 260 | "dev": true 261 | }, 262 | "brace-expansion": { 263 | "version": "1.1.11", 264 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 265 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 266 | "dev": true, 267 | "requires": { 268 | "balanced-match": "^1.0.0", 269 | "concat-map": "0.0.1" 270 | } 271 | }, 272 | "braces": { 273 | "version": "3.0.2", 274 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 275 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 276 | "dev": true, 277 | "requires": { 278 | "fill-range": "^7.0.1" 279 | } 280 | }, 281 | "browser-stdout": { 282 | "version": "1.3.1", 283 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 284 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 285 | "dev": true 286 | }, 287 | "callsite": { 288 | "version": "1.0.0", 289 | "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", 290 | "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", 291 | "dev": true 292 | }, 293 | "callsites": { 294 | "version": "3.1.0", 295 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 296 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 297 | "dev": true 298 | }, 299 | "camelcase": { 300 | "version": "5.3.1", 301 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 302 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 303 | "dev": true 304 | }, 305 | "chalk": { 306 | "version": "2.4.2", 307 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 308 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 309 | "dev": true, 310 | "requires": { 311 | "ansi-styles": "^3.2.1", 312 | "escape-string-regexp": "^1.0.5", 313 | "supports-color": "^5.3.0" 314 | } 315 | }, 316 | "chardet": { 317 | "version": "0.7.0", 318 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", 319 | "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", 320 | "dev": true 321 | }, 322 | "chokidar": { 323 | "version": "3.3.0", 324 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", 325 | "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", 326 | "dev": true, 327 | "requires": { 328 | "anymatch": "~3.1.1", 329 | "braces": "~3.0.2", 330 | "fsevents": "~2.1.1", 331 | "glob-parent": "~5.1.0", 332 | "is-binary-path": "~2.1.0", 333 | "is-glob": "~4.0.1", 334 | "normalize-path": "~3.0.0", 335 | "readdirp": "~3.2.0" 336 | } 337 | }, 338 | "cli-cursor": { 339 | "version": "3.1.0", 340 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", 341 | "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", 342 | "dev": true, 343 | "requires": { 344 | "restore-cursor": "^3.1.0" 345 | } 346 | }, 347 | "cli-width": { 348 | "version": "2.2.1", 349 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", 350 | "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", 351 | "dev": true 352 | }, 353 | "cliui": { 354 | "version": "5.0.0", 355 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", 356 | "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", 357 | "dev": true, 358 | "requires": { 359 | "string-width": "^3.1.0", 360 | "strip-ansi": "^5.2.0", 361 | "wrap-ansi": "^5.1.0" 362 | }, 363 | "dependencies": { 364 | "emoji-regex": { 365 | "version": "7.0.3", 366 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 367 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 368 | "dev": true 369 | }, 370 | "is-fullwidth-code-point": { 371 | "version": "2.0.0", 372 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 373 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 374 | "dev": true 375 | }, 376 | "string-width": { 377 | "version": "3.1.0", 378 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 379 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 380 | "dev": true, 381 | "requires": { 382 | "emoji-regex": "^7.0.1", 383 | "is-fullwidth-code-point": "^2.0.0", 384 | "strip-ansi": "^5.1.0" 385 | } 386 | }, 387 | "wrap-ansi": { 388 | "version": "5.1.0", 389 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", 390 | "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", 391 | "dev": true, 392 | "requires": { 393 | "ansi-styles": "^3.2.0", 394 | "string-width": "^3.0.0", 395 | "strip-ansi": "^5.0.0" 396 | } 397 | } 398 | } 399 | }, 400 | "color-convert": { 401 | "version": "1.9.3", 402 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 403 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 404 | "dev": true, 405 | "requires": { 406 | "color-name": "1.1.3" 407 | } 408 | }, 409 | "color-name": { 410 | "version": "1.1.3", 411 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 412 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 413 | "dev": true 414 | }, 415 | "concat-map": { 416 | "version": "0.0.1", 417 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 418 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 419 | "dev": true 420 | }, 421 | "cross-spawn": { 422 | "version": "6.0.5", 423 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", 424 | "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", 425 | "dev": true, 426 | "requires": { 427 | "nice-try": "^1.0.4", 428 | "path-key": "^2.0.1", 429 | "semver": "^5.5.0", 430 | "shebang-command": "^1.2.0", 431 | "which": "^1.2.9" 432 | }, 433 | "dependencies": { 434 | "semver": { 435 | "version": "5.7.1", 436 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 437 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 438 | "dev": true 439 | } 440 | } 441 | }, 442 | "debug": { 443 | "version": "3.1.0", 444 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 445 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 446 | "dev": true, 447 | "requires": { 448 | "ms": "2.0.0" 449 | } 450 | }, 451 | "decache": { 452 | "version": "4.6.0", 453 | "resolved": "https://registry.npmjs.org/decache/-/decache-4.6.0.tgz", 454 | "integrity": "sha512-PppOuLiz+DFeaUvFXEYZjLxAkKiMYH/do/b/MxpDe/8AgKBi5GhZxridoVIbBq72GDbL36e4p0Ce2jTGUwwU+w==", 455 | "dev": true, 456 | "requires": { 457 | "callsite": "^1.0.0" 458 | } 459 | }, 460 | "decamelize": { 461 | "version": "1.2.0", 462 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 463 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 464 | "dev": true 465 | }, 466 | "deep-is": { 467 | "version": "0.1.3", 468 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 469 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 470 | "dev": true 471 | }, 472 | "define-properties": { 473 | "version": "1.1.3", 474 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 475 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 476 | "dev": true, 477 | "requires": { 478 | "object-keys": "^1.0.12" 479 | } 480 | }, 481 | "diff": { 482 | "version": "3.5.0", 483 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", 484 | "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", 485 | "dev": true 486 | }, 487 | "doctrine": { 488 | "version": "3.0.0", 489 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 490 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 491 | "dev": true, 492 | "requires": { 493 | "esutils": "^2.0.2" 494 | } 495 | }, 496 | "emoji-regex": { 497 | "version": "8.0.0", 498 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 499 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 500 | "dev": true 501 | }, 502 | "es-abstract": { 503 | "version": "1.17.5", 504 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", 505 | "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", 506 | "dev": true, 507 | "requires": { 508 | "es-to-primitive": "^1.2.1", 509 | "function-bind": "^1.1.1", 510 | "has": "^1.0.3", 511 | "has-symbols": "^1.0.1", 512 | "is-callable": "^1.1.5", 513 | "is-regex": "^1.0.5", 514 | "object-inspect": "^1.7.0", 515 | "object-keys": "^1.1.1", 516 | "object.assign": "^4.1.0", 517 | "string.prototype.trimleft": "^2.1.1", 518 | "string.prototype.trimright": "^2.1.1" 519 | } 520 | }, 521 | "es-to-primitive": { 522 | "version": "1.2.1", 523 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", 524 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", 525 | "dev": true, 526 | "requires": { 527 | "is-callable": "^1.1.4", 528 | "is-date-object": "^1.0.1", 529 | "is-symbol": "^1.0.2" 530 | } 531 | }, 532 | "es6-promise": { 533 | "version": "4.2.8", 534 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", 535 | "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", 536 | "dev": true 537 | }, 538 | "es6-promisify": { 539 | "version": "5.0.0", 540 | "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", 541 | "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", 542 | "dev": true, 543 | "requires": { 544 | "es6-promise": "^4.0.3" 545 | } 546 | }, 547 | "escape-string-regexp": { 548 | "version": "1.0.5", 549 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 550 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 551 | "dev": true 552 | }, 553 | "eslint": { 554 | "version": "6.8.0", 555 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", 556 | "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", 557 | "dev": true, 558 | "requires": { 559 | "@babel/code-frame": "^7.0.0", 560 | "ajv": "^6.10.0", 561 | "chalk": "^2.1.0", 562 | "cross-spawn": "^6.0.5", 563 | "debug": "^4.0.1", 564 | "doctrine": "^3.0.0", 565 | "eslint-scope": "^5.0.0", 566 | "eslint-utils": "^1.4.3", 567 | "eslint-visitor-keys": "^1.1.0", 568 | "espree": "^6.1.2", 569 | "esquery": "^1.0.1", 570 | "esutils": "^2.0.2", 571 | "file-entry-cache": "^5.0.1", 572 | "functional-red-black-tree": "^1.0.1", 573 | "glob-parent": "^5.0.0", 574 | "globals": "^12.1.0", 575 | "ignore": "^4.0.6", 576 | "import-fresh": "^3.0.0", 577 | "imurmurhash": "^0.1.4", 578 | "inquirer": "^7.0.0", 579 | "is-glob": "^4.0.0", 580 | "js-yaml": "^3.13.1", 581 | "json-stable-stringify-without-jsonify": "^1.0.1", 582 | "levn": "^0.3.0", 583 | "lodash": "^4.17.14", 584 | "minimatch": "^3.0.4", 585 | "mkdirp": "^0.5.1", 586 | "natural-compare": "^1.4.0", 587 | "optionator": "^0.8.3", 588 | "progress": "^2.0.0", 589 | "regexpp": "^2.0.1", 590 | "semver": "^6.1.2", 591 | "strip-ansi": "^5.2.0", 592 | "strip-json-comments": "^3.0.1", 593 | "table": "^5.2.3", 594 | "text-table": "^0.2.0", 595 | "v8-compile-cache": "^2.0.3" 596 | }, 597 | "dependencies": { 598 | "debug": { 599 | "version": "4.1.1", 600 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 601 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 602 | "dev": true, 603 | "requires": { 604 | "ms": "^2.1.1" 605 | } 606 | }, 607 | "eslint-utils": { 608 | "version": "1.4.3", 609 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", 610 | "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", 611 | "dev": true, 612 | "requires": { 613 | "eslint-visitor-keys": "^1.1.0" 614 | } 615 | }, 616 | "ms": { 617 | "version": "2.1.2", 618 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 619 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 620 | "dev": true 621 | }, 622 | "optionator": { 623 | "version": "0.8.3", 624 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", 625 | "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", 626 | "dev": true, 627 | "requires": { 628 | "deep-is": "~0.1.3", 629 | "fast-levenshtein": "~2.0.6", 630 | "levn": "~0.3.0", 631 | "prelude-ls": "~1.1.2", 632 | "type-check": "~0.3.2", 633 | "word-wrap": "~1.2.3" 634 | } 635 | }, 636 | "regexpp": { 637 | "version": "2.0.1", 638 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", 639 | "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", 640 | "dev": true 641 | }, 642 | "semver": { 643 | "version": "6.3.0", 644 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 645 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 646 | "dev": true 647 | } 648 | } 649 | }, 650 | "eslint-scope": { 651 | "version": "5.0.0", 652 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", 653 | "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", 654 | "dev": true, 655 | "requires": { 656 | "esrecurse": "^4.1.0", 657 | "estraverse": "^4.1.1" 658 | }, 659 | "dependencies": { 660 | "estraverse": { 661 | "version": "4.3.0", 662 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 663 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 664 | "dev": true 665 | } 666 | } 667 | }, 668 | "eslint-utils": { 669 | "version": "2.0.0", 670 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz", 671 | "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==", 672 | "dev": true, 673 | "requires": { 674 | "eslint-visitor-keys": "^1.1.0" 675 | } 676 | }, 677 | "eslint-visitor-keys": { 678 | "version": "1.1.0", 679 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", 680 | "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", 681 | "dev": true 682 | }, 683 | "espree": { 684 | "version": "6.2.1", 685 | "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", 686 | "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", 687 | "dev": true, 688 | "requires": { 689 | "acorn": "^7.1.1", 690 | "acorn-jsx": "^5.2.0", 691 | "eslint-visitor-keys": "^1.1.0" 692 | } 693 | }, 694 | "esprima": { 695 | "version": "4.0.0", 696 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", 697 | "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", 698 | "dev": true 699 | }, 700 | "esquery": { 701 | "version": "1.3.1", 702 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", 703 | "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", 704 | "dev": true, 705 | "requires": { 706 | "estraverse": "^5.1.0" 707 | }, 708 | "dependencies": { 709 | "estraverse": { 710 | "version": "5.1.0", 711 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz", 712 | "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==", 713 | "dev": true 714 | } 715 | } 716 | }, 717 | "esrecurse": { 718 | "version": "4.2.1", 719 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", 720 | "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", 721 | "dev": true, 722 | "requires": { 723 | "estraverse": "^4.1.0" 724 | }, 725 | "dependencies": { 726 | "estraverse": { 727 | "version": "4.3.0", 728 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 729 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 730 | "dev": true 731 | } 732 | } 733 | }, 734 | "esutils": { 735 | "version": "2.0.2", 736 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", 737 | "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", 738 | "dev": true 739 | }, 740 | "external-editor": { 741 | "version": "3.1.0", 742 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", 743 | "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", 744 | "dev": true, 745 | "requires": { 746 | "chardet": "^0.7.0", 747 | "iconv-lite": "^0.4.24", 748 | "tmp": "^0.0.33" 749 | } 750 | }, 751 | "fast-deep-equal": { 752 | "version": "3.1.1", 753 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", 754 | "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", 755 | "dev": true 756 | }, 757 | "fast-json-stable-stringify": { 758 | "version": "2.1.0", 759 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 760 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 761 | "dev": true 762 | }, 763 | "fast-levenshtein": { 764 | "version": "2.0.6", 765 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 766 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 767 | "dev": true 768 | }, 769 | "figures": { 770 | "version": "3.2.0", 771 | "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", 772 | "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", 773 | "dev": true, 774 | "requires": { 775 | "escape-string-regexp": "^1.0.5" 776 | } 777 | }, 778 | "file-entry-cache": { 779 | "version": "5.0.1", 780 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", 781 | "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", 782 | "dev": true, 783 | "requires": { 784 | "flat-cache": "^2.0.1" 785 | } 786 | }, 787 | "fill-range": { 788 | "version": "7.0.1", 789 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 790 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 791 | "dev": true, 792 | "requires": { 793 | "to-regex-range": "^5.0.1" 794 | } 795 | }, 796 | "flat": { 797 | "version": "4.1.0", 798 | "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", 799 | "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", 800 | "dev": true, 801 | "requires": { 802 | "is-buffer": "~2.0.3" 803 | } 804 | }, 805 | "flat-cache": { 806 | "version": "2.0.1", 807 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", 808 | "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", 809 | "dev": true, 810 | "requires": { 811 | "flatted": "^2.0.0", 812 | "rimraf": "2.6.3", 813 | "write": "1.0.3" 814 | }, 815 | "dependencies": { 816 | "rimraf": { 817 | "version": "2.6.3", 818 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", 819 | "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", 820 | "dev": true, 821 | "requires": { 822 | "glob": "^7.1.3" 823 | } 824 | } 825 | } 826 | }, 827 | "flatted": { 828 | "version": "2.0.2", 829 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", 830 | "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", 831 | "dev": true 832 | }, 833 | "fs.realpath": { 834 | "version": "1.0.0", 835 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 836 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 837 | "dev": true 838 | }, 839 | "fsevents": { 840 | "version": "2.1.3", 841 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", 842 | "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", 843 | "dev": true, 844 | "optional": true 845 | }, 846 | "function-bind": { 847 | "version": "1.1.1", 848 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 849 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 850 | "dev": true 851 | }, 852 | "functional-red-black-tree": { 853 | "version": "1.0.1", 854 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 855 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 856 | "dev": true 857 | }, 858 | "get-caller-file": { 859 | "version": "2.0.5", 860 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 861 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 862 | "dev": true 863 | }, 864 | "glob": { 865 | "version": "7.1.6", 866 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 867 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 868 | "dev": true, 869 | "requires": { 870 | "fs.realpath": "^1.0.0", 871 | "inflight": "^1.0.4", 872 | "inherits": "2", 873 | "minimatch": "^3.0.4", 874 | "once": "^1.3.0", 875 | "path-is-absolute": "^1.0.0" 876 | } 877 | }, 878 | "glob-parent": { 879 | "version": "5.1.1", 880 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", 881 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", 882 | "dev": true, 883 | "requires": { 884 | "is-glob": "^4.0.1" 885 | } 886 | }, 887 | "globals": { 888 | "version": "12.4.0", 889 | "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", 890 | "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", 891 | "dev": true, 892 | "requires": { 893 | "type-fest": "^0.8.1" 894 | } 895 | }, 896 | "growl": { 897 | "version": "1.10.5", 898 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 899 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 900 | "dev": true 901 | }, 902 | "has": { 903 | "version": "1.0.3", 904 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 905 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 906 | "dev": true, 907 | "requires": { 908 | "function-bind": "^1.1.1" 909 | } 910 | }, 911 | "has-flag": { 912 | "version": "3.0.0", 913 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 914 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 915 | "dev": true 916 | }, 917 | "has-symbols": { 918 | "version": "1.0.1", 919 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", 920 | "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", 921 | "dev": true 922 | }, 923 | "he": { 924 | "version": "1.2.0", 925 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 926 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 927 | "dev": true 928 | }, 929 | "http-proxy-agent": { 930 | "version": "2.1.0", 931 | "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", 932 | "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", 933 | "dev": true, 934 | "requires": { 935 | "agent-base": "4", 936 | "debug": "3.1.0" 937 | } 938 | }, 939 | "https-proxy-agent": { 940 | "version": "2.2.4", 941 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", 942 | "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", 943 | "dev": true, 944 | "requires": { 945 | "agent-base": "^4.3.0", 946 | "debug": "^3.1.0" 947 | } 948 | }, 949 | "iconv-lite": { 950 | "version": "0.4.24", 951 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 952 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 953 | "dev": true, 954 | "requires": { 955 | "safer-buffer": ">= 2.1.2 < 3" 956 | } 957 | }, 958 | "ignore": { 959 | "version": "4.0.6", 960 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 961 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 962 | "dev": true 963 | }, 964 | "import-fresh": { 965 | "version": "3.2.1", 966 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", 967 | "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", 968 | "dev": true, 969 | "requires": { 970 | "parent-module": "^1.0.0", 971 | "resolve-from": "^4.0.0" 972 | } 973 | }, 974 | "imurmurhash": { 975 | "version": "0.1.4", 976 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 977 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 978 | "dev": true 979 | }, 980 | "inflight": { 981 | "version": "1.0.6", 982 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 983 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 984 | "dev": true, 985 | "requires": { 986 | "once": "^1.3.0", 987 | "wrappy": "1" 988 | } 989 | }, 990 | "inherits": { 991 | "version": "2.0.3", 992 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 993 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 994 | "dev": true 995 | }, 996 | "inquirer": { 997 | "version": "7.1.0", 998 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", 999 | "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", 1000 | "dev": true, 1001 | "requires": { 1002 | "ansi-escapes": "^4.2.1", 1003 | "chalk": "^3.0.0", 1004 | "cli-cursor": "^3.1.0", 1005 | "cli-width": "^2.0.0", 1006 | "external-editor": "^3.0.3", 1007 | "figures": "^3.0.0", 1008 | "lodash": "^4.17.15", 1009 | "mute-stream": "0.0.8", 1010 | "run-async": "^2.4.0", 1011 | "rxjs": "^6.5.3", 1012 | "string-width": "^4.1.0", 1013 | "strip-ansi": "^6.0.0", 1014 | "through": "^2.3.6" 1015 | }, 1016 | "dependencies": { 1017 | "ansi-styles": { 1018 | "version": "4.2.1", 1019 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", 1020 | "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", 1021 | "dev": true, 1022 | "requires": { 1023 | "@types/color-name": "^1.1.1", 1024 | "color-convert": "^2.0.1" 1025 | } 1026 | }, 1027 | "chalk": { 1028 | "version": "3.0.0", 1029 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", 1030 | "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", 1031 | "dev": true, 1032 | "requires": { 1033 | "ansi-styles": "^4.1.0", 1034 | "supports-color": "^7.1.0" 1035 | } 1036 | }, 1037 | "color-convert": { 1038 | "version": "2.0.1", 1039 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1040 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1041 | "dev": true, 1042 | "requires": { 1043 | "color-name": "~1.1.4" 1044 | } 1045 | }, 1046 | "color-name": { 1047 | "version": "1.1.4", 1048 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1049 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1050 | "dev": true 1051 | }, 1052 | "has-flag": { 1053 | "version": "4.0.0", 1054 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1055 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1056 | "dev": true 1057 | }, 1058 | "strip-ansi": { 1059 | "version": "6.0.0", 1060 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 1061 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 1062 | "dev": true, 1063 | "requires": { 1064 | "ansi-regex": "^5.0.0" 1065 | } 1066 | }, 1067 | "supports-color": { 1068 | "version": "7.1.0", 1069 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", 1070 | "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", 1071 | "dev": true, 1072 | "requires": { 1073 | "has-flag": "^4.0.0" 1074 | } 1075 | } 1076 | } 1077 | }, 1078 | "is-binary-path": { 1079 | "version": "2.1.0", 1080 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 1081 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 1082 | "dev": true, 1083 | "requires": { 1084 | "binary-extensions": "^2.0.0" 1085 | } 1086 | }, 1087 | "is-buffer": { 1088 | "version": "2.0.4", 1089 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", 1090 | "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", 1091 | "dev": true 1092 | }, 1093 | "is-callable": { 1094 | "version": "1.1.5", 1095 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", 1096 | "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", 1097 | "dev": true 1098 | }, 1099 | "is-date-object": { 1100 | "version": "1.0.2", 1101 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", 1102 | "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", 1103 | "dev": true 1104 | }, 1105 | "is-extglob": { 1106 | "version": "2.1.1", 1107 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1108 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 1109 | "dev": true 1110 | }, 1111 | "is-fullwidth-code-point": { 1112 | "version": "3.0.0", 1113 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1114 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 1115 | "dev": true 1116 | }, 1117 | "is-glob": { 1118 | "version": "4.0.1", 1119 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 1120 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 1121 | "dev": true, 1122 | "requires": { 1123 | "is-extglob": "^2.1.1" 1124 | } 1125 | }, 1126 | "is-number": { 1127 | "version": "7.0.0", 1128 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1129 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1130 | "dev": true 1131 | }, 1132 | "is-regex": { 1133 | "version": "1.0.5", 1134 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", 1135 | "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", 1136 | "dev": true, 1137 | "requires": { 1138 | "has": "^1.0.3" 1139 | } 1140 | }, 1141 | "is-symbol": { 1142 | "version": "1.0.3", 1143 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", 1144 | "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", 1145 | "dev": true, 1146 | "requires": { 1147 | "has-symbols": "^1.0.1" 1148 | } 1149 | }, 1150 | "isexe": { 1151 | "version": "2.0.0", 1152 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1153 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 1154 | "dev": true 1155 | }, 1156 | "js-tokens": { 1157 | "version": "4.0.0", 1158 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 1159 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 1160 | "dev": true 1161 | }, 1162 | "js-yaml": { 1163 | "version": "3.13.1", 1164 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 1165 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 1166 | "dev": true, 1167 | "requires": { 1168 | "argparse": "^1.0.7", 1169 | "esprima": "^4.0.0" 1170 | } 1171 | }, 1172 | "json-schema-traverse": { 1173 | "version": "0.4.1", 1174 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1175 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1176 | "dev": true 1177 | }, 1178 | "json-stable-stringify-without-jsonify": { 1179 | "version": "1.0.1", 1180 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 1181 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 1182 | "dev": true 1183 | }, 1184 | "levn": { 1185 | "version": "0.3.0", 1186 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 1187 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 1188 | "dev": true, 1189 | "requires": { 1190 | "prelude-ls": "~1.1.2", 1191 | "type-check": "~0.3.2" 1192 | } 1193 | }, 1194 | "lodash": { 1195 | "version": "4.17.15", 1196 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 1197 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", 1198 | "dev": true 1199 | }, 1200 | "log-symbols": { 1201 | "version": "3.0.0", 1202 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", 1203 | "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", 1204 | "dev": true, 1205 | "requires": { 1206 | "chalk": "^2.4.2" 1207 | } 1208 | }, 1209 | "mimic-fn": { 1210 | "version": "2.1.0", 1211 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 1212 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", 1213 | "dev": true 1214 | }, 1215 | "minimatch": { 1216 | "version": "3.0.4", 1217 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1218 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1219 | "dev": true, 1220 | "requires": { 1221 | "brace-expansion": "^1.1.7" 1222 | } 1223 | }, 1224 | "mkdirp": { 1225 | "version": "0.5.5", 1226 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 1227 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 1228 | "dev": true, 1229 | "requires": { 1230 | "minimist": "^1.2.5" 1231 | }, 1232 | "dependencies": { 1233 | "minimist": { 1234 | "version": "1.2.5", 1235 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 1236 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 1237 | "dev": true 1238 | } 1239 | } 1240 | }, 1241 | "mocha": { 1242 | "version": "7.2.0", 1243 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz", 1244 | "integrity": "sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ==", 1245 | "dev": true, 1246 | "requires": { 1247 | "ansi-colors": "3.2.3", 1248 | "browser-stdout": "1.3.1", 1249 | "chokidar": "3.3.0", 1250 | "debug": "3.2.6", 1251 | "diff": "3.5.0", 1252 | "escape-string-regexp": "1.0.5", 1253 | "find-up": "3.0.0", 1254 | "glob": "7.1.3", 1255 | "growl": "1.10.5", 1256 | "he": "1.2.0", 1257 | "js-yaml": "3.13.1", 1258 | "log-symbols": "3.0.0", 1259 | "minimatch": "3.0.4", 1260 | "mkdirp": "0.5.5", 1261 | "ms": "2.1.1", 1262 | "node-environment-flags": "1.0.6", 1263 | "object.assign": "4.1.0", 1264 | "strip-json-comments": "2.0.1", 1265 | "supports-color": "6.0.0", 1266 | "which": "1.3.1", 1267 | "wide-align": "1.1.3", 1268 | "yargs": "13.3.2", 1269 | "yargs-parser": "13.1.2", 1270 | "yargs-unparser": "1.6.0" 1271 | }, 1272 | "dependencies": { 1273 | "ansi-colors": { 1274 | "version": "3.2.3", 1275 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", 1276 | "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", 1277 | "dev": true 1278 | }, 1279 | "debug": { 1280 | "version": "3.2.6", 1281 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 1282 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 1283 | "dev": true, 1284 | "requires": { 1285 | "ms": "^2.1.1" 1286 | } 1287 | }, 1288 | "find-up": { 1289 | "version": "3.0.0", 1290 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 1291 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 1292 | "dev": true, 1293 | "requires": { 1294 | "locate-path": "^3.0.0" 1295 | } 1296 | }, 1297 | "glob": { 1298 | "version": "7.1.3", 1299 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", 1300 | "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", 1301 | "dev": true, 1302 | "requires": { 1303 | "fs.realpath": "^1.0.0", 1304 | "inflight": "^1.0.4", 1305 | "inherits": "2", 1306 | "minimatch": "^3.0.4", 1307 | "once": "^1.3.0", 1308 | "path-is-absolute": "^1.0.0" 1309 | } 1310 | }, 1311 | "locate-path": { 1312 | "version": "3.0.0", 1313 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 1314 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 1315 | "dev": true, 1316 | "requires": { 1317 | "p-locate": "^3.0.0", 1318 | "path-exists": "^3.0.0" 1319 | } 1320 | }, 1321 | "ms": { 1322 | "version": "2.1.1", 1323 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 1324 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", 1325 | "dev": true 1326 | }, 1327 | "p-locate": { 1328 | "version": "3.0.0", 1329 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 1330 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 1331 | "dev": true, 1332 | "requires": { 1333 | "p-limit": "^2.0.0" 1334 | } 1335 | }, 1336 | "path-exists": { 1337 | "version": "3.0.0", 1338 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 1339 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 1340 | "dev": true 1341 | }, 1342 | "strip-json-comments": { 1343 | "version": "2.0.1", 1344 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1345 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 1346 | "dev": true 1347 | }, 1348 | "supports-color": { 1349 | "version": "6.0.0", 1350 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", 1351 | "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", 1352 | "dev": true, 1353 | "requires": { 1354 | "has-flag": "^3.0.0" 1355 | } 1356 | }, 1357 | "which": { 1358 | "version": "1.3.1", 1359 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 1360 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 1361 | "dev": true, 1362 | "requires": { 1363 | "isexe": "^2.0.0" 1364 | } 1365 | }, 1366 | "yargs-parser": { 1367 | "version": "13.1.2", 1368 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", 1369 | "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", 1370 | "dev": true, 1371 | "requires": { 1372 | "camelcase": "^5.0.0", 1373 | "decamelize": "^1.2.0" 1374 | } 1375 | } 1376 | } 1377 | }, 1378 | "ms": { 1379 | "version": "2.0.0", 1380 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1381 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 1382 | "dev": true 1383 | }, 1384 | "mute-stream": { 1385 | "version": "0.0.8", 1386 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", 1387 | "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", 1388 | "dev": true 1389 | }, 1390 | "natural-compare": { 1391 | "version": "1.4.0", 1392 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1393 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 1394 | "dev": true 1395 | }, 1396 | "nice-try": { 1397 | "version": "1.0.5", 1398 | "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", 1399 | "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", 1400 | "dev": true 1401 | }, 1402 | "node-environment-flags": { 1403 | "version": "1.0.6", 1404 | "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", 1405 | "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", 1406 | "dev": true, 1407 | "requires": { 1408 | "object.getownpropertydescriptors": "^2.0.3", 1409 | "semver": "^5.7.0" 1410 | }, 1411 | "dependencies": { 1412 | "semver": { 1413 | "version": "5.7.1", 1414 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1415 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1416 | "dev": true 1417 | } 1418 | } 1419 | }, 1420 | "normalize-path": { 1421 | "version": "3.0.0", 1422 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1423 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1424 | "dev": true 1425 | }, 1426 | "object-inspect": { 1427 | "version": "1.7.0", 1428 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", 1429 | "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", 1430 | "dev": true 1431 | }, 1432 | "object-keys": { 1433 | "version": "1.1.1", 1434 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 1435 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 1436 | "dev": true 1437 | }, 1438 | "object.assign": { 1439 | "version": "4.1.0", 1440 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", 1441 | "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", 1442 | "dev": true, 1443 | "requires": { 1444 | "define-properties": "^1.1.2", 1445 | "function-bind": "^1.1.1", 1446 | "has-symbols": "^1.0.0", 1447 | "object-keys": "^1.0.11" 1448 | } 1449 | }, 1450 | "object.getownpropertydescriptors": { 1451 | "version": "2.1.0", 1452 | "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", 1453 | "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", 1454 | "dev": true, 1455 | "requires": { 1456 | "define-properties": "^1.1.3", 1457 | "es-abstract": "^1.17.0-next.1" 1458 | } 1459 | }, 1460 | "once": { 1461 | "version": "1.4.0", 1462 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1463 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1464 | "dev": true, 1465 | "requires": { 1466 | "wrappy": "1" 1467 | } 1468 | }, 1469 | "onetime": { 1470 | "version": "5.1.0", 1471 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", 1472 | "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", 1473 | "dev": true, 1474 | "requires": { 1475 | "mimic-fn": "^2.1.0" 1476 | } 1477 | }, 1478 | "os-tmpdir": { 1479 | "version": "1.0.2", 1480 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 1481 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", 1482 | "dev": true 1483 | }, 1484 | "p-limit": { 1485 | "version": "2.3.0", 1486 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 1487 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 1488 | "dev": true, 1489 | "requires": { 1490 | "p-try": "^2.0.0" 1491 | } 1492 | }, 1493 | "p-try": { 1494 | "version": "2.2.0", 1495 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 1496 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 1497 | "dev": true 1498 | }, 1499 | "parent-module": { 1500 | "version": "1.0.1", 1501 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 1502 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 1503 | "dev": true, 1504 | "requires": { 1505 | "callsites": "^3.0.0" 1506 | } 1507 | }, 1508 | "path-is-absolute": { 1509 | "version": "1.0.1", 1510 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1511 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1512 | "dev": true 1513 | }, 1514 | "path-key": { 1515 | "version": "2.0.1", 1516 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", 1517 | "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", 1518 | "dev": true 1519 | }, 1520 | "picomatch": { 1521 | "version": "2.2.2", 1522 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", 1523 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", 1524 | "dev": true 1525 | }, 1526 | "prelude-ls": { 1527 | "version": "1.1.2", 1528 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 1529 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 1530 | "dev": true 1531 | }, 1532 | "progress": { 1533 | "version": "2.0.3", 1534 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 1535 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 1536 | "dev": true 1537 | }, 1538 | "punycode": { 1539 | "version": "2.1.1", 1540 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1541 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 1542 | "dev": true 1543 | }, 1544 | "readdirp": { 1545 | "version": "3.2.0", 1546 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", 1547 | "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", 1548 | "dev": true, 1549 | "requires": { 1550 | "picomatch": "^2.0.4" 1551 | } 1552 | }, 1553 | "regexpp": { 1554 | "version": "3.1.0", 1555 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", 1556 | "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", 1557 | "dev": true 1558 | }, 1559 | "require-directory": { 1560 | "version": "2.1.1", 1561 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1562 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 1563 | "dev": true 1564 | }, 1565 | "require-main-filename": { 1566 | "version": "2.0.0", 1567 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 1568 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", 1569 | "dev": true 1570 | }, 1571 | "resolve-from": { 1572 | "version": "4.0.0", 1573 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1574 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1575 | "dev": true 1576 | }, 1577 | "restore-cursor": { 1578 | "version": "3.1.0", 1579 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", 1580 | "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", 1581 | "dev": true, 1582 | "requires": { 1583 | "onetime": "^5.1.0", 1584 | "signal-exit": "^3.0.2" 1585 | } 1586 | }, 1587 | "rimraf": { 1588 | "version": "2.7.1", 1589 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", 1590 | "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", 1591 | "dev": true, 1592 | "requires": { 1593 | "glob": "^7.1.3" 1594 | } 1595 | }, 1596 | "run-async": { 1597 | "version": "2.4.1", 1598 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", 1599 | "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", 1600 | "dev": true 1601 | }, 1602 | "rxjs": { 1603 | "version": "6.5.5", 1604 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", 1605 | "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", 1606 | "dev": true, 1607 | "requires": { 1608 | "tslib": "^1.9.0" 1609 | } 1610 | }, 1611 | "safer-buffer": { 1612 | "version": "2.1.2", 1613 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1614 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1615 | "dev": true 1616 | }, 1617 | "semver": { 1618 | "version": "7.3.2", 1619 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", 1620 | "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", 1621 | "dev": true 1622 | }, 1623 | "set-blocking": { 1624 | "version": "2.0.0", 1625 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 1626 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", 1627 | "dev": true 1628 | }, 1629 | "shebang-command": { 1630 | "version": "1.2.0", 1631 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 1632 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 1633 | "dev": true, 1634 | "requires": { 1635 | "shebang-regex": "^1.0.0" 1636 | } 1637 | }, 1638 | "shebang-regex": { 1639 | "version": "1.0.0", 1640 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 1641 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", 1642 | "dev": true 1643 | }, 1644 | "signal-exit": { 1645 | "version": "3.0.3", 1646 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", 1647 | "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", 1648 | "dev": true 1649 | }, 1650 | "slice-ansi": { 1651 | "version": "2.1.0", 1652 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", 1653 | "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", 1654 | "dev": true, 1655 | "requires": { 1656 | "ansi-styles": "^3.2.0", 1657 | "astral-regex": "^1.0.0", 1658 | "is-fullwidth-code-point": "^2.0.0" 1659 | }, 1660 | "dependencies": { 1661 | "is-fullwidth-code-point": { 1662 | "version": "2.0.0", 1663 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 1664 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 1665 | "dev": true 1666 | } 1667 | } 1668 | }, 1669 | "sprintf-js": { 1670 | "version": "1.0.3", 1671 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1672 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 1673 | "dev": true 1674 | }, 1675 | "string-width": { 1676 | "version": "4.2.0", 1677 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", 1678 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", 1679 | "dev": true, 1680 | "requires": { 1681 | "emoji-regex": "^8.0.0", 1682 | "is-fullwidth-code-point": "^3.0.0", 1683 | "strip-ansi": "^6.0.0" 1684 | }, 1685 | "dependencies": { 1686 | "strip-ansi": { 1687 | "version": "6.0.0", 1688 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 1689 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 1690 | "dev": true, 1691 | "requires": { 1692 | "ansi-regex": "^5.0.0" 1693 | } 1694 | } 1695 | } 1696 | }, 1697 | "string.prototype.trimend": { 1698 | "version": "1.0.1", 1699 | "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", 1700 | "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", 1701 | "dev": true, 1702 | "requires": { 1703 | "define-properties": "^1.1.3", 1704 | "es-abstract": "^1.17.5" 1705 | } 1706 | }, 1707 | "string.prototype.trimleft": { 1708 | "version": "2.1.2", 1709 | "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", 1710 | "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", 1711 | "dev": true, 1712 | "requires": { 1713 | "define-properties": "^1.1.3", 1714 | "es-abstract": "^1.17.5", 1715 | "string.prototype.trimstart": "^1.0.0" 1716 | } 1717 | }, 1718 | "string.prototype.trimright": { 1719 | "version": "2.1.2", 1720 | "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", 1721 | "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", 1722 | "dev": true, 1723 | "requires": { 1724 | "define-properties": "^1.1.3", 1725 | "es-abstract": "^1.17.5", 1726 | "string.prototype.trimend": "^1.0.0" 1727 | } 1728 | }, 1729 | "string.prototype.trimstart": { 1730 | "version": "1.0.1", 1731 | "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", 1732 | "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", 1733 | "dev": true, 1734 | "requires": { 1735 | "define-properties": "^1.1.3", 1736 | "es-abstract": "^1.17.5" 1737 | } 1738 | }, 1739 | "strip-ansi": { 1740 | "version": "5.2.0", 1741 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 1742 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 1743 | "dev": true, 1744 | "requires": { 1745 | "ansi-regex": "^4.1.0" 1746 | }, 1747 | "dependencies": { 1748 | "ansi-regex": { 1749 | "version": "4.1.0", 1750 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 1751 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 1752 | "dev": true 1753 | } 1754 | } 1755 | }, 1756 | "strip-json-comments": { 1757 | "version": "3.1.0", 1758 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", 1759 | "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==", 1760 | "dev": true 1761 | }, 1762 | "supports-color": { 1763 | "version": "5.5.0", 1764 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1765 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1766 | "dev": true, 1767 | "requires": { 1768 | "has-flag": "^3.0.0" 1769 | } 1770 | }, 1771 | "table": { 1772 | "version": "5.4.6", 1773 | "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", 1774 | "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", 1775 | "dev": true, 1776 | "requires": { 1777 | "ajv": "^6.10.2", 1778 | "lodash": "^4.17.14", 1779 | "slice-ansi": "^2.1.0", 1780 | "string-width": "^3.0.0" 1781 | }, 1782 | "dependencies": { 1783 | "emoji-regex": { 1784 | "version": "7.0.3", 1785 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 1786 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 1787 | "dev": true 1788 | }, 1789 | "is-fullwidth-code-point": { 1790 | "version": "2.0.0", 1791 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 1792 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 1793 | "dev": true 1794 | }, 1795 | "string-width": { 1796 | "version": "3.1.0", 1797 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 1798 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 1799 | "dev": true, 1800 | "requires": { 1801 | "emoji-regex": "^7.0.1", 1802 | "is-fullwidth-code-point": "^2.0.0", 1803 | "strip-ansi": "^5.1.0" 1804 | } 1805 | } 1806 | } 1807 | }, 1808 | "text-table": { 1809 | "version": "0.2.0", 1810 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1811 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 1812 | "dev": true 1813 | }, 1814 | "through": { 1815 | "version": "2.3.8", 1816 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1817 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", 1818 | "dev": true 1819 | }, 1820 | "tmp": { 1821 | "version": "0.0.33", 1822 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 1823 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 1824 | "dev": true, 1825 | "requires": { 1826 | "os-tmpdir": "~1.0.2" 1827 | } 1828 | }, 1829 | "to-regex-range": { 1830 | "version": "5.0.1", 1831 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1832 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1833 | "dev": true, 1834 | "requires": { 1835 | "is-number": "^7.0.0" 1836 | } 1837 | }, 1838 | "tslib": { 1839 | "version": "1.13.0", 1840 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", 1841 | "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", 1842 | "dev": true 1843 | }, 1844 | "tsutils": { 1845 | "version": "3.17.1", 1846 | "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", 1847 | "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", 1848 | "dev": true, 1849 | "requires": { 1850 | "tslib": "^1.8.1" 1851 | } 1852 | }, 1853 | "type-check": { 1854 | "version": "0.3.2", 1855 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 1856 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 1857 | "dev": true, 1858 | "requires": { 1859 | "prelude-ls": "~1.1.2" 1860 | } 1861 | }, 1862 | "type-fest": { 1863 | "version": "0.8.1", 1864 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", 1865 | "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", 1866 | "dev": true 1867 | }, 1868 | "typescript": { 1869 | "version": "3.9.3", 1870 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.3.tgz", 1871 | "integrity": "sha512-D/wqnB2xzNFIcoBG9FG8cXRDjiqSTbG2wd8DMZeQyJlP1vfTkIxH4GKveWaEBYySKIg+USu+E+EDIR47SqnaMQ==", 1872 | "dev": true 1873 | }, 1874 | "uri-js": { 1875 | "version": "4.2.2", 1876 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 1877 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 1878 | "dev": true, 1879 | "requires": { 1880 | "punycode": "^2.1.0" 1881 | } 1882 | }, 1883 | "v8-compile-cache": { 1884 | "version": "2.1.0", 1885 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", 1886 | "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", 1887 | "dev": true 1888 | }, 1889 | "vscode-test": { 1890 | "version": "1.3.0", 1891 | "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.3.0.tgz", 1892 | "integrity": "sha512-LddukcBiSU2FVTDr3c1D8lwkiOvwlJdDL2hqVbn6gIz+rpTqUCkMZSKYm94Y1v0WXlHSDQBsXyY+tchWQgGVsw==", 1893 | "dev": true, 1894 | "requires": { 1895 | "http-proxy-agent": "^2.1.0", 1896 | "https-proxy-agent": "^2.2.4", 1897 | "rimraf": "^2.6.3" 1898 | } 1899 | }, 1900 | "which": { 1901 | "version": "1.3.0", 1902 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", 1903 | "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", 1904 | "dev": true, 1905 | "requires": { 1906 | "isexe": "^2.0.0" 1907 | } 1908 | }, 1909 | "which-module": { 1910 | "version": "2.0.0", 1911 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 1912 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", 1913 | "dev": true 1914 | }, 1915 | "wide-align": { 1916 | "version": "1.1.3", 1917 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", 1918 | "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", 1919 | "dev": true, 1920 | "requires": { 1921 | "string-width": "^1.0.2 || 2" 1922 | }, 1923 | "dependencies": { 1924 | "ansi-regex": { 1925 | "version": "3.0.0", 1926 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 1927 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 1928 | "dev": true 1929 | }, 1930 | "is-fullwidth-code-point": { 1931 | "version": "2.0.0", 1932 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 1933 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 1934 | "dev": true 1935 | }, 1936 | "string-width": { 1937 | "version": "2.1.1", 1938 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 1939 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 1940 | "dev": true, 1941 | "requires": { 1942 | "is-fullwidth-code-point": "^2.0.0", 1943 | "strip-ansi": "^4.0.0" 1944 | } 1945 | }, 1946 | "strip-ansi": { 1947 | "version": "4.0.0", 1948 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 1949 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 1950 | "dev": true, 1951 | "requires": { 1952 | "ansi-regex": "^3.0.0" 1953 | } 1954 | } 1955 | } 1956 | }, 1957 | "word-wrap": { 1958 | "version": "1.2.3", 1959 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 1960 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 1961 | "dev": true 1962 | }, 1963 | "wrappy": { 1964 | "version": "1.0.2", 1965 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1966 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1967 | "dev": true 1968 | }, 1969 | "write": { 1970 | "version": "1.0.3", 1971 | "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", 1972 | "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", 1973 | "dev": true, 1974 | "requires": { 1975 | "mkdirp": "^0.5.1" 1976 | } 1977 | }, 1978 | "y18n": { 1979 | "version": "4.0.0", 1980 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", 1981 | "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", 1982 | "dev": true 1983 | }, 1984 | "yargs": { 1985 | "version": "13.3.2", 1986 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", 1987 | "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", 1988 | "dev": true, 1989 | "requires": { 1990 | "cliui": "^5.0.0", 1991 | "find-up": "^3.0.0", 1992 | "get-caller-file": "^2.0.1", 1993 | "require-directory": "^2.1.1", 1994 | "require-main-filename": "^2.0.0", 1995 | "set-blocking": "^2.0.0", 1996 | "string-width": "^3.0.0", 1997 | "which-module": "^2.0.0", 1998 | "y18n": "^4.0.0", 1999 | "yargs-parser": "^13.1.2" 2000 | }, 2001 | "dependencies": { 2002 | "emoji-regex": { 2003 | "version": "7.0.3", 2004 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 2005 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 2006 | "dev": true 2007 | }, 2008 | "find-up": { 2009 | "version": "3.0.0", 2010 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 2011 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 2012 | "dev": true, 2013 | "requires": { 2014 | "locate-path": "^3.0.0" 2015 | } 2016 | }, 2017 | "is-fullwidth-code-point": { 2018 | "version": "2.0.0", 2019 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 2020 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 2021 | "dev": true 2022 | }, 2023 | "locate-path": { 2024 | "version": "3.0.0", 2025 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 2026 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 2027 | "dev": true, 2028 | "requires": { 2029 | "p-locate": "^3.0.0", 2030 | "path-exists": "^3.0.0" 2031 | } 2032 | }, 2033 | "p-locate": { 2034 | "version": "3.0.0", 2035 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 2036 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 2037 | "dev": true, 2038 | "requires": { 2039 | "p-limit": "^2.0.0" 2040 | } 2041 | }, 2042 | "path-exists": { 2043 | "version": "3.0.0", 2044 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 2045 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 2046 | "dev": true 2047 | }, 2048 | "string-width": { 2049 | "version": "3.1.0", 2050 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 2051 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 2052 | "dev": true, 2053 | "requires": { 2054 | "emoji-regex": "^7.0.1", 2055 | "is-fullwidth-code-point": "^2.0.0", 2056 | "strip-ansi": "^5.1.0" 2057 | } 2058 | }, 2059 | "yargs-parser": { 2060 | "version": "13.1.2", 2061 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", 2062 | "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", 2063 | "dev": true, 2064 | "requires": { 2065 | "camelcase": "^5.0.0", 2066 | "decamelize": "^1.2.0" 2067 | } 2068 | } 2069 | } 2070 | }, 2071 | "yargs-unparser": { 2072 | "version": "1.6.0", 2073 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", 2074 | "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", 2075 | "dev": true, 2076 | "requires": { 2077 | "flat": "^4.1.0", 2078 | "lodash": "^4.17.15", 2079 | "yargs": "^13.3.0" 2080 | } 2081 | } 2082 | } 2083 | } 2084 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vscode-text-tables", 3 | "displayName": "Text Tables", 4 | "description": "Work with text tables without pain", 5 | "version": "0.1.5", 6 | "icon": "icons/icon.png", 7 | "preview": false, 8 | "publisher": "RomanPeshkov", 9 | "license": "SEE LICENSE IN LICENSE", 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/rpeshkov/vscode-text-tables" 13 | }, 14 | "engines": { 15 | "vscode": "^1.45.0" 16 | }, 17 | "categories": [ 18 | "Formatters", 19 | "Other" 20 | ], 21 | "keywords": [ 22 | "org-mode", 23 | "org", 24 | "tables", 25 | "markdown" 26 | ], 27 | "activationEvents": [ 28 | "onLanguage:markdown", 29 | "onLanguage:org", 30 | "onCommand:text-tables.enable" 31 | ], 32 | "main": "./out/src/extension", 33 | "contributes": { 34 | "commands": [ 35 | { 36 | "command": "text-tables.enable", 37 | "title": "Text Tables: Enable" 38 | }, 39 | { 40 | "command": "text-tables.formatUnderCursor", 41 | "title": "Text Tables: Format under cursor" 42 | }, 43 | { 44 | "command": "text-tables.tableModeOn", 45 | "title": "Text Tables: Enter table mode" 46 | }, 47 | { 48 | "command": "text-tables.tableModeOff", 49 | "title": "Text Tables: Exit table mode" 50 | }, 51 | { 52 | "command": "text-tables.gotoNextCell", 53 | "title": "Text Tables: Go to next cell" 54 | }, 55 | { 56 | "command": "text-tables.gotoPreviousCell", 57 | "title": "Text Tables: Go to previous cell" 58 | }, 59 | { 60 | "command": "text-tables.createTable", 61 | "title": "Text Tables: Create table" 62 | }, 63 | { 64 | "command": "text-tables.clearCell", 65 | "title": "Text Tables: Clear cell" 66 | }, 67 | { 68 | "command": "text-tables.moveRowDown", 69 | "title": "Move row down", 70 | "category": "Text Tables" 71 | }, 72 | { 73 | "command": "text-tables.moveRowUp", 74 | "title": "Move row up", 75 | "category": "Text Tables" 76 | }, 77 | { 78 | "command": "text-tables.moveColRight", 79 | "title": "Move column right", 80 | "category": "Text Tables" 81 | }, 82 | { 83 | "command": "text-tables.moveColLeft", 84 | "title": "Move column left", 85 | "category": "Text Tables" 86 | }, 87 | { 88 | "command": "text-tables.nextRow", 89 | "title": "Next row", 90 | "category": "Text Tables" 91 | } 92 | ], 93 | "configuration": { 94 | "type": "object", 95 | "title": "Text Tables configuration", 96 | "properties": { 97 | "text-tables.mode": { 98 | "type": "string", 99 | "enum": [ 100 | "markdown", 101 | "org" 102 | ], 103 | "default": "markdown", 104 | "description": "Sets the mode in which extension should work", 105 | "scope": "window" 106 | }, 107 | "text-tables.showStatus": { 108 | "type": "boolean", 109 | "default": true, 110 | "description": "Show table mode status bar item", 111 | "scope": "window" 112 | } 113 | } 114 | }, 115 | "keybindings": [ 116 | { 117 | "command": "text-tables.formatUnderCursor", 118 | "key": "ctrl+q ctrl+f" 119 | }, 120 | { 121 | "command": "text-tables.clearCell", 122 | "key": "ctrl+q space" 123 | }, 124 | { 125 | "command": "text-tables.tableModeOn", 126 | "key": "ctrl+q ctrl+q", 127 | "when": "editorFocus && !tableMode" 128 | }, 129 | { 130 | "command": "text-tables.tableModeOff", 131 | "key": "ctrl+q ctrl+q", 132 | "when": "editorFocus && tableMode" 133 | }, 134 | { 135 | "command": "text-tables.gotoNextCell", 136 | "key": "tab", 137 | "when": "tableMode" 138 | }, 139 | { 140 | "command": "text-tables.gotoPreviousCell", 141 | "key": "shift+tab", 142 | "when": "tableMode" 143 | }, 144 | { 145 | "command": "text-tables.moveRowUp", 146 | "key": "alt+up", 147 | "when": "tableMode" 148 | }, 149 | { 150 | "command": "text-tables.moveRowDown", 151 | "key": "alt+down", 152 | "when": "tableMode" 153 | }, 154 | { 155 | "command": "text-tables.moveColRight", 156 | "key": "alt+right", 157 | "when": "tableMode" 158 | }, 159 | { 160 | "command": "text-tables.moveColLeft", 161 | "key": "alt+left", 162 | "when": "tableMode" 163 | }, 164 | { 165 | "command": "text-tables.nextRow", 166 | "key": "enter", 167 | "when": "tableMode" 168 | } 169 | ] 170 | }, 171 | "scripts": { 172 | "vscode:prepublish": "npm run compile", 173 | "compile": "tsc -p ./", 174 | "watch": "tsc -watch -p ./", 175 | "pretest": "npm run compile && npm run lint", 176 | "test": "node ./out/test/runTest.js", 177 | "lint": "eslint src --ext ts" 178 | }, 179 | "devDependencies": { 180 | "@types/glob": "^7.1.1", 181 | "@types/mocha": "^7.0.2", 182 | "@types/node": "^7.10.11", 183 | "@types/vscode": "^1.45.1", 184 | "@typescript-eslint/eslint-plugin": "^2.30.0", 185 | "@typescript-eslint/parser": "^2.30.0", 186 | "decache": "^4.6.0", 187 | "eslint": "^6.8.0", 188 | "glob": "^7.1.6", 189 | "mocha": "^7.2.0", 190 | "typescript": "^3.8.3", 191 | "vscode-test": "^1.3.0" 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /src/commands.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | import { Table, RowType, Stringifier, TableNavigator, Parser } from './ttTable'; 3 | 4 | /** 5 | * Create new table with specified rows and columns count in position of cursor 6 | */ 7 | export async function createTable(rowsCount: number, colsCount: number, editor: vscode.TextEditor, stringifier: Stringifier) { 8 | const table = new Table(); 9 | for (let i = 0; i < rowsCount + 1; i++) { 10 | table.addRow(RowType.Data, new Array(colsCount).fill('')); 11 | } 12 | table.rows[1].type = RowType.Separator; 13 | 14 | const currentPosition = editor.selection.start; 15 | await editor.edit(b => b.insert(currentPosition, stringifier.stringify(table))); 16 | editor.selection = new vscode.Selection(currentPosition, currentPosition); 17 | } 18 | 19 | /** 20 | * Swap row under cursor with row below 21 | */ 22 | export async function moveRowDown(editor: vscode.TextEditor, _range: vscode.Range, table: Table) { 23 | const rowNum = editor.selection.end.line - table.startLine; 24 | if (rowNum >= table.rows.length - 1) { 25 | vscode.window.showWarningMessage('Cannot move row further'); 26 | return; 27 | } 28 | await vscode.commands.executeCommand('editor.action.moveLinesDownAction'); 29 | } 30 | 31 | /** 32 | * Swap row under cursor with row above 33 | */ 34 | export async function moveRowUp(editor: vscode.TextEditor, _range: vscode.Range, table: Table) { 35 | const rowNum = editor.selection.start.line - table.startLine; 36 | if (rowNum <= 0) { 37 | vscode.window.showWarningMessage('Cannot move row further'); 38 | return; 39 | } 40 | await vscode.commands.executeCommand('editor.action.moveLinesUpAction'); 41 | } 42 | 43 | /** 44 | * Move cursor to the next cell of table 45 | */ 46 | export async function gotoNextCell(editor: vscode.TextEditor, range: vscode.Range, table: Table, 47 | stringifier: Stringifier) { 48 | 49 | const nav = new TableNavigator(table); 50 | const newPos = nav.nextCell(editor.selection.start); 51 | if (newPos) { 52 | await formatUnderCursor(editor, range, table, stringifier); 53 | editor.selection = new vscode.Selection(newPos, newPos); 54 | } else { 55 | table.addRow(RowType.Data, new Array(table.cols.length).fill('')); 56 | await gotoNextCell(editor, range, table, stringifier); 57 | } 58 | } 59 | 60 | /** 61 | * Move cursor to the previous cell of table 62 | */ 63 | export async function gotoPreviousCell(editor: vscode.TextEditor, _range: vscode.Range, table: Table) { 64 | const nav = new TableNavigator(table); 65 | const newPos = nav.previousCell(editor.selection.start); 66 | if (newPos) { 67 | editor.selection = new vscode.Selection(newPos, newPos); 68 | } 69 | } 70 | 71 | /** 72 | * Format table under cursor 73 | */ 74 | export async function formatUnderCursor(editor: vscode.TextEditor, range: vscode.Range, table: Table, stringifier: Stringifier) { 75 | const newText = stringifier.stringify(table); 76 | const prevSel = editor.selection.start; 77 | 78 | await editor.edit(e => e.replace(range, newText)); 79 | editor.selection = new vscode.Selection(prevSel, prevSel); 80 | } 81 | 82 | /** 83 | * Swap column under cursor with column on the right 84 | */ 85 | export async function moveColRight(editor: vscode.TextEditor, range: vscode.Range, table: Table, stringifier: Stringifier) { 86 | const rowCol = rowColFromPosition(table, editor.selection.start); 87 | if (rowCol.col < 0) { 88 | vscode.window.showWarningMessage('Not in table data field'); 89 | return; 90 | } 91 | 92 | if (rowCol.col >= table.cols.length - 1 ) { 93 | vscode.window.showWarningMessage('Cannot move column further right'); 94 | return; 95 | } 96 | 97 | [table.cols[rowCol.col], table.cols[rowCol.col + 1]] = [table.cols[rowCol.col + 1], table.cols[rowCol.col]]; 98 | 99 | table.rows.forEach((_, i) => { 100 | const v1 = table.getAt(i, rowCol.col); 101 | const v2 = table.getAt(i, rowCol.col + 1); 102 | table.setAt(i, rowCol.col + 1, v1); 103 | table.setAt(i, rowCol.col, v2); 104 | }); 105 | 106 | const newText = stringifier.stringify(table); 107 | await editor.edit(e => e.replace(range, newText)); 108 | await gotoNextCell(editor, range, table, stringifier); 109 | } 110 | 111 | /** 112 | * Swap column under cursor with column on the left 113 | */ 114 | export async function moveColLeft(editor: vscode.TextEditor, range: vscode.Range, table: Table, stringifier: Stringifier) { 115 | const rowCol = rowColFromPosition(table, editor.selection.start); 116 | if (rowCol.col < 0) { 117 | vscode.window.showWarningMessage('Not in table data field'); 118 | return; 119 | } 120 | 121 | if (rowCol.col === 0) { 122 | vscode.window.showWarningMessage('Cannot move column further left'); 123 | return; 124 | } 125 | 126 | [table.cols[rowCol.col], table.cols[rowCol.col - 1]] = [table.cols[rowCol.col - 1], table.cols[rowCol.col]]; 127 | 128 | table.rows.forEach((_, i) => { 129 | const v1 = table.getAt(i, rowCol.col); 130 | const v2 = table.getAt(i, rowCol.col - 1); 131 | table.setAt(i, rowCol.col - 1, v1); 132 | table.setAt(i, rowCol.col, v2); 133 | }); 134 | 135 | const newText = stringifier.stringify(table); 136 | await editor.edit(e => e.replace(range, newText)); 137 | await gotoPreviousCell(editor, range, table); 138 | } 139 | 140 | /** 141 | * Clear cell under cursor 142 | */ 143 | export function clearCell(editor: vscode.TextEditor, edit: vscode.TextEditorEdit, parser: Parser) { 144 | const document = editor.document; 145 | const currentLineNumber = editor.selection.start.line; 146 | const currentLine = document.lineAt(currentLineNumber); 147 | 148 | if (parser.isSeparatorRow(currentLine.text)) { 149 | vscode.window.showInformationMessage('Not in table data field'); 150 | return; 151 | } 152 | 153 | const leftSepPosition = currentLine.text.lastIndexOf('|', editor.selection.start.character - 1); 154 | let rightSepPosition = currentLine.text.indexOf('|', editor.selection.start.character); 155 | if (rightSepPosition < 0) { 156 | rightSepPosition = currentLine.range.end.character; 157 | } 158 | 159 | if (leftSepPosition === rightSepPosition) { 160 | vscode.window.showInformationMessage('Not in table data field'); 161 | return; 162 | } 163 | 164 | const r = new vscode.Range(currentLineNumber, leftSepPosition + 1, currentLineNumber, rightSepPosition); 165 | edit.replace(r, ' '.repeat(rightSepPosition - leftSepPosition - 1)); 166 | const newPos = new vscode.Position(currentLineNumber, leftSepPosition + 2); 167 | editor.selection = new vscode.Selection(newPos, newPos); 168 | } 169 | 170 | /** 171 | * Moves cursor to the next row. If cursor is in the last row of table, create new row 172 | */ 173 | export async function nextRow(editor: vscode.TextEditor, range: vscode.Range, table: Table, stringifier: Stringifier) { 174 | const inLastRow = range.end.line === editor.selection.start.line; 175 | 176 | if (inLastRow) { 177 | table.addRow(RowType.Data, new Array(table.cols.length).fill('')); 178 | } 179 | 180 | await editor.edit(b => b.replace(range, stringifier.stringify(table))); 181 | 182 | const nav = new TableNavigator(table); 183 | const nextRowPos = nav.nextRow(editor.selection.start); 184 | if (nextRowPos) { 185 | editor.selection = new vscode.Selection(nextRowPos, nextRowPos); 186 | } 187 | } 188 | 189 | function rowColFromPosition(table: Table, position: vscode.Position): { row: number, col: number } { 190 | const result = { row: -1, col: -1 }; 191 | 192 | result.row = position.line - table.startLine; 193 | let counter = 1; 194 | for (let i = 0; i < table.cols.length; ++i) { 195 | const col = table.cols[i]; 196 | if (position.character >= counter && position.character < counter + col.width + 3) { 197 | result.col = i; 198 | break; 199 | } 200 | 201 | counter += col.width + 3; 202 | } 203 | 204 | return result; 205 | } 206 | -------------------------------------------------------------------------------- /src/configuration.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | 3 | export const section = 'text-tables'; 4 | 5 | export const modeKey = 'mode'; 6 | export const showStatusKey = 'showStatus'; 7 | 8 | export enum Mode { 9 | Org = 'org', 10 | Markdown = 'markdown' 11 | } 12 | 13 | export interface Configuration { 14 | mode: Mode; 15 | showStatus: boolean; 16 | } 17 | 18 | export function build(): Configuration { 19 | const c = vscode.workspace.getConfiguration(section); 20 | 21 | return { 22 | mode: c.get(modeKey, Mode.Markdown), 23 | showStatus: c.get(showStatusKey, true) 24 | }; 25 | } 26 | 27 | export async function override(overrides: any) { 28 | const c = vscode.workspace.getConfiguration(section); 29 | for (const k of Object.keys(overrides)) { 30 | await c.update(k, overrides[k], false); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/context.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | 3 | export enum ContextType { 4 | TableMode = 'tableMode' 5 | } 6 | 7 | const contexts: Map = new Map(); 8 | const state: Map = new Map(); 9 | 10 | export function registerContext(type: ContextType, title: string, statusItem?: vscode.StatusBarItem) { 11 | const ctx = new Context(type, title, statusItem); 12 | contexts.set(type, ctx); 13 | ctx.setState(false); 14 | } 15 | 16 | export function enterContext(editor: vscode.TextEditor, type: ContextType) { 17 | const ctx = contexts.get(type); 18 | if (ctx) { 19 | ctx.setState(true); 20 | 21 | const editorState = state.get(editor.document.fileName) || []; 22 | state.set(editor.document.fileName, editorState.concat(type)); 23 | } 24 | } 25 | 26 | export function exitContext(editor: vscode.TextEditor, type: ContextType) { 27 | const ctx = contexts.get(type); 28 | if (ctx) { 29 | ctx.setState(false); 30 | 31 | const editorState = state.get(editor.document.fileName) || []; 32 | state.set(editor.document.fileName, editorState.filter(x => x !== type)); 33 | } 34 | } 35 | 36 | export function restoreContext(editor: vscode.TextEditor) { 37 | let toEnter: ContextType[] = []; 38 | // @ts-ignore 39 | let toExit: ContextType[] = Object.keys(ContextType).map((x: any) => ContextType[x] as ContextType); 40 | 41 | if (state.has(editor.document.fileName)) { 42 | toEnter = state.get(editor.document.fileName)!; 43 | toExit = toExit.filter(x => toEnter.indexOf(x) < 0); 44 | } 45 | 46 | toEnter.forEach(x => enterContext(editor, x)); 47 | toExit.forEach(x => exitContext(editor, x)); 48 | } 49 | 50 | class Context { 51 | constructor(private type: ContextType, private title: string, private statusItem?: vscode.StatusBarItem) { 52 | 53 | } 54 | 55 | setState(isEnabled: boolean) { 56 | vscode.commands.executeCommand('setContext', this.type, isEnabled); 57 | if (this.statusItem) { 58 | const stateText = isEnabled ? 'On' : 'Off'; 59 | this.statusItem.text = `${this.title}: ${stateText}`; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/extension.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import * as vscode from 'vscode'; 4 | import * as utils from './utils'; 5 | import * as cmd from './commands'; 6 | import { OrgLocator, OrgParser, OrgStringifier } from './ttOrg'; 7 | import { Locator, Parser, Stringifier, Table } from './ttTable'; 8 | import { MarkdownLocator, MarkdownParser, MarkdownStringifier } from './ttMarkdown'; 9 | import { isUndefined } from 'util'; 10 | import { registerContext, ContextType, enterContext, exitContext, restoreContext } from './context'; 11 | import * as cfg from './configuration'; 12 | 13 | let locator: Locator; 14 | let parser: Parser; 15 | let stringifier: Stringifier; 16 | let configuration: cfg.Configuration; 17 | 18 | function loadConfiguration() { 19 | configuration = cfg.build(); 20 | 21 | if (configuration.mode === cfg.Mode.Org) { 22 | locator = new OrgLocator(); 23 | parser = new OrgParser(); 24 | stringifier = new OrgStringifier(); 25 | } else { 26 | locator = new MarkdownLocator(); 27 | parser = new MarkdownParser(); 28 | stringifier = new MarkdownStringifier(); 29 | } 30 | } 31 | 32 | export function activate(ctx: vscode.ExtensionContext) { 33 | loadConfiguration(); 34 | 35 | const statusItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); 36 | registerContext(ContextType.TableMode, '$(book) Table Mode', statusItem); 37 | 38 | if (configuration.showStatus) { 39 | statusItem.show(); 40 | } 41 | 42 | vscode.workspace.onDidChangeConfiguration(() => { 43 | loadConfiguration(); 44 | 45 | if (configuration.showStatus) { 46 | statusItem.show(); 47 | } else { 48 | statusItem.hide(); 49 | } 50 | }); 51 | 52 | vscode.window.onDidChangeActiveTextEditor(e => { 53 | if (e) { 54 | restoreContext(e); 55 | } 56 | }); 57 | 58 | ctx.subscriptions.push(vscode.commands.registerCommand('text-tables.enable', () => { 59 | vscode.window.showInformationMessage('Text tables enabled!'); 60 | })); 61 | 62 | ctx.subscriptions.push(vscode.commands.registerTextEditorCommand('text-tables.tableModeOn', 63 | (e) => enterContext(e, ContextType.TableMode))); 64 | ctx.subscriptions.push(vscode.commands.registerTextEditorCommand('text-tables.tableModeOff', 65 | (e) => exitContext(e, ContextType.TableMode))); 66 | 67 | ctx.subscriptions.push(registerTableCommand('text-tables.moveRowDown', cmd.moveRowDown, {format: true})); 68 | ctx.subscriptions.push(registerTableCommand('text-tables.moveRowUp', cmd.moveRowUp, {format: true})); 69 | ctx.subscriptions.push(registerTableCommand('text-tables.moveColRight', async (editor, range, table) => { 70 | await cmd.moveColRight(editor, range, table, stringifier); 71 | })); 72 | ctx.subscriptions.push(registerTableCommand('text-tables.moveColLeft', async (editor, range, table) => { 73 | await cmd.moveColLeft(editor, range, table, stringifier); 74 | })); 75 | 76 | ctx.subscriptions.push(vscode.commands.registerTextEditorCommand('text-tables.clearCell', 77 | (e, ed) => cmd.clearCell(e, ed, parser))); 78 | 79 | ctx.subscriptions.push(registerTableCommand('text-tables.gotoNextCell', async (editor, range, table) => { 80 | await cmd.gotoNextCell(editor, range, table, stringifier); 81 | })); 82 | 83 | ctx.subscriptions.push(registerTableCommand('text-tables.gotoPreviousCell', cmd.gotoPreviousCell, {format: true})); 84 | ctx.subscriptions.push(registerTableCommand('text-tables.nextRow', async (editor, range, table) => { 85 | await cmd.nextRow(editor, range, table, stringifier); 86 | })); 87 | 88 | // Format table under cursor 89 | ctx.subscriptions.push(registerTableCommand('text-tables.formatUnderCursor', 90 | (editor, range, table) => cmd.formatUnderCursor(editor, range, table, stringifier))); 91 | 92 | ctx.subscriptions.push(vscode.commands.registerTextEditorCommand('text-tables.createTable', async editor => { 93 | const opts: vscode.InputBoxOptions = { 94 | value: '5x2', 95 | prompt: 'Table size Columns x Rows (e.g. 5x2)', 96 | validateInput: (value: string) => { 97 | if (!utils.tableSizeRe.test(value)) { 98 | return 'Provided value is invalid. Please provide the value in format Columns x Rows (e.g. 5x2)'; 99 | } 100 | return; 101 | } 102 | }; 103 | 104 | const size = await vscode.window.showInputBox(opts); 105 | if (size) { 106 | const match = size.match(utils.tableSizeRe); 107 | if (match) { 108 | const cols = +match[1] || 1; 109 | const rows = +match[2] || 2; 110 | cmd.createTable(rows, cols, editor, stringifier); 111 | } 112 | } 113 | })); 114 | } 115 | 116 | export function deactivate() { 117 | } 118 | 119 | type TableCommandCallback = (editor: vscode.TextEditor, tableLocation: vscode.Range, table: Table) => Thenable; 120 | 121 | function registerTableCommand(command: string, callback: TableCommandCallback, options?: {format: boolean}) { 122 | return vscode.commands.registerCommand(command, async () => { 123 | const editor = vscode.window.activeTextEditor; 124 | 125 | if (isUndefined(editor)) { 126 | return; 127 | } 128 | 129 | const tableRange = locator.locate(editor.document, editor.selection.start.line); 130 | if (isUndefined(tableRange)) { 131 | return; 132 | } 133 | const selectedText = editor.document.getText(tableRange); 134 | const table = parser.parse(selectedText); 135 | 136 | if (isUndefined(table)) { 137 | return; 138 | } 139 | 140 | table.startLine = tableRange.start.line; 141 | 142 | if (options && options.format) { 143 | await cmd.formatUnderCursor(editor, tableRange, table, stringifier); 144 | } 145 | 146 | await callback(editor, tableRange, table); 147 | }); 148 | } 149 | -------------------------------------------------------------------------------- /src/ttMarkdown.ts: -------------------------------------------------------------------------------- 1 | import * as tt from './ttTable'; 2 | import * as vscode from 'vscode'; 3 | import { RowType } from './ttTable'; 4 | 5 | const verticalSeparator = '|'; 6 | const horizontalSeparator = '-'; 7 | 8 | type StringReducer = (previous: string, current: string, index: number) => string; 9 | 10 | export class MarkdownParser implements tt.Parser { 11 | parse(text: string): tt.Table | undefined { 12 | if (!text || text.length === 0) { 13 | return undefined; 14 | } 15 | 16 | const result = new tt.Table(); 17 | const strings = text.split('\n').map(x => x.trim()).filter(x => x.startsWith(verticalSeparator)); 18 | 19 | for (const s of strings) { 20 | const cleanedString = s.replace(/\s+/g, ''); 21 | 22 | if (this.isSeparatorRow(cleanedString)) { 23 | result.addRow(tt.RowType.Separator, []); 24 | const startIndex = cleanedString.startsWith(verticalSeparator) ? 1 : 0; 25 | const endIndex = cleanedString.length - (cleanedString.endsWith(verticalSeparator) ? 1 : 0); 26 | const rowParts = cleanedString.slice(startIndex, endIndex).split('|'); 27 | 28 | rowParts.forEach((part, i) => { 29 | if (part.length < 3) { 30 | return; 31 | } 32 | const trimmed = part.trim(); 33 | let align = tt.Alignment.Left; 34 | if (trimmed[trimmed.length - 1] === ':') { 35 | if (trimmed[0] === ':') { 36 | align = tt.Alignment.Center; 37 | } else { 38 | align = tt.Alignment.Right; 39 | } 40 | } 41 | const col = result.cols[i]; 42 | if (col) { 43 | col.alignment = align; 44 | } else { 45 | result.cols.push({ alignment: align, width: 3 }); 46 | } 47 | }); 48 | 49 | continue; 50 | } 51 | 52 | const lastIndex = s.length - (s.endsWith(verticalSeparator) ? 1 : 0); 53 | 54 | const values = s 55 | .slice(1, lastIndex) 56 | .split(verticalSeparator) 57 | .map(x => x.trim()); 58 | 59 | result.addRow(tt.RowType.Data, values); 60 | } 61 | 62 | if (result.rows.some(x => x.type === RowType.Separator)) { 63 | result.cols.forEach(x => x.width = Math.max(x.width, 3)); 64 | } 65 | 66 | return result; 67 | } 68 | 69 | isSeparatorRow(text: string): boolean { 70 | const cleaned = text.replace(/\s+/g, ''); 71 | return cleaned.startsWith('|-') || cleaned.startsWith('|:-'); 72 | } 73 | } 74 | 75 | export class MarkdownStringifier implements tt.Stringifier { 76 | private reducers = new Map([ 77 | [tt.RowType.Data, this.dataRowReducer], 78 | [tt.RowType.Separator, this.separatorReducer], 79 | ]); 80 | 81 | stringify(table: tt.Table): string { 82 | const result = []; 83 | 84 | if (table.rows.some(x => x.type === RowType.Separator)) { 85 | table.cols.forEach(x => x.width = Math.max(x.width, 3)); 86 | } 87 | 88 | for (let i = 0; i < table.rows.length; ++i) { 89 | let rowString = ''; 90 | const rowData = table.getRow(i); 91 | const reducer = this.reducers.get(table.rows[i].type); 92 | if (reducer) { 93 | rowString = rowData.reduce(reducer(table.cols), verticalSeparator); 94 | } 95 | result.push(rowString); 96 | } 97 | 98 | return result.join('\n'); 99 | } 100 | 101 | private dataRowReducer(cols: tt.ColDef[]): StringReducer { 102 | return (prev, cur, idx) => { 103 | const pad = ' '.repeat(cols[idx].width - cur.length + 1); 104 | return prev + ' ' + cur + pad + verticalSeparator; 105 | }; 106 | } 107 | 108 | private separatorReducer(cols: tt.ColDef[]): StringReducer { 109 | return (prev, _, idx) => { 110 | const begin = cols[idx].alignment === tt.Alignment.Center 111 | ? ' :' 112 | : ' -'; 113 | const ending = cols[idx].alignment !== tt.Alignment.Left 114 | ? ': ' + verticalSeparator 115 | : '- ' + verticalSeparator; 116 | 117 | const middle = horizontalSeparator.repeat(cols[idx].width - 2); 118 | 119 | return prev + begin + middle + ending; 120 | }; 121 | } 122 | } 123 | 124 | export class MarkdownLocator implements tt.Locator { 125 | locate(reader: tt.LineReader, lineNr: number): vscode.Range | undefined { 126 | const isTableLikeString = (ln: number) => { 127 | if (ln < 0 || ln >= reader.lineCount) { 128 | return false; 129 | } 130 | const firstCharIdx = reader.lineAt(ln).firstNonWhitespaceCharacterIndex; 131 | const firstChar = reader.lineAt(ln).text[firstCharIdx]; 132 | return firstChar === '|'; 133 | }; 134 | 135 | let start = lineNr; 136 | while (isTableLikeString(start)) { 137 | start--; 138 | } 139 | 140 | let end = lineNr; 141 | while (isTableLikeString(end)) { 142 | end++; 143 | } 144 | 145 | if (start === end) { 146 | return undefined; 147 | } 148 | 149 | const startPos = reader.lineAt(start + 1).range.start; 150 | const endPos = reader.lineAt(end - 1).range.end; 151 | 152 | return new vscode.Range(startPos, endPos); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/ttOrg.ts: -------------------------------------------------------------------------------- 1 | import * as tt from './ttTable'; 2 | import * as vscode from 'vscode'; 3 | 4 | const verticalSeparator = '|'; 5 | const horizontalSeparator = '-'; 6 | const intersection = '+'; 7 | 8 | type StringReducer = (previous: string, current: string, index: number) => string; 9 | 10 | export class OrgParser implements tt.Parser { 11 | parse(text: string): tt.Table | undefined { 12 | if (!text || text.length === 0) { 13 | return undefined; 14 | } 15 | 16 | const result = new tt.Table(); 17 | const strings = text.split('\n').map(x => x.trim()).filter(x => x.startsWith(verticalSeparator)); 18 | 19 | for (const s of strings) { 20 | if (this.isSeparatorRow(s)) { 21 | result.addRow(tt.RowType.Separator, []); 22 | continue; 23 | } 24 | 25 | const lastIndex = s.length - (s.endsWith(verticalSeparator) ? 1 : 0); 26 | const values = s 27 | .slice(1, lastIndex) 28 | .split(verticalSeparator) 29 | .map(x => x.trim()); 30 | 31 | result.addRow(tt.RowType.Data, values); 32 | } 33 | 34 | return result; 35 | } 36 | 37 | isSeparatorRow(text: string): boolean { 38 | return text.length > 1 && text[1] === horizontalSeparator; 39 | } 40 | } 41 | 42 | export class OrgStringifier implements tt.Stringifier { 43 | private reducers = new Map([ 44 | [tt.RowType.Data, this.dataRowReducer], 45 | [tt.RowType.Separator, this.separatorReducer], 46 | ]); 47 | 48 | stringify(table: tt.Table): string { 49 | const result = []; 50 | 51 | for (let i = 0; i < table.rows.length; ++i) { 52 | let rowString = ''; 53 | const rowData = table.getRow(i); 54 | const reducer = this.reducers.get(table.rows[i].type); 55 | if (reducer) { 56 | rowString = rowData.reduce(reducer(table.cols), verticalSeparator); 57 | } 58 | 59 | result.push(rowString); 60 | } 61 | 62 | return result.join('\n'); 63 | } 64 | 65 | private dataRowReducer(cols: tt.ColDef[]): StringReducer { 66 | return (prev, cur, idx) => { 67 | const pad = ' '.repeat(cols[idx].width - cur.length + 1); 68 | return prev + ' ' + cur + pad + verticalSeparator; 69 | }; 70 | } 71 | 72 | private separatorReducer(cols: tt.ColDef[]): (p: string, c: string, i: number) => string { 73 | return (prev, _, idx) => { 74 | // Intersections for each cell are '+', except the last one, where it should be '|' 75 | const ending = (idx === cols.length - 1) 76 | ? verticalSeparator 77 | : intersection; 78 | 79 | return prev + horizontalSeparator.repeat(cols[idx].width + 2) + ending; 80 | }; 81 | } 82 | } 83 | 84 | export class OrgLocator implements tt.Locator { 85 | /** 86 | * Locate start and end of Org table in text from line number. 87 | * 88 | * @param reader Reader that is able to read line by line 89 | * @param lineNr Current line number 90 | * @returns vscode.Range if table was located. undefined if it failed 91 | */ 92 | locate(reader: tt.LineReader, lineNr: number): vscode.Range | undefined { 93 | 94 | // Checks that line starts with vertical bar 95 | const isTableLikeString = (ln: number) => { 96 | if (ln < 0 || ln >= reader.lineCount) { 97 | return false; 98 | } 99 | const line = reader.lineAt(ln); 100 | const firstCharIdx = line.firstNonWhitespaceCharacterIndex; 101 | const firstChar = line.text[firstCharIdx]; 102 | return firstChar === '|'; 103 | }; 104 | 105 | let start = lineNr; 106 | while (isTableLikeString(start)) { 107 | start--; 108 | } 109 | 110 | let end = lineNr; 111 | while (isTableLikeString(end)) { 112 | end++; 113 | } 114 | 115 | if (start === end) { 116 | return undefined; 117 | } 118 | 119 | const startPos = reader.lineAt(start + 1).range.start; 120 | const endPos = reader.lineAt(end - 1).range.end; 121 | 122 | return new vscode.Range(startPos, endPos); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/ttTable.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | 3 | export enum RowType { 4 | Unknown, 5 | Separator, 6 | Data 7 | } 8 | 9 | export enum Alignment { 10 | Left, 11 | Center, 12 | Right 13 | } 14 | 15 | export interface RowDef { 16 | type: RowType; 17 | } 18 | 19 | export interface ColDef { 20 | alignment: Alignment; 21 | width: number; 22 | } 23 | 24 | export class Table { 25 | /** 26 | * Line where the table starts 27 | */ 28 | startLine = 0; 29 | 30 | rows: RowDef[] = []; 31 | cols: ColDef[] = []; 32 | 33 | private data: string[][] = []; 34 | 35 | addRow(type: RowType, values: string[]) { 36 | let adjustCount = values.length - this.cols.length; 37 | while (adjustCount-- > 0) { 38 | this.cols.push({ alignment: Alignment.Left, width: 0 }); 39 | } 40 | 41 | for (const row of this.data) { 42 | const adjustee = row.length < values.length ? row : values; 43 | adjustCount = Math.abs(row.length - values.length); 44 | 45 | while (adjustCount-- > 0) { 46 | adjustee.push(''); 47 | } 48 | } 49 | 50 | this.cols.forEach((col, i) => col.width = Math.max(col.width, values[i].length)); 51 | 52 | this.rows.push({ type }); 53 | this.data.push(values); 54 | } 55 | 56 | getAt(row: number, col: number): string { 57 | return this.data[row][col]; 58 | } 59 | 60 | getRow(row: number): string[] { 61 | return this.data[row]; 62 | } 63 | 64 | setAt(row: number, col: number, value: string) { 65 | if (this.cols[col].width < value.length) { 66 | this.cols[col].width = value.length; 67 | } 68 | 69 | this.data[row][col] = value; 70 | } 71 | } 72 | 73 | export interface Parser { 74 | parse(text: string): Table | undefined; 75 | isSeparatorRow(text: string): boolean; 76 | } 77 | 78 | export interface Stringifier { 79 | stringify(table: Table): string; 80 | } 81 | 82 | export interface Locator { 83 | locate(reader: LineReader, lineNr: number): vscode.Range | undefined; 84 | } 85 | 86 | export interface LineReader { 87 | lineAt(line: number): vscode.TextLine; 88 | lineCount: number; 89 | } 90 | 91 | class JumpPosition { 92 | constructor(start: vscode.Position, end: vscode.Position, public isSeparator: boolean, prev?: JumpPosition) { 93 | this.range = new vscode.Range(start, end); 94 | 95 | if (prev) { 96 | prev.next = this; 97 | this.prev = prev; 98 | } 99 | } 100 | 101 | range: vscode.Range; 102 | next?: JumpPosition; 103 | prev?: JumpPosition; 104 | } 105 | 106 | export class TableNavigator { 107 | private jumpPositions: JumpPosition[] = []; 108 | 109 | constructor(public table: Table) { 110 | this.jumpPositions = this.buildJumpPositions(); 111 | } 112 | 113 | nextCell(cursorPosition: vscode.Position): vscode.Position | undefined { 114 | return this.jump(cursorPosition, x => x.next!); 115 | } 116 | 117 | previousCell(cursorPosition: vscode.Position): vscode.Position | undefined { 118 | return this.jump(cursorPosition, x => x.prev!); 119 | } 120 | 121 | nextRow(cursorPosition: vscode.Position): vscode.Position | undefined { 122 | const nextRowJump = this.jumpPositions.find(x => x.range.contains(cursorPosition.translate(1))); 123 | if (!nextRowJump) { 124 | return undefined; 125 | } 126 | 127 | return nextRowJump.range.start.translate(0, 1); 128 | } 129 | 130 | private jump(currentPosition: vscode.Position, accessor: (x: JumpPosition) => JumpPosition): vscode.Position | undefined { 131 | let jmp = this.jumpPositions.find(x => x.range.contains(currentPosition)); 132 | if (jmp) { 133 | jmp = accessor(jmp); 134 | if (jmp) { 135 | if (jmp.isSeparator) { 136 | if (!accessor(jmp)) { 137 | return undefined; 138 | } 139 | jmp = accessor(jmp); 140 | } 141 | return jmp.range.start.translate(0, 1); 142 | } 143 | } 144 | 145 | // Maybe we're just outside left part of table? Let's move cursor a bit... 146 | if (currentPosition.character === 0) { 147 | return currentPosition.translate(0, 2); 148 | } else { 149 | return undefined; 150 | } 151 | } 152 | 153 | private buildJumpPositions(): JumpPosition[] { 154 | const result: JumpPosition[] = []; 155 | 156 | const cellPadding = 2; 157 | let lastAnchor = 0; 158 | const anchors = this.table.cols.reduce((accum, col) => { 159 | lastAnchor += col.width + cellPadding + 1; 160 | accum.push(lastAnchor); 161 | return accum; 162 | }, [lastAnchor]); 163 | // extend last point to "infinity" 164 | anchors[anchors.length - 1] = 999; 165 | 166 | for (let i = 0; i < this.table.rows.length; ++i) { 167 | const row = this.table.rows[i]; 168 | const rowLine = this.table.startLine + i; 169 | 170 | if (row.type === RowType.Separator) { 171 | const prevJmpPos = result[result.length - 1]; 172 | // Extend last range to whole separator line or start from beginning of line 173 | const start = prevJmpPos 174 | ? prevJmpPos.range.end 175 | : new vscode.Position(rowLine, 0); 176 | const end = start.translate(1); 177 | const jmpPos = new JumpPosition(start, end, true, prevJmpPos); 178 | result.push(jmpPos); 179 | } else { 180 | for (let j = 0; j < anchors.length - 1; ++j) { 181 | const prevJmpPos = result[result.length - 1]; 182 | const start = new vscode.Position(rowLine, anchors[j] + 1); 183 | const end = new vscode.Position(rowLine, anchors[j + 1]); 184 | const jmpPos = new JumpPosition(start, end, false, prevJmpPos); 185 | result.push(jmpPos); 186 | } 187 | } 188 | } 189 | return result; 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | export const tableSizeRe = /^(\d+)x(\d+)$/u; 2 | -------------------------------------------------------------------------------- /test/commands.test.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | import * as assert from 'assert'; 3 | import * as cfg from '../src/configuration'; 4 | 5 | import * as cmd from '../src/commands'; 6 | import { MarkdownStringifier } from '../src/ttMarkdown'; 7 | import { OrgStringifier } from '../src/ttOrg'; 8 | 9 | async function inTextEditor(options: { language?: string; content?: string; }, 10 | cb: (editor: vscode.TextEditor, document: vscode.TextDocument) => void) { 11 | const d = await vscode.workspace.openTextDocument(options); 12 | await vscode.window.showTextDocument(d); 13 | await cb(vscode.window.activeTextEditor!, d); 14 | } 15 | 16 | function move(editor: vscode.TextEditor, line: number, col: number) { 17 | const pos = new vscode.Position(line, col); 18 | editor.selection = new vscode.Selection(pos, pos); 19 | } 20 | 21 | suite('Commands', () => { 22 | test('Test "Create table" for markdown', async () => { 23 | const expectedResult = `| | | 24 | | --- | --- | 25 | | | |`; 26 | 27 | await inTextEditor({language: 'markdown'}, async (editor, document) => { 28 | await cfg.override({'mode': cfg.Mode.Markdown}); 29 | await cmd.createTable(2, 2, editor, new MarkdownStringifier()); 30 | assert.equal(document.getText(), expectedResult); 31 | }); 32 | }).timeout(10000); 33 | 34 | test('Test "Create table" for org', async () => { 35 | const expectedResult = `| | | 36 | |--+--| 37 | | | |`; 38 | 39 | await inTextEditor({language: 'org'}, async (editor, document) => { 40 | await cfg.override({'mode': cfg.Mode.Org}); 41 | await cmd.createTable(2, 2, editor, new OrgStringifier()); 42 | assert.equal(document.getText(), expectedResult); 43 | }); 44 | }); 45 | 46 | test('Test "Clear cell"', async () => { 47 | const testCase = 48 | `| Hello | World | Some other text 49 | | ----- | ----- |`; 50 | const expectedResult = 51 | `| | World | \n` + 52 | `| ----- | ----- |`; 53 | 54 | await inTextEditor({language: 'markdown', content: testCase}, async (editor, document) => { 55 | await cfg.override({mode: 'markdown'}); 56 | await vscode.commands.executeCommand('text-tables.clearCell'); 57 | move(editor, 0, 2); 58 | await vscode.commands.executeCommand('text-tables.clearCell'); 59 | move(editor, 0, 17); 60 | await vscode.commands.executeCommand('text-tables.clearCell'); 61 | move(editor, 1, 2); 62 | await vscode.commands.executeCommand('text-tables.clearCell'); 63 | assert.equal(document.getText(), expectedResult); 64 | }); 65 | }); 66 | 67 | test('Test "Go to next cell"', async () => { 68 | const input = `| | | 69 | |--+--| 70 | | | |`; 71 | const expected = `| | | 72 | |--+--| 73 | | | | 74 | | | |`; 75 | 76 | const testCases = [ 77 | new vscode.Position(0, 2), 78 | new vscode.Position(0, 5), 79 | new vscode.Position(2, 2), 80 | new vscode.Position(2, 5), 81 | new vscode.Position(3, 2), 82 | new vscode.Position(3, 5), 83 | ]; 84 | 85 | await inTextEditor({language: 'markdown', content: input}, async (editor, document) => { 86 | await cfg.override({mode: 'org'}); 87 | for (const t of testCases) { 88 | await vscode.commands.executeCommand('text-tables.gotoNextCell'); 89 | assert.deepEqual(editor.selection.start, t); 90 | } 91 | 92 | assert.equal(document.getText(), expected); 93 | }); 94 | }); 95 | 96 | test('Test "Go to previous cell"', async () => { 97 | const input = `| | | 98 | |--+--| 99 | | | |`; 100 | 101 | const testCases = [ 102 | new vscode.Position(2, 2), 103 | new vscode.Position(0, 5), 104 | new vscode.Position(0, 2), 105 | // Repeated intentionally to check that it won't jump outside 106 | new vscode.Position(0, 2), 107 | ]; 108 | 109 | await inTextEditor({language: 'markdown', content: input}, async (editor, _) => { 110 | await cfg.override({mode: 'org'}); 111 | move(editor, 2, 5); 112 | for (const t of testCases) { 113 | await vscode.commands.executeCommand('text-tables.gotoPreviousCell'); 114 | assert.deepEqual(editor.selection.start, t); 115 | } 116 | }); 117 | }); 118 | 119 | test('Test "Move row down"', async () => { 120 | const input = `| 1 | 2 | 121 | |---+---| 122 | | 3 | 4 |`; 123 | 124 | const steps = [ 125 | `|---+---| 126 | | 1 | 2 | 127 | | 3 | 4 |` 128 | , 129 | `|---+---| 130 | | 3 | 4 | 131 | | 1 | 2 |`, 132 | `|---+---| 133 | | 3 | 4 | 134 | | 1 | 2 |` 135 | ]; 136 | 137 | await inTextEditor({language: 'org', content: input}, async (_, document) => { 138 | await cfg.override({mode: 'org'}); 139 | 140 | for (const expected of steps) { 141 | await vscode.commands.executeCommand('text-tables.moveRowDown'); 142 | assert.equal(document.getText(), expected); 143 | } 144 | }); 145 | }); 146 | 147 | test('Test "Move row up"', async () => { 148 | const input = 149 | `|---+---| 150 | | 3 | 4 | 151 | | 1 | 2 |`; 152 | 153 | const steps = [ 154 | `|---+---| 155 | | 1 | 2 | 156 | | 3 | 4 |` 157 | , 158 | `| 1 | 2 | 159 | |---+---| 160 | | 3 | 4 |` 161 | , 162 | `| 1 | 2 | 163 | |---+---| 164 | | 3 | 4 |` 165 | 166 | ]; 167 | 168 | await inTextEditor({language: 'org', content: input}, async (editor, document) => { 169 | await cfg.override({mode: 'org'}); 170 | move(editor, 2, 0); 171 | for (const expected of steps) { 172 | await vscode.commands.executeCommand('text-tables.moveRowUp'); 173 | assert.equal(document.getText(), expected); 174 | } 175 | }); 176 | }); 177 | 178 | test('Test "Move col right"', async () => { 179 | const input = 180 | `| 1 | 2 | 3 | 181 | | 4 | 5 | 6 |`; 182 | 183 | const steps = [ 184 | `| 2 | 1 | 3 | 185 | | 5 | 4 | 6 |` 186 | , 187 | `| 2 | 3 | 1 | 188 | | 5 | 6 | 4 |` 189 | , 190 | `| 2 | 3 | 1 | 191 | | 5 | 6 | 4 |` 192 | 193 | ]; 194 | 195 | await inTextEditor({language: 'org', content: input}, async (editor, document) => { 196 | await cfg.override({mode: 'org'}); 197 | move(editor, 0, 2); 198 | for (const expected of steps) { 199 | await vscode.commands.executeCommand('text-tables.moveColRight'); 200 | assert.equal(document.getText(), expected); 201 | } 202 | }); 203 | }); 204 | 205 | test('Test "Move col left"', async () => { 206 | const input = 207 | `| 1 | 2 | 3 | 208 | | 4 | 5 | 6 |`; 209 | 210 | const steps = [ 211 | `| 1 | 3 | 2 | 212 | | 4 | 6 | 5 |` 213 | , 214 | `| 3 | 1 | 2 | 215 | | 6 | 4 | 5 |` 216 | , 217 | `| 3 | 1 | 2 | 218 | | 6 | 4 | 5 |` 219 | ]; 220 | 221 | await inTextEditor({language: 'org', content: input}, async (editor, document) => { 222 | await cfg.override({mode: 'org'}); 223 | move(editor, 0, 10); 224 | for (const expected of steps) { 225 | await vscode.commands.executeCommand('text-tables.moveColLeft'); 226 | assert.equal(document.getText(), expected); 227 | } 228 | }); 229 | }); 230 | 231 | test('Test "Format under cursor"', async () => { 232 | const input = 233 | `| 1 | 2 | 3 | 234 | | 4 | 5 | 6 |`; 235 | 236 | const expected = 237 | `| 1 | 2 | 3 | 238 | | 4 | 5 | 6 |`; 239 | 240 | await inTextEditor({language: 'org', content: input}, async (_, document) => { 241 | await cfg.override({mode: 'org'}); 242 | 243 | await vscode.commands.executeCommand('text-tables.formatUnderCursor'); 244 | assert.equal(document.getText(), expected); 245 | }); 246 | }); 247 | 248 | test('Test "Format under cursor" for markdown', async () => { 249 | const input = 250 | `| 1 | 2 | 251 | | --- | 252 | | 4 | 5 | 6 |`; 253 | 254 | const expected = 255 | `| 1 | 2 | | 256 | | --- | --- | --- | 257 | | 4 | 5 | 6 |`; 258 | 259 | await inTextEditor({language: 'markdown', content: input}, async (_, document) => { 260 | await cfg.override({mode: 'markdown'}); 261 | 262 | await vscode.commands.executeCommand('text-tables.formatUnderCursor'); 263 | assert.equal(document.getText(), expected); 264 | }); 265 | }); 266 | 267 | test('Test "Next Row"', async () => { 268 | const input = 269 | `| Row | 270 | | Row2 |`; 271 | 272 | const steps = [ 273 | `| Row | 274 | | Row2 |` 275 | , 276 | `| Row | 277 | | Row2 | 278 | | |` 279 | , 280 | `| Row | 281 | | Row2 | 282 | | | 283 | | |` 284 | ]; 285 | 286 | await inTextEditor({language: 'org', content: input}, async (editor, document) => { 287 | await cfg.override({mode: 'org'}); 288 | move(editor, 0, 2); 289 | for (const expected of steps) { 290 | await vscode.commands.executeCommand('text-tables.nextRow'); 291 | assert.equal(document.getText(), expected); 292 | } 293 | }); 294 | }); 295 | }); 296 | -------------------------------------------------------------------------------- /test/index.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import * as Mocha from 'mocha'; 3 | import * as glob from 'glob'; 4 | 5 | export function run(): Promise { 6 | // Create the mocha test 7 | const mocha = new Mocha({ 8 | ui: 'tdd', 9 | color: true 10 | }); 11 | 12 | const testsRoot = path.resolve(__dirname, '..'); 13 | 14 | return new Promise((c, e) => { 15 | glob('**/**.test.js', { cwd: testsRoot }, (err, files) => { 16 | if (err) { 17 | return e(err); 18 | } 19 | 20 | // Add files to the test suite 21 | files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); 22 | 23 | try { 24 | // Run the mocha test 25 | mocha.run(failures => { 26 | if (failures > 0) { 27 | e(new Error(`${failures} tests failed.`)); 28 | } else { 29 | c(); 30 | } 31 | }); 32 | } catch (err) { 33 | console.error(err); 34 | e(err); 35 | } 36 | }); 37 | }); 38 | } 39 | 40 | -------------------------------------------------------------------------------- /test/runTest.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | 3 | import { runTests } from 'vscode-test'; 4 | 5 | async function main() { 6 | try { 7 | // The folder containing the Extension Manifest package.json 8 | // Passed to `--extensionDevelopmentPath` 9 | const extensionDevelopmentPath = path.resolve(__dirname, '../../'); 10 | 11 | // The path to test runner 12 | // Passed to --extensionTestsPath 13 | const extensionTestsPath = path.resolve(__dirname, './index'); 14 | 15 | const testWorkspace = path.resolve(__dirname, '../../e2e') 16 | 17 | 18 | // Download VS Code, unzip it and run the integration test 19 | await runTests({ extensionDevelopmentPath, extensionTestsPath, launchArgs: [testWorkspace]}); 20 | } catch (err) { 21 | console.error('Failed to run tests'); 22 | process.exit(1); 23 | } 24 | } 25 | 26 | main(); 27 | 28 | -------------------------------------------------------------------------------- /test/table-navigator.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import * as vscode from 'vscode'; 3 | import { Table, TableNavigator, RowType } from '../src/ttTable'; 4 | 5 | suite('TableNavigator', () => { 6 | let table: Table; 7 | let navigator: TableNavigator; 8 | 9 | setup(() => { 10 | table = new Table(); 11 | table.addRow(RowType.Data, ['Column 1', 'Column 2']); 12 | table.addRow(RowType.Separator, ['', '']); 13 | table.addRow(RowType.Data, ['1', '2']); 14 | table.addRow(RowType.Data, ['3', '4']); 15 | table.addRow(RowType.Separator, ['', '']); 16 | 17 | navigator = new TableNavigator(table); 18 | }); 19 | 20 | test('constructor should initialize table property', () => { 21 | assert.equal(navigator.table, table); 22 | }); 23 | 24 | suite('nextCell', () => { 25 | test('should select first column when cursor in the beginning of line', () => { 26 | const pos = new vscode.Position(0, 0); 27 | const newPos = navigator.nextCell(pos); 28 | 29 | assert.equal(newPos!.line, 0); 30 | assert.equal(newPos!.character, 2); 31 | }); 32 | 33 | test('should navigate next cell', () => { 34 | const pos = new vscode.Position(0, 2); 35 | const newPos = navigator.nextCell(pos); 36 | assert.equal(newPos!.line, 0); 37 | assert.equal(newPos!.character, 13); 38 | }); 39 | 40 | test('should jump to next row', () => { 41 | const pos = new vscode.Position(2, 13); 42 | const newPos = navigator.nextCell(pos); 43 | assert.equal(newPos!.line, 3); 44 | assert.equal(newPos!.character, 2); 45 | }); 46 | 47 | test('should skip separator row', () => { 48 | const pos = new vscode.Position(0, 13); 49 | const newPos = navigator.nextCell(pos); 50 | assert.equal(newPos!.line, 2); 51 | assert.equal(newPos!.character, 2); 52 | }); 53 | 54 | test('should not move if cursor is on separator and it\'s the last line', () => { 55 | const pos = new vscode.Position(4, 13); 56 | const newPos = navigator.nextCell(pos); 57 | assert.equal(newPos, undefined); 58 | }); 59 | 60 | test('should not move if cursor in last cell and there is separator line below', () => { 61 | const pos = new vscode.Position(3, 13); 62 | const newPos = navigator.nextCell(pos); 63 | assert.equal(newPos, undefined); 64 | }); 65 | }); 66 | 67 | suite('previousCell', () => { 68 | test('should navigate previous cell', () => { 69 | const pos = new vscode.Position(0, 13); 70 | const newPos = navigator.previousCell(pos); 71 | assert.equal(newPos!.line, 0); 72 | assert.equal(newPos!.character, 2); 73 | }); 74 | 75 | test('should jump to prev row', () => { 76 | const pos = new vscode.Position(1, 2); 77 | const newPos = navigator.previousCell(pos); 78 | assert.equal(newPos!.line, 0); 79 | assert.equal(newPos!.character, 13); 80 | }); 81 | }); 82 | }); 83 | -------------------------------------------------------------------------------- /test/ttMarkdown.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import { MarkdownParser } from '../src/ttMarkdown'; 3 | import { RowType } from '../src/ttTable'; 4 | 5 | suite('Text tables. Markdown', () => { 6 | suite('Parser', () => { 7 | let parser: MarkdownParser; 8 | setup(() => { 9 | parser = new MarkdownParser(); 10 | }); 11 | 12 | test('should return undefined when incorrect text provided', () => { 13 | const table = parser.parse(''); 14 | assert.equal(table, undefined); 15 | }); 16 | 17 | test('should return table when correct text provided', () => { 18 | const table = parser.parse('a'); 19 | assert.notEqual(table, undefined); 20 | }); 21 | 22 | test('should add row when string starts with |', () => { 23 | const table = parser.parse('|'); 24 | if (table !== undefined) { 25 | assert.equal(table.rows.length, 1); 26 | assert.equal(table.rows[0].type, RowType.Data); 27 | assert.equal(table.cols.length, 1); 28 | } 29 | }); 30 | 31 | test('should parse "| -" as separator row', () => { 32 | const table = parser.parse('| -'); 33 | assert.notEqual(table, undefined); 34 | if (table !== undefined) { 35 | assert.equal(table.rows.length, 1); 36 | assert.equal(table.rows[0].type, RowType.Separator); 37 | } 38 | }); 39 | 40 | test('should parse "| :-" as separator row', () => { 41 | const table = parser.parse('| :-'); 42 | assert.notEqual(table, undefined); 43 | if (table !== undefined) { 44 | assert.equal(table.rows.length, 1); 45 | assert.equal(table.rows[0].type, RowType.Separator); 46 | } 47 | }); 48 | 49 | test('should split columns by |', () => { 50 | const table = parser.parse('||||'); 51 | if (table !== undefined) { 52 | assert.equal(table.rows.length, 1); 53 | assert.equal(table.cols.length, 3); 54 | } 55 | }); 56 | 57 | test('should handle last characters as column', () => { 58 | const table = parser.parse('||Last col'); 59 | if (table !== undefined) { 60 | assert.equal(table.cols.length, 2); 61 | } 62 | }); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /test/ttOrg.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import { OrgParser } from '../src/ttOrg'; 3 | import { RowType } from '../src/ttTable'; 4 | 5 | suite('Text tables. Org', () => { 6 | suite('Parser', () => { 7 | let parser: OrgParser; 8 | setup(() => { 9 | parser = new OrgParser(); 10 | }); 11 | 12 | test('should return undefined when incorrect text provided', () => { 13 | const table = parser.parse(''); 14 | assert.equal(table, undefined); 15 | }); 16 | 17 | test('should return table when correct text provided', () => { 18 | const table = parser.parse('a'); 19 | assert.notEqual(table, undefined); 20 | }); 21 | 22 | test('should add row when string starts with |', () => { 23 | const table = parser.parse('|'); 24 | if (table !== undefined) { 25 | assert.equal(table.rows.length, 1); 26 | assert.equal(table.rows[0].type, RowType.Data); 27 | assert.equal(table.cols.length, 1); 28 | } 29 | }); 30 | 31 | test('should parse |- as separator row', () => { 32 | const table = parser.parse('|-'); 33 | assert.notEqual(table, undefined); 34 | if (table !== undefined) { 35 | assert.equal(table.rows.length, 1); 36 | assert.equal(table.rows[0].type, RowType.Separator); 37 | } 38 | }); 39 | 40 | test('should split columns by |', () => { 41 | const table = parser.parse('||||'); 42 | if (table !== undefined) { 43 | assert.equal(table.rows.length, 1); 44 | assert.equal(table.cols.length, 3); 45 | } 46 | }); 47 | 48 | test('should handle last characters as column', () => { 49 | const table = parser.parse('||Last col'); 50 | if (table !== undefined) { 51 | assert.equal(table.cols.length, 2); 52 | } 53 | }); 54 | }); 55 | }); 56 | -------------------------------------------------------------------------------- /test/ttTable.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import { Table, RowType } from '../src/ttTable'; 3 | 4 | suite('Text tables. Table', () => { 5 | let table: Table; 6 | 7 | setup(() => { 8 | table = new Table(); 9 | }); 10 | 11 | test('It creates', () => { 12 | assert.notEqual(table, undefined); 13 | }); 14 | 15 | test('It should add rows', () => { 16 | table.addRow(RowType.Data, []); 17 | assert.equal(table.rows.length, 1); 18 | }); 19 | 20 | test('It should update cols when row values provided', () => { 21 | table.addRow(RowType.Data, ['Value1', 'Value2']); 22 | assert.equal(table.cols.length, 2); 23 | 24 | table.addRow(RowType.Data, ['NewValue1', 'NewValue2', 'NewValue3']); 25 | assert.equal(table.cols.length, 3); 26 | }); 27 | 28 | test('It should recalculate columns widths when adding values', () => { 29 | table.addRow(RowType.Data, ['C']); 30 | assert.equal(table.cols[0].width, 1); 31 | 32 | table.addRow(RowType.Data, ['Column']); 33 | assert.equal(table.cols[0].width, 6); 34 | }); 35 | 36 | test('getAt returns value of cell', () => { 37 | table.addRow(RowType.Data, ['1.1', '1.2']); 38 | table.addRow(RowType.Data, ['2.1', '2.2']); 39 | 40 | assert.equal(table.getAt(0, 0), '1.1'); 41 | assert.equal(table.getAt(0, 1), '1.2'); 42 | assert.equal(table.getAt(1, 0), '2.1'); 43 | assert.equal(table.getAt(1, 1), '2.2'); 44 | }); 45 | 46 | test('getRow returns array of data in row', () => { 47 | table.addRow(RowType.Data, ['1', '2']); 48 | 49 | assert.deepEqual(table.getRow(0), ['1', '2']); 50 | }); 51 | 52 | test('setAt should set new value for cell', () => { 53 | table.addRow(RowType.Data, ['1', '2']); 54 | table.setAt(0, 0, 'NewValue'); 55 | assert.equal(table.getAt(0, 0), 'NewValue'); 56 | assert.deepEqual(table.getRow(0), ['NewValue', '2']); 57 | }); 58 | 59 | test('setAt should update column width', () => { 60 | table.addRow(RowType.Data, ['1']); 61 | table.setAt(0, 0, 'Long'); 62 | assert.equal(table.cols[0].width, 4); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "outDir": "out", 6 | "lib": [ 7 | "es6" 8 | ], 9 | "sourceMap": true, 10 | "rootDir": ".", 11 | /* Strict Type-Checking Option */ 12 | "strict": true, /* enable all strict type-checking options */ 13 | /* Additional Checks */ 14 | "noUnusedLocals": true, /* Report errors on unused locals. */ 15 | "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 16 | "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 17 | "noUnusedParameters": true, /* Report errors on unused parameters. */ 18 | }, 19 | "exclude": [ 20 | "node_modules", 21 | ".vscode-test" 22 | ] 23 | } 24 | --------------------------------------------------------------------------------