├── .gitignore
├── .travis.yml
├── .vscode
├── launch.json
├── settings.json
└── tasks.json
├── .vscodeignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── img
├── demo.gif
├── icon.png
├── r0.5.0
│ ├── example_highlight.png
│ └── example_inner.png
├── r0.6.0
│ └── new_active_indent.png
└── r0.7.0
│ ├── hover_with_highlight.png
│ └── hover_without_highlight.png
├── package-lock.json
├── package.json
├── src
└── extension.ts
├── test-fixtures
└── demo
│ └── demo.ts
├── test
├── runTest.ts
└── suite
│ ├── extension.test.ts
│ └── index.ts
├── tsconfig.json
└── vsc-extension-quickstart.md
/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | node_modules
3 | .vscode-test
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 |
3 | language: node_js
4 |
5 | node_js: "6"
6 |
7 | os:
8 | - osx
9 | - linux
10 |
11 | before_install:
12 | - if [ $TRAVIS_OS_NAME == "linux" ]; then
13 | export CXX="g++-4.9" CC="gcc-4.9" DISPLAY=:99.0;
14 | sh -e /etc/init.d/xvfb start;
15 | sleep 3;
16 | fi
17 |
18 | install:
19 | - npm install
20 | - npm run vscode:prepublish
21 |
22 | script:
23 | - npm test
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | // A launch configuration that compiles the extension and then opens it inside a new window
2 | {
3 | "version": "0.6.0",
4 | "configurations": [
5 | {
6 | "name": "Launch Extension",
7 | "type": "extensionHost",
8 | "request": "launch",
9 | "runtimeExecutable": "${execPath}",
10 | "args": ["${workspaceRoot}/test-fixtures/demo", "--extensionDevelopmentPath=${workspaceRoot}" ],
11 | "stopOnEntry": false,
12 | "sourceMaps": true,
13 | "outFiles": [
14 | "${workspaceFolder}/out/src/*.js"
15 | ],
16 | "preLaunchTask": "npm: compile"
17 | },
18 | {
19 | "name": "Launch Tests",
20 | "type": "extensionHost",
21 | "request": "launch",
22 | "runtimeExecutable": "${execPath}",
23 | "args": [
24 | "${workspaceRoot}/out/test/suite",
25 | "--extensionDevelopmentPath=${workspaceRoot}",
26 | "--extensionTestsPath=${workspaceRoot}/out/test/suite" ],
27 | "preLaunchTask": "npm: compile"
28 | }
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/.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 | "typescript.tsdk": "./node_modules/typescript/lib" // we want to use the TS server from our node_modules folder to control its version
10 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // Available variables which can be used inside of strings.
2 | // ${workspaceRoot}: the root folder of the team
3 | // ${file}: the current opened file
4 | // ${fileBasename}: the current opened file's basename
5 | // ${fileDirname}: the current opened file's dirname
6 | // ${fileExtname}: the current opened file's extension
7 | // ${cwd}: the current working directory of the spawned process
8 |
9 | // See https://go.microsoft.com/fwlink/?LinkId=733558
10 | // for the documentation about the tasks.json format
11 | {
12 | "version": "2.0.0",
13 | "tasks": [
14 | {
15 | "type": "npm",
16 | "script": "compile",
17 | "problemMatcher": "$tsc-watch",
18 | "isBackground": true,
19 | "presentation": {
20 | "reveal": "never"
21 | },
22 | "group": {
23 | "kind": "build",
24 | "isDefault": true
25 | }
26 | }
27 | ]
28 | }
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | typings/**
3 | out/test/**
4 | test/**
5 | src/**
6 | **/*.map
7 | .gitignore
8 | tsconfig.json
9 | vsc-extension-quickstart.md
10 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # 0.7.0
2 |
3 | ## Minor
4 | - Renamed settings:
5 | - **indenticator.showHighlight** changed to **indenticator.showIndentGuide**
6 | - **indenticator.inner.showHighlight** changed to **indenticator.inner.showIndentGuide**
7 | - At some point the behaviour for hovers in VS Code changed slightly:
8 |
9 | Now if the hover highlights a code block the content of the hover is shown above or below the highlighted block, rather than at the cursor position. Without highlighting a code block the hover will still be shown at the cursor position.
10 |
11 | To give the user control over how the peek feature should behave when hovering on the indent guides new settings were added:
12 | - **indenticator.hover.highlight** (default `true`): Controls wether hovering on the indent guide should highlight the code block
13 | - **indenticator.inner.hover.highlight** (default `true`): Controls wether hovering on the inner indent guide should highlight the code block
14 | - Hovering now works even if the indent guides themselves are disabled
15 | ## Patch
16 | - Fixes for #23, #25 & #26
17 | - Dependencies updated
18 |
19 | # 0.6.0
20 |
21 | ## Minor
22 |
23 | - Switched default border style from 'solid' to 'inset'
24 | - With VS Code 1.23.0 there seems to have been a change in the rendering of solid borders that makes them appear thicker than before. To offset that change the default style is now inset which should make the default borders somewhat slimmer again.
25 | - Updated README to reflect recent changes with new buildin active indent guide of VS Code
26 |
27 | ## Patch
28 | - additional checks before fetching lines from document to fix #20
29 |
30 | # 0.5.1
31 |
32 | ## Path
33 |
34 | - Fixed some typos
35 |
36 | # 0.5.0
37 |
38 | ## Minor
39 |
40 | - New Setting **indenticator.showHighlight** to toggle the Highlighting of the indent line. (default is `true`)
41 | - If this setting is `false` the hover options will be ignored
42 | - New Feature: Highlighting for inner indent as suggested in #14
43 | - highlights the indent guide of the block contained by the current cursor position
44 | - added settings **indenticator.inner.\*** allowing for all configuration options already present for the standard indent highlight to be configured for the new highlight of the inner indent.
45 | - To keep the extensions behaviour for existing users **indenticator.inner.showHighlight** defaults to `false`
46 |
47 | 
48 |
49 | - Hover-Feature now also highlights the block it peeks around
50 |
51 | 
52 |
53 | - Setting **indenticator.languageSpecific** now allows configuration of multiple languages at once by naming them in a comma seperated list
54 |
55 | Example:
56 | ``` JS
57 | {
58 | "indenticator.languageSpecific": {
59 | "[json, jsonc]": {
60 | //...
61 | },
62 | "[xml, html, xhtml]": {
63 | //...
64 | }
65 | }
66 | }
67 | ```
68 |
69 | # 0.4.2
70 |
71 | ## Patch
72 |
73 | - Fixed Issue #6: include first and last line of file in hover
74 |
75 | # 0.4.1
76 |
77 | ## Patch
78 |
79 | - Fixed Issue #5: Language specific settings will now be applied correctly
80 |
81 | # 0.4.0
82 |
83 | ## Minor
84 |
85 | - More Configuration Options for hover on indent line
86 | - changed setting **indenticator.showHover** to accept boolean and number. If given a number the hover is active if the current indent block is at list that many lines long. (default is `false`)
87 | - added setting **indenticator.hover.peekBack** to set the number of lines to be peeked before the current indent block (default is `1`)
88 | - added setting **indenticator.hover.peekForward** to set the number of lines to be peeked after the current indent block (default is `0`)
89 | - added setting **indenticator.hover.trimLinesShorterThan** to remove lines at beginning and end of hover if they are shorter then the given value (default is `2`)
90 | - added setting **indenticator.hover.peekBlockPlaceholder** to set string to be shown between the peeked lines in the hover (default is "`...`")
91 | - Added option to specify language specific configurations
92 | - added setting **indenticator.languageSpecific** to specify language specific settings (default is `{}`)
93 |
94 | Accepts an object with language keys enclosed in square brackets (analogous to [language specific editor options](https://code.visualstudio.com/docs/getstarted/settings#_language-specific-editor-settings)) as property keys and any set of indenticator configuartion as values.
95 |
96 | Example:
97 | ``` JS
98 | {
99 | "indenticator.languageSpecific": {
100 | "[json]": {
101 | "indenticator.showHover": true,
102 | "indenticator.hover.peekBack": 1
103 | }
104 | }
105 | }
106 | ```
107 |
108 | # 0.3.0
109 |
110 | ## Minor
111 | - New Feature: Hover on active indent line peeks first line (thanks to [rsbondi](https://github.com/rsbondi) on github)
112 | - added setting **indenticator.showHover** to activate the new Feature (default is `false`)
113 |
114 | ## Patch
115 | - Updated project to Typescript 2
116 | - Fixed Travis builds
117 |
118 | # 0.2.1
119 |
120 | ## Patch
121 |
122 | - Fixed Issue #1: The Extension will no longer add multiple Information Items into the Statusbar
123 |
124 | # 0.2.0
125 |
126 | ## Minor
127 |
128 | - First release to be published to the VS Marketplace
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (c) 2016 Fabian Krueger
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 |
6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 |
8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/SirTori/indenticator)
2 |
3 | # Indenticator
4 |
5 | Visually highlights the current indent depth.
6 |
7 | This extension can be used by itself, but it's recommended to use it alongside the built-in indent guides (setting **editor.renderIndentGuides**). These show thin grey lines on *every* indent, while this extension highlights the indent on the indent depth the cursor is currently on.
8 |
9 | **Changes in Visual Studio Code 1.23.0**:
10 | With Version 1.23.0 VS Code introduced a new built-in active indent guide. For an explanation of differences and tips regarding the new feature and this extension please see [remarks section](#remarks)
11 |
12 |
13 |
14 |  |
15 |
16 |
17 | Example using default settings |
18 |
19 |
20 |
21 |
22 | ## Feature Highlights
23 |
24 | - **Peeking around the current indent block**: *Optionally* a hover can be added on the current indent marker to peek before and/or after the current indent block.
25 | *To activate set **indenticator.showHover** to `true`*
26 |
27 |
28 |
29 |  |
30 |  |
31 |
32 |
33 | Example has indenticator.hover.peekBack & indenticator.hover.peekForward set to 1 and indenticator.hover.highlight set to true |
34 | Example has indenticator.hover.peekBack & indenticator.hover.peekForward set to 1 and indenticator.hover.highlight set to false |
35 |
36 |
37 |
38 | - **Highlighting the the indent guide for the contained block**: *Optionally* a second indent guide can be configured to show the block *contained* by the current cursor position
39 | *To activate set **indenticator.inner.showIndentGuide** to `true`*
40 |
41 |
42 |
43 |  |
44 |
45 |
46 | Example has indenticator.inner.showIndentGuide set to true and indenticator.inner.color.dark set to #ff000 |
47 |
48 |
49 |
50 |
51 | - **Language specific settings**: The extension can be configured for each language separately to accommondate the requirements of different coding styles.
52 |
53 | Example:
54 | ``` JS
55 | {
56 | "indenticator.languageSpecific": {
57 | "[json, jsonc]": {
58 | //...
59 | },
60 | "[xml, html, xhtml]": {
61 | //...
62 | }
63 | }
64 | }
65 | ```
66 |
67 | - **Highlight Styling**: All indent highlighting can be styled individually by defining color, width and border style.
68 |
69 | ## Settings and defaults
70 | ``` JS
71 | {
72 | /******************************************************/
73 | /********** Standard Indent Highlight Config **********/
74 | /******************************************************/
75 | /* Whether to highlight the indent of the block enclosing the current line */
76 | "indenticator.showIndentGuide": true
77 | /* Color of the indent marker for dark themes */
78 | "indenticator.color.dark": "#888",
79 | /* Color of the indent marker for light themes */
80 | "indenticator.color.light": "#999",
81 | /* Width of the indent marker in pixels */
82 | "indenticator.width": 1,
83 | /* Line style of the indent marker (e.g. "inset", "dashed", "dotted", ...) */
84 | "indenticator.style": "inset",
85 | /* Whether to display the hover near the indent line */
86 | "indenticator.showHover": false,
87 | /* Wether to highlight the contained code block when hovering the indent line. If activated, the peeked content will be shown at top or bottom of the block, otherwise it will be shown at cursor position.*/
88 | "indenticator.hover.highlight": true,
89 | /* Lines before the current indent to be shown on hover */
90 | "indenticator.hover.peekBack": 1,
91 | /* Lines after the current indent to be shown on hover */
92 | "indenticator.hover.peekForward": 0,
93 | /* Remove lines from the hover at the beginning and end that have less characters than this */
94 | "indenticator.hover.trimLinesShorterThan": 2,
95 | /* Block placeholder to be written between peeked lines */
96 | "indenticator.hover.peekBlockPlaceholder": "...",
97 |
98 | /***************************************************/
99 | /********** Inner Indent Highlight Config **********/
100 | /***************************************************/
101 | /* Whether to highlight the indent of the block enclosed by the current line */
102 | "indenticator.inner.showHighlight": false
103 | /* Color of the indent marker for dark themes */
104 | "indenticator.inner.color.dark": "#888",
105 | /* Color of the indent marker for light themes */
106 | "indenticator.inner.color.light": "#999",
107 | /* Width of the indent marker in pixels */
108 | "indenticator.inner.width": 1,
109 | /* Line style of the indent marker (e.g. "inset", "dashed", "dotted", ...) */
110 | "indenticator.inner.style": "inset",
111 | /* Whether to display the hover near the inner indent line */
112 | "indenticator.inner.showHover": false,
113 | /* Wether to highlight the contained code block when hovering the indent line. If activated, the peeked content will be shown at top or bottom of the block, otherwise it will be shown at cursor position.*/
114 | "indenticator.inner.hover.highlight": true,
115 | /* Lines before the current inner indent to be shown on hover */
116 | "indenticator.inner.hover.peekBack": 1,
117 | /* Lines after the current inner indent to be shown on hover */
118 | "indenticator.inner.hover.peekForward": 0,
119 | /* Remove lines from the inner indent hover at the beginning and end that have less characters than this */
120 | "indenticator.inner.hover.trimLinesShorterThan": 2,
121 | /* Block placeholder to be written between peeked lines */
122 | "indenticator.inner.hover.peekBlockPlaceholder": "...",
123 | /* Whether to display the current indent depth on the statusbar */
124 |
125 | /********************************************/
126 | /********** Further Configurations **********/
127 | /********************************************/
128 | "indenticator.showCurrentDepthInStatusBar": true,
129 | /* A construct with language identifiers as properties containing a subset of indenticator options to be applied for that language */
130 | "indenticator.languageSpecific": {}
131 | }
132 | ```
133 | ### Remarks
134 | - **New Built-in active indent guide (VS Code 1.23.0)**
135 | - The built-in active indent guide always highlights the *highest* indent on the currently selected line, while this extensions highlights the indent depth the *cursor is currently at*. The difference can be seen in the following image:
136 |
137 | |  |
138 | |- |
139 | | *yellow* is the new built-in active indent guide
*red* is the inner active indent guide of this extension
*grey* is the default active indent guide of this extension |
140 |
141 | - The built-in *active* indent guide can be configured through the setting: **editor.highlightActiveIndentGuide**
142 |
143 | - **indenticator.languageSpecific**: The language identifiers can be viewed by using [VS Codes language selection](https://code.visualstudio.com/docs/languages/overview#_language-id) in the statusbar. To be analogous to [language specific editor options](https://code.visualstudio.com/docs/getstarted/settings#_language-specific-editor-settings) of VS Code the key has to be put between square brackets. But to simplify configuration of similar languages multiple keys can be listed within the square brackets as a comma seperated list.
144 |
145 | Any setting for indenticator that can be set normally, can also be set for the language specific configuration. If any setting is not set for the specific language the overall configuration will be used.
146 |
147 | Example:
148 | ``` JS
149 | {
150 | "indenticator.languageSpecific": {
151 | "[json, jsonc]": {
152 | "indenticator.showHover": true,
153 | "indenticator.hover.peekBack": 1
154 | }
155 | }
156 | }
157 | ```
--------------------------------------------------------------------------------
/img/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SirTori/indenticator/2a8507f07425e19d6949cdb831614e9d57793ce1/img/demo.gif
--------------------------------------------------------------------------------
/img/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SirTori/indenticator/2a8507f07425e19d6949cdb831614e9d57793ce1/img/icon.png
--------------------------------------------------------------------------------
/img/r0.5.0/example_highlight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SirTori/indenticator/2a8507f07425e19d6949cdb831614e9d57793ce1/img/r0.5.0/example_highlight.png
--------------------------------------------------------------------------------
/img/r0.5.0/example_inner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SirTori/indenticator/2a8507f07425e19d6949cdb831614e9d57793ce1/img/r0.5.0/example_inner.png
--------------------------------------------------------------------------------
/img/r0.6.0/new_active_indent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SirTori/indenticator/2a8507f07425e19d6949cdb831614e9d57793ce1/img/r0.6.0/new_active_indent.png
--------------------------------------------------------------------------------
/img/r0.7.0/hover_with_highlight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SirTori/indenticator/2a8507f07425e19d6949cdb831614e9d57793ce1/img/r0.7.0/hover_with_highlight.png
--------------------------------------------------------------------------------
/img/r0.7.0/hover_without_highlight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SirTori/indenticator/2a8507f07425e19d6949cdb831614e9d57793ce1/img/r0.7.0/hover_without_highlight.png
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "indenticator",
3 | "version": "0.7.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "@types/glob": {
8 | "version": "7.1.3",
9 | "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz",
10 | "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==",
11 | "dev": true,
12 | "requires": {
13 | "@types/minimatch": "*",
14 | "@types/node": "*"
15 | }
16 | },
17 | "@types/minimatch": {
18 | "version": "3.0.3",
19 | "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
20 | "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
21 | "dev": true
22 | },
23 | "@types/mocha": {
24 | "version": "8.0.3",
25 | "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.0.3.tgz",
26 | "integrity": "sha512-vyxR57nv8NfcU0GZu8EUXZLTbCMupIUwy95LJ6lllN+JRPG25CwMHoB1q5xKh8YKhQnHYRAn4yW2yuHbf/5xgg==",
27 | "dev": true
28 | },
29 | "@types/node": {
30 | "version": "12.12.54",
31 | "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.54.tgz",
32 | "integrity": "sha512-ge4xZ3vSBornVYlDnk7yZ0gK6ChHf/CHB7Gl1I0Jhah8DDnEQqBzgohYG4FX4p81TNirSETOiSyn+y1r9/IR6w==",
33 | "dev": true
34 | },
35 | "@types/vscode": {
36 | "version": "1.48.0",
37 | "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.48.0.tgz",
38 | "integrity": "sha512-sZJKzsJz1gSoFXcOJWw3fnKl2sseUgZmvB4AJZS+Fea+bC/jfGPVhmFL/FfQHld/TKtukVONsmoD3Pkyx9iadg==",
39 | "dev": true
40 | },
41 | "agent-base": {
42 | "version": "4.3.0",
43 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
44 | "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
45 | "dev": true,
46 | "requires": {
47 | "es6-promisify": "^5.0.0"
48 | }
49 | },
50 | "ansi-colors": {
51 | "version": "4.1.1",
52 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
53 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
54 | "dev": true
55 | },
56 | "ansi-regex": {
57 | "version": "3.0.0",
58 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
59 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
60 | "dev": true
61 | },
62 | "ansi-styles": {
63 | "version": "3.2.1",
64 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
65 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
66 | "dev": true,
67 | "requires": {
68 | "color-convert": "^1.9.0"
69 | }
70 | },
71 | "anymatch": {
72 | "version": "3.1.1",
73 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
74 | "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
75 | "dev": true,
76 | "requires": {
77 | "normalize-path": "^3.0.0",
78 | "picomatch": "^2.0.4"
79 | }
80 | },
81 | "argparse": {
82 | "version": "1.0.10",
83 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
84 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
85 | "dev": true,
86 | "requires": {
87 | "sprintf-js": "~1.0.2"
88 | }
89 | },
90 | "array-filter": {
91 | "version": "1.0.0",
92 | "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz",
93 | "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=",
94 | "dev": true
95 | },
96 | "array.prototype.map": {
97 | "version": "1.0.2",
98 | "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.2.tgz",
99 | "integrity": "sha512-Az3OYxgsa1g7xDYp86l0nnN4bcmuEITGe1rbdEBVkrqkzMgDcbdQ2R7r41pNzti+4NMces3H8gMmuioZUilLgw==",
100 | "dev": true,
101 | "requires": {
102 | "define-properties": "^1.1.3",
103 | "es-abstract": "^1.17.0-next.1",
104 | "es-array-method-boxes-properly": "^1.0.0",
105 | "is-string": "^1.0.4"
106 | }
107 | },
108 | "assert": {
109 | "version": "2.0.0",
110 | "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz",
111 | "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==",
112 | "dev": true,
113 | "requires": {
114 | "es6-object-assign": "^1.1.0",
115 | "is-nan": "^1.2.1",
116 | "object-is": "^1.0.1",
117 | "util": "^0.12.0"
118 | }
119 | },
120 | "available-typed-arrays": {
121 | "version": "1.0.2",
122 | "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz",
123 | "integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==",
124 | "dev": true,
125 | "requires": {
126 | "array-filter": "^1.0.0"
127 | }
128 | },
129 | "balanced-match": {
130 | "version": "1.0.0",
131 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
132 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
133 | "dev": true
134 | },
135 | "binary-extensions": {
136 | "version": "2.1.0",
137 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
138 | "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
139 | "dev": true
140 | },
141 | "brace-expansion": {
142 | "version": "1.1.11",
143 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
144 | "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=",
145 | "dev": true,
146 | "requires": {
147 | "balanced-match": "^1.0.0",
148 | "concat-map": "0.0.1"
149 | }
150 | },
151 | "braces": {
152 | "version": "3.0.2",
153 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
154 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
155 | "dev": true,
156 | "requires": {
157 | "fill-range": "^7.0.1"
158 | }
159 | },
160 | "browser-stdout": {
161 | "version": "1.3.1",
162 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
163 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
164 | "dev": true
165 | },
166 | "camelcase": {
167 | "version": "5.3.1",
168 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
169 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
170 | "dev": true
171 | },
172 | "chalk": {
173 | "version": "2.4.2",
174 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
175 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
176 | "dev": true,
177 | "requires": {
178 | "ansi-styles": "^3.2.1",
179 | "escape-string-regexp": "^1.0.5",
180 | "supports-color": "^5.3.0"
181 | },
182 | "dependencies": {
183 | "supports-color": {
184 | "version": "5.5.0",
185 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
186 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
187 | "dev": true,
188 | "requires": {
189 | "has-flag": "^3.0.0"
190 | }
191 | }
192 | }
193 | },
194 | "chokidar": {
195 | "version": "3.3.1",
196 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz",
197 | "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==",
198 | "dev": true,
199 | "requires": {
200 | "anymatch": "~3.1.1",
201 | "braces": "~3.0.2",
202 | "fsevents": "~2.1.2",
203 | "glob-parent": "~5.1.0",
204 | "is-binary-path": "~2.1.0",
205 | "is-glob": "~4.0.1",
206 | "normalize-path": "~3.0.0",
207 | "readdirp": "~3.3.0"
208 | }
209 | },
210 | "cliui": {
211 | "version": "5.0.0",
212 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
213 | "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
214 | "dev": true,
215 | "requires": {
216 | "string-width": "^3.1.0",
217 | "strip-ansi": "^5.2.0",
218 | "wrap-ansi": "^5.1.0"
219 | },
220 | "dependencies": {
221 | "ansi-regex": {
222 | "version": "4.1.0",
223 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
224 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
225 | "dev": true
226 | },
227 | "string-width": {
228 | "version": "3.1.0",
229 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
230 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
231 | "dev": true,
232 | "requires": {
233 | "emoji-regex": "^7.0.1",
234 | "is-fullwidth-code-point": "^2.0.0",
235 | "strip-ansi": "^5.1.0"
236 | }
237 | },
238 | "strip-ansi": {
239 | "version": "5.2.0",
240 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
241 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
242 | "dev": true,
243 | "requires": {
244 | "ansi-regex": "^4.1.0"
245 | }
246 | }
247 | }
248 | },
249 | "color-convert": {
250 | "version": "1.9.3",
251 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
252 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
253 | "dev": true,
254 | "requires": {
255 | "color-name": "1.1.3"
256 | }
257 | },
258 | "color-name": {
259 | "version": "1.1.3",
260 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
261 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
262 | "dev": true
263 | },
264 | "concat-map": {
265 | "version": "0.0.1",
266 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
267 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
268 | "dev": true
269 | },
270 | "debug": {
271 | "version": "3.2.6",
272 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
273 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
274 | "dev": true,
275 | "requires": {
276 | "ms": "^2.1.1"
277 | }
278 | },
279 | "decamelize": {
280 | "version": "1.2.0",
281 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
282 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
283 | "dev": true
284 | },
285 | "define-properties": {
286 | "version": "1.1.3",
287 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
288 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
289 | "dev": true,
290 | "requires": {
291 | "object-keys": "^1.0.12"
292 | }
293 | },
294 | "diff": {
295 | "version": "4.0.2",
296 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
297 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
298 | "dev": true
299 | },
300 | "emoji-regex": {
301 | "version": "7.0.3",
302 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
303 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
304 | "dev": true
305 | },
306 | "es-abstract": {
307 | "version": "1.17.6",
308 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
309 | "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
310 | "dev": true,
311 | "requires": {
312 | "es-to-primitive": "^1.2.1",
313 | "function-bind": "^1.1.1",
314 | "has": "^1.0.3",
315 | "has-symbols": "^1.0.1",
316 | "is-callable": "^1.2.0",
317 | "is-regex": "^1.1.0",
318 | "object-inspect": "^1.7.0",
319 | "object-keys": "^1.1.1",
320 | "object.assign": "^4.1.0",
321 | "string.prototype.trimend": "^1.0.1",
322 | "string.prototype.trimstart": "^1.0.1"
323 | }
324 | },
325 | "es-array-method-boxes-properly": {
326 | "version": "1.0.0",
327 | "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz",
328 | "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==",
329 | "dev": true
330 | },
331 | "es-get-iterator": {
332 | "version": "1.1.0",
333 | "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz",
334 | "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==",
335 | "dev": true,
336 | "requires": {
337 | "es-abstract": "^1.17.4",
338 | "has-symbols": "^1.0.1",
339 | "is-arguments": "^1.0.4",
340 | "is-map": "^2.0.1",
341 | "is-set": "^2.0.1",
342 | "is-string": "^1.0.5",
343 | "isarray": "^2.0.5"
344 | }
345 | },
346 | "es-to-primitive": {
347 | "version": "1.2.1",
348 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
349 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
350 | "dev": true,
351 | "requires": {
352 | "is-callable": "^1.1.4",
353 | "is-date-object": "^1.0.1",
354 | "is-symbol": "^1.0.2"
355 | }
356 | },
357 | "es6-object-assign": {
358 | "version": "1.1.0",
359 | "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz",
360 | "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=",
361 | "dev": true
362 | },
363 | "es6-promise": {
364 | "version": "4.2.8",
365 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
366 | "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
367 | "dev": true
368 | },
369 | "es6-promisify": {
370 | "version": "5.0.0",
371 | "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
372 | "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
373 | "dev": true,
374 | "requires": {
375 | "es6-promise": "^4.0.3"
376 | }
377 | },
378 | "escape-string-regexp": {
379 | "version": "1.0.5",
380 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
381 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
382 | "dev": true
383 | },
384 | "esprima": {
385 | "version": "4.0.1",
386 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
387 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
388 | "dev": true
389 | },
390 | "fill-range": {
391 | "version": "7.0.1",
392 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
393 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
394 | "dev": true,
395 | "requires": {
396 | "to-regex-range": "^5.0.1"
397 | }
398 | },
399 | "find-up": {
400 | "version": "4.1.0",
401 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
402 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
403 | "dev": true,
404 | "requires": {
405 | "locate-path": "^5.0.0",
406 | "path-exists": "^4.0.0"
407 | }
408 | },
409 | "flat": {
410 | "version": "4.1.0",
411 | "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz",
412 | "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==",
413 | "dev": true,
414 | "requires": {
415 | "is-buffer": "~2.0.3"
416 | }
417 | },
418 | "foreach": {
419 | "version": "2.0.5",
420 | "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
421 | "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
422 | "dev": true
423 | },
424 | "fs.realpath": {
425 | "version": "1.0.0",
426 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
427 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
428 | "dev": true
429 | },
430 | "fsevents": {
431 | "version": "2.1.3",
432 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
433 | "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
434 | "dev": true,
435 | "optional": true
436 | },
437 | "function-bind": {
438 | "version": "1.1.1",
439 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
440 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
441 | "dev": true
442 | },
443 | "get-caller-file": {
444 | "version": "2.0.5",
445 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
446 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
447 | "dev": true
448 | },
449 | "glob": {
450 | "version": "7.1.6",
451 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
452 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
453 | "dev": true,
454 | "requires": {
455 | "fs.realpath": "^1.0.0",
456 | "inflight": "^1.0.4",
457 | "inherits": "2",
458 | "minimatch": "^3.0.4",
459 | "once": "^1.3.0",
460 | "path-is-absolute": "^1.0.0"
461 | }
462 | },
463 | "glob-parent": {
464 | "version": "5.1.1",
465 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
466 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
467 | "dev": true,
468 | "requires": {
469 | "is-glob": "^4.0.1"
470 | }
471 | },
472 | "growl": {
473 | "version": "1.10.5",
474 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
475 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
476 | "dev": true
477 | },
478 | "has": {
479 | "version": "1.0.3",
480 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
481 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
482 | "dev": true,
483 | "requires": {
484 | "function-bind": "^1.1.1"
485 | }
486 | },
487 | "has-flag": {
488 | "version": "3.0.0",
489 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
490 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
491 | "dev": true
492 | },
493 | "has-symbols": {
494 | "version": "1.0.1",
495 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
496 | "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
497 | "dev": true
498 | },
499 | "he": {
500 | "version": "1.2.0",
501 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
502 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
503 | "dev": true
504 | },
505 | "http-proxy-agent": {
506 | "version": "2.1.0",
507 | "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz",
508 | "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==",
509 | "dev": true,
510 | "requires": {
511 | "agent-base": "4",
512 | "debug": "3.1.0"
513 | },
514 | "dependencies": {
515 | "debug": {
516 | "version": "3.1.0",
517 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
518 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
519 | "dev": true,
520 | "requires": {
521 | "ms": "2.0.0"
522 | }
523 | },
524 | "ms": {
525 | "version": "2.0.0",
526 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
527 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
528 | "dev": true
529 | }
530 | }
531 | },
532 | "https-proxy-agent": {
533 | "version": "2.2.4",
534 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz",
535 | "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==",
536 | "dev": true,
537 | "requires": {
538 | "agent-base": "^4.3.0",
539 | "debug": "^3.1.0"
540 | },
541 | "dependencies": {
542 | "debug": {
543 | "version": "3.2.6",
544 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
545 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
546 | "dev": true,
547 | "requires": {
548 | "ms": "^2.1.1"
549 | }
550 | },
551 | "ms": {
552 | "version": "2.1.2",
553 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
554 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
555 | "dev": true
556 | }
557 | }
558 | },
559 | "inflight": {
560 | "version": "1.0.6",
561 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
562 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
563 | "dev": true,
564 | "requires": {
565 | "once": "^1.3.0",
566 | "wrappy": "1"
567 | }
568 | },
569 | "inherits": {
570 | "version": "2.0.1",
571 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
572 | "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
573 | "dev": true
574 | },
575 | "is-arguments": {
576 | "version": "1.0.4",
577 | "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
578 | "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==",
579 | "dev": true
580 | },
581 | "is-binary-path": {
582 | "version": "2.1.0",
583 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
584 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
585 | "dev": true,
586 | "requires": {
587 | "binary-extensions": "^2.0.0"
588 | }
589 | },
590 | "is-buffer": {
591 | "version": "2.0.4",
592 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
593 | "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==",
594 | "dev": true
595 | },
596 | "is-callable": {
597 | "version": "1.2.0",
598 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
599 | "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==",
600 | "dev": true
601 | },
602 | "is-date-object": {
603 | "version": "1.0.2",
604 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
605 | "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==",
606 | "dev": true
607 | },
608 | "is-extglob": {
609 | "version": "2.1.1",
610 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
611 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
612 | "dev": true
613 | },
614 | "is-fullwidth-code-point": {
615 | "version": "2.0.0",
616 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
617 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
618 | "dev": true
619 | },
620 | "is-generator-function": {
621 | "version": "1.0.7",
622 | "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz",
623 | "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==",
624 | "dev": true
625 | },
626 | "is-glob": {
627 | "version": "4.0.1",
628 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
629 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
630 | "dev": true,
631 | "requires": {
632 | "is-extglob": "^2.1.1"
633 | }
634 | },
635 | "is-map": {
636 | "version": "2.0.1",
637 | "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz",
638 | "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==",
639 | "dev": true
640 | },
641 | "is-nan": {
642 | "version": "1.3.0",
643 | "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.0.tgz",
644 | "integrity": "sha512-z7bbREymOqt2CCaZVly8aC4ML3Xhfi0ekuOnjO2L8vKdl+CttdVoGZQhd4adMFAsxQ5VeRVwORs4tU8RH+HFtQ==",
645 | "dev": true,
646 | "requires": {
647 | "define-properties": "^1.1.3"
648 | }
649 | },
650 | "is-number": {
651 | "version": "7.0.0",
652 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
653 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
654 | "dev": true
655 | },
656 | "is-plain-obj": {
657 | "version": "1.1.0",
658 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
659 | "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
660 | "dev": true
661 | },
662 | "is-regex": {
663 | "version": "1.1.1",
664 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
665 | "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
666 | "dev": true,
667 | "requires": {
668 | "has-symbols": "^1.0.1"
669 | }
670 | },
671 | "is-set": {
672 | "version": "2.0.1",
673 | "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz",
674 | "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==",
675 | "dev": true
676 | },
677 | "is-string": {
678 | "version": "1.0.5",
679 | "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz",
680 | "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
681 | "dev": true
682 | },
683 | "is-symbol": {
684 | "version": "1.0.3",
685 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
686 | "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
687 | "dev": true,
688 | "requires": {
689 | "has-symbols": "^1.0.1"
690 | }
691 | },
692 | "is-typed-array": {
693 | "version": "1.1.3",
694 | "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.3.tgz",
695 | "integrity": "sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ==",
696 | "dev": true,
697 | "requires": {
698 | "available-typed-arrays": "^1.0.0",
699 | "es-abstract": "^1.17.4",
700 | "foreach": "^2.0.5",
701 | "has-symbols": "^1.0.1"
702 | }
703 | },
704 | "isarray": {
705 | "version": "2.0.5",
706 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
707 | "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
708 | "dev": true
709 | },
710 | "isexe": {
711 | "version": "2.0.0",
712 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
713 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
714 | "dev": true
715 | },
716 | "iterate-iterator": {
717 | "version": "1.0.1",
718 | "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.1.tgz",
719 | "integrity": "sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==",
720 | "dev": true
721 | },
722 | "iterate-value": {
723 | "version": "1.0.2",
724 | "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz",
725 | "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==",
726 | "dev": true,
727 | "requires": {
728 | "es-get-iterator": "^1.0.2",
729 | "iterate-iterator": "^1.0.1"
730 | }
731 | },
732 | "js-yaml": {
733 | "version": "3.13.1",
734 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
735 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
736 | "dev": true,
737 | "requires": {
738 | "argparse": "^1.0.7",
739 | "esprima": "^4.0.0"
740 | }
741 | },
742 | "locate-path": {
743 | "version": "5.0.0",
744 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
745 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
746 | "dev": true,
747 | "requires": {
748 | "p-locate": "^4.1.0"
749 | }
750 | },
751 | "log-symbols": {
752 | "version": "3.0.0",
753 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz",
754 | "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==",
755 | "dev": true,
756 | "requires": {
757 | "chalk": "^2.4.2"
758 | }
759 | },
760 | "minimatch": {
761 | "version": "3.0.4",
762 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
763 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
764 | "dev": true,
765 | "requires": {
766 | "brace-expansion": "^1.1.7"
767 | }
768 | },
769 | "mocha": {
770 | "version": "8.1.1",
771 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.1.1.tgz",
772 | "integrity": "sha512-p7FuGlYH8t7gaiodlFreseLxEmxTgvyG9RgPHODFPySNhwUehu8NIb0vdSt3WFckSneswZ0Un5typYcWElk7HQ==",
773 | "dev": true,
774 | "requires": {
775 | "ansi-colors": "4.1.1",
776 | "browser-stdout": "1.3.1",
777 | "chokidar": "3.3.1",
778 | "debug": "3.2.6",
779 | "diff": "4.0.2",
780 | "escape-string-regexp": "1.0.5",
781 | "find-up": "4.1.0",
782 | "glob": "7.1.6",
783 | "growl": "1.10.5",
784 | "he": "1.2.0",
785 | "js-yaml": "3.13.1",
786 | "log-symbols": "3.0.0",
787 | "minimatch": "3.0.4",
788 | "ms": "2.1.2",
789 | "object.assign": "4.1.0",
790 | "promise.allsettled": "1.0.2",
791 | "serialize-javascript": "4.0.0",
792 | "strip-json-comments": "3.0.1",
793 | "supports-color": "7.1.0",
794 | "which": "2.0.2",
795 | "wide-align": "1.1.3",
796 | "workerpool": "6.0.0",
797 | "yargs": "13.3.2",
798 | "yargs-parser": "13.1.2",
799 | "yargs-unparser": "1.6.1"
800 | }
801 | },
802 | "ms": {
803 | "version": "2.1.2",
804 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
805 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
806 | "dev": true
807 | },
808 | "normalize-path": {
809 | "version": "3.0.0",
810 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
811 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
812 | "dev": true
813 | },
814 | "object-inspect": {
815 | "version": "1.8.0",
816 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
817 | "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==",
818 | "dev": true
819 | },
820 | "object-is": {
821 | "version": "1.1.2",
822 | "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz",
823 | "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==",
824 | "dev": true,
825 | "requires": {
826 | "define-properties": "^1.1.3",
827 | "es-abstract": "^1.17.5"
828 | }
829 | },
830 | "object-keys": {
831 | "version": "1.1.1",
832 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
833 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
834 | "dev": true
835 | },
836 | "object.assign": {
837 | "version": "4.1.0",
838 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
839 | "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
840 | "dev": true,
841 | "requires": {
842 | "define-properties": "^1.1.2",
843 | "function-bind": "^1.1.1",
844 | "has-symbols": "^1.0.0",
845 | "object-keys": "^1.0.11"
846 | }
847 | },
848 | "once": {
849 | "version": "1.4.0",
850 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
851 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
852 | "dev": true,
853 | "requires": {
854 | "wrappy": "1"
855 | }
856 | },
857 | "p-limit": {
858 | "version": "2.3.0",
859 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
860 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
861 | "dev": true,
862 | "requires": {
863 | "p-try": "^2.0.0"
864 | }
865 | },
866 | "p-locate": {
867 | "version": "4.1.0",
868 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
869 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
870 | "dev": true,
871 | "requires": {
872 | "p-limit": "^2.2.0"
873 | }
874 | },
875 | "p-try": {
876 | "version": "2.2.0",
877 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
878 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
879 | "dev": true
880 | },
881 | "path-exists": {
882 | "version": "4.0.0",
883 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
884 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
885 | "dev": true
886 | },
887 | "path-is-absolute": {
888 | "version": "1.0.1",
889 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
890 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
891 | "dev": true
892 | },
893 | "picomatch": {
894 | "version": "2.2.2",
895 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
896 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
897 | "dev": true
898 | },
899 | "promise.allsettled": {
900 | "version": "1.0.2",
901 | "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.2.tgz",
902 | "integrity": "sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg==",
903 | "dev": true,
904 | "requires": {
905 | "array.prototype.map": "^1.0.1",
906 | "define-properties": "^1.1.3",
907 | "es-abstract": "^1.17.0-next.1",
908 | "function-bind": "^1.1.1",
909 | "iterate-value": "^1.0.0"
910 | }
911 | },
912 | "randombytes": {
913 | "version": "2.1.0",
914 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
915 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
916 | "dev": true,
917 | "requires": {
918 | "safe-buffer": "^5.1.0"
919 | }
920 | },
921 | "readdirp": {
922 | "version": "3.3.0",
923 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz",
924 | "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==",
925 | "dev": true,
926 | "requires": {
927 | "picomatch": "^2.0.7"
928 | }
929 | },
930 | "require-directory": {
931 | "version": "2.1.1",
932 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
933 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
934 | "dev": true
935 | },
936 | "require-main-filename": {
937 | "version": "2.0.0",
938 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
939 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
940 | "dev": true
941 | },
942 | "rimraf": {
943 | "version": "2.7.1",
944 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
945 | "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
946 | "dev": true,
947 | "requires": {
948 | "glob": "^7.1.3"
949 | },
950 | "dependencies": {
951 | "glob": {
952 | "version": "7.1.6",
953 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
954 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
955 | "dev": true,
956 | "requires": {
957 | "fs.realpath": "^1.0.0",
958 | "inflight": "^1.0.4",
959 | "inherits": "2",
960 | "minimatch": "^3.0.4",
961 | "once": "^1.3.0",
962 | "path-is-absolute": "^1.0.0"
963 | }
964 | },
965 | "minimatch": {
966 | "version": "3.0.4",
967 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
968 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
969 | "dev": true,
970 | "requires": {
971 | "brace-expansion": "^1.1.7"
972 | }
973 | }
974 | }
975 | },
976 | "safe-buffer": {
977 | "version": "5.2.1",
978 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
979 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
980 | "dev": true
981 | },
982 | "serialize-javascript": {
983 | "version": "4.0.0",
984 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
985 | "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
986 | "dev": true,
987 | "requires": {
988 | "randombytes": "^2.1.0"
989 | }
990 | },
991 | "set-blocking": {
992 | "version": "2.0.0",
993 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
994 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
995 | "dev": true
996 | },
997 | "sprintf-js": {
998 | "version": "1.0.3",
999 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
1000 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
1001 | "dev": true
1002 | },
1003 | "string-width": {
1004 | "version": "2.1.1",
1005 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
1006 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
1007 | "dev": true,
1008 | "requires": {
1009 | "is-fullwidth-code-point": "^2.0.0",
1010 | "strip-ansi": "^4.0.0"
1011 | }
1012 | },
1013 | "string.prototype.trimend": {
1014 | "version": "1.0.1",
1015 | "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
1016 | "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
1017 | "dev": true,
1018 | "requires": {
1019 | "define-properties": "^1.1.3",
1020 | "es-abstract": "^1.17.5"
1021 | }
1022 | },
1023 | "string.prototype.trimstart": {
1024 | "version": "1.0.1",
1025 | "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
1026 | "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
1027 | "dev": true,
1028 | "requires": {
1029 | "define-properties": "^1.1.3",
1030 | "es-abstract": "^1.17.5"
1031 | }
1032 | },
1033 | "strip-ansi": {
1034 | "version": "4.0.0",
1035 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
1036 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
1037 | "dev": true,
1038 | "requires": {
1039 | "ansi-regex": "^3.0.0"
1040 | }
1041 | },
1042 | "strip-json-comments": {
1043 | "version": "3.0.1",
1044 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz",
1045 | "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==",
1046 | "dev": true
1047 | },
1048 | "supports-color": {
1049 | "version": "7.1.0",
1050 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
1051 | "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
1052 | "dev": true,
1053 | "requires": {
1054 | "has-flag": "^4.0.0"
1055 | },
1056 | "dependencies": {
1057 | "has-flag": {
1058 | "version": "4.0.0",
1059 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
1060 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
1061 | "dev": true
1062 | }
1063 | }
1064 | },
1065 | "to-regex-range": {
1066 | "version": "5.0.1",
1067 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
1068 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
1069 | "dev": true,
1070 | "requires": {
1071 | "is-number": "^7.0.0"
1072 | }
1073 | },
1074 | "typescript": {
1075 | "version": "3.9.7",
1076 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz",
1077 | "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==",
1078 | "dev": true
1079 | },
1080 | "util": {
1081 | "version": "0.12.3",
1082 | "resolved": "https://registry.npmjs.org/util/-/util-0.12.3.tgz",
1083 | "integrity": "sha512-I8XkoQwE+fPQEhy9v012V+TSdH2kp9ts29i20TaaDUXsg7x/onePbhFJUExBfv/2ay1ZOp/Vsm3nDlmnFGSAog==",
1084 | "dev": true,
1085 | "requires": {
1086 | "inherits": "^2.0.3",
1087 | "is-arguments": "^1.0.4",
1088 | "is-generator-function": "^1.0.7",
1089 | "is-typed-array": "^1.1.3",
1090 | "safe-buffer": "^5.1.2",
1091 | "which-typed-array": "^1.1.2"
1092 | },
1093 | "dependencies": {
1094 | "inherits": {
1095 | "version": "2.0.4",
1096 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
1097 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
1098 | "dev": true
1099 | }
1100 | }
1101 | },
1102 | "vscode-test": {
1103 | "version": "1.4.0",
1104 | "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.4.0.tgz",
1105 | "integrity": "sha512-Jt7HNGvSE0+++Tvtq5wc4hiXLIr2OjDShz/gbAfM/mahQpy4rKBnmOK33D+MR67ATWviQhl+vpmU3p/qwSH/Pg==",
1106 | "dev": true,
1107 | "requires": {
1108 | "http-proxy-agent": "^2.1.0",
1109 | "https-proxy-agent": "^2.2.4",
1110 | "rimraf": "^2.6.3"
1111 | }
1112 | },
1113 | "which": {
1114 | "version": "2.0.2",
1115 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
1116 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
1117 | "dev": true,
1118 | "requires": {
1119 | "isexe": "^2.0.0"
1120 | }
1121 | },
1122 | "which-module": {
1123 | "version": "2.0.0",
1124 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
1125 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
1126 | "dev": true
1127 | },
1128 | "which-typed-array": {
1129 | "version": "1.1.2",
1130 | "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.2.tgz",
1131 | "integrity": "sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ==",
1132 | "dev": true,
1133 | "requires": {
1134 | "available-typed-arrays": "^1.0.2",
1135 | "es-abstract": "^1.17.5",
1136 | "foreach": "^2.0.5",
1137 | "function-bind": "^1.1.1",
1138 | "has-symbols": "^1.0.1",
1139 | "is-typed-array": "^1.1.3"
1140 | }
1141 | },
1142 | "wide-align": {
1143 | "version": "1.1.3",
1144 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
1145 | "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
1146 | "dev": true,
1147 | "requires": {
1148 | "string-width": "^1.0.2 || 2"
1149 | }
1150 | },
1151 | "workerpool": {
1152 | "version": "6.0.0",
1153 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.0.tgz",
1154 | "integrity": "sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA==",
1155 | "dev": true
1156 | },
1157 | "wrap-ansi": {
1158 | "version": "5.1.0",
1159 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
1160 | "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
1161 | "dev": true,
1162 | "requires": {
1163 | "ansi-styles": "^3.2.0",
1164 | "string-width": "^3.0.0",
1165 | "strip-ansi": "^5.0.0"
1166 | },
1167 | "dependencies": {
1168 | "ansi-regex": {
1169 | "version": "4.1.0",
1170 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
1171 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
1172 | "dev": true
1173 | },
1174 | "string-width": {
1175 | "version": "3.1.0",
1176 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
1177 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
1178 | "dev": true,
1179 | "requires": {
1180 | "emoji-regex": "^7.0.1",
1181 | "is-fullwidth-code-point": "^2.0.0",
1182 | "strip-ansi": "^5.1.0"
1183 | }
1184 | },
1185 | "strip-ansi": {
1186 | "version": "5.2.0",
1187 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
1188 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
1189 | "dev": true,
1190 | "requires": {
1191 | "ansi-regex": "^4.1.0"
1192 | }
1193 | }
1194 | }
1195 | },
1196 | "wrappy": {
1197 | "version": "1.0.2",
1198 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1199 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
1200 | "dev": true
1201 | },
1202 | "y18n": {
1203 | "version": "4.0.0",
1204 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
1205 | "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
1206 | "dev": true
1207 | },
1208 | "yargs": {
1209 | "version": "13.3.2",
1210 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
1211 | "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
1212 | "dev": true,
1213 | "requires": {
1214 | "cliui": "^5.0.0",
1215 | "find-up": "^3.0.0",
1216 | "get-caller-file": "^2.0.1",
1217 | "require-directory": "^2.1.1",
1218 | "require-main-filename": "^2.0.0",
1219 | "set-blocking": "^2.0.0",
1220 | "string-width": "^3.0.0",
1221 | "which-module": "^2.0.0",
1222 | "y18n": "^4.0.0",
1223 | "yargs-parser": "^13.1.2"
1224 | },
1225 | "dependencies": {
1226 | "ansi-regex": {
1227 | "version": "4.1.0",
1228 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
1229 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
1230 | "dev": true
1231 | },
1232 | "find-up": {
1233 | "version": "3.0.0",
1234 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
1235 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
1236 | "dev": true,
1237 | "requires": {
1238 | "locate-path": "^3.0.0"
1239 | }
1240 | },
1241 | "locate-path": {
1242 | "version": "3.0.0",
1243 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
1244 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
1245 | "dev": true,
1246 | "requires": {
1247 | "p-locate": "^3.0.0",
1248 | "path-exists": "^3.0.0"
1249 | }
1250 | },
1251 | "p-locate": {
1252 | "version": "3.0.0",
1253 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
1254 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
1255 | "dev": true,
1256 | "requires": {
1257 | "p-limit": "^2.0.0"
1258 | }
1259 | },
1260 | "path-exists": {
1261 | "version": "3.0.0",
1262 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
1263 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
1264 | "dev": true
1265 | },
1266 | "string-width": {
1267 | "version": "3.1.0",
1268 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
1269 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
1270 | "dev": true,
1271 | "requires": {
1272 | "emoji-regex": "^7.0.1",
1273 | "is-fullwidth-code-point": "^2.0.0",
1274 | "strip-ansi": "^5.1.0"
1275 | }
1276 | },
1277 | "strip-ansi": {
1278 | "version": "5.2.0",
1279 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
1280 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
1281 | "dev": true,
1282 | "requires": {
1283 | "ansi-regex": "^4.1.0"
1284 | }
1285 | }
1286 | }
1287 | },
1288 | "yargs-parser": {
1289 | "version": "13.1.2",
1290 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
1291 | "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
1292 | "dev": true,
1293 | "requires": {
1294 | "camelcase": "^5.0.0",
1295 | "decamelize": "^1.2.0"
1296 | }
1297 | },
1298 | "yargs-unparser": {
1299 | "version": "1.6.1",
1300 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.1.tgz",
1301 | "integrity": "sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA==",
1302 | "dev": true,
1303 | "requires": {
1304 | "camelcase": "^5.3.1",
1305 | "decamelize": "^1.2.0",
1306 | "flat": "^4.1.0",
1307 | "is-plain-obj": "^1.1.0",
1308 | "yargs": "^14.2.3"
1309 | },
1310 | "dependencies": {
1311 | "ansi-regex": {
1312 | "version": "4.1.0",
1313 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
1314 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
1315 | "dev": true
1316 | },
1317 | "find-up": {
1318 | "version": "3.0.0",
1319 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
1320 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
1321 | "dev": true,
1322 | "requires": {
1323 | "locate-path": "^3.0.0"
1324 | }
1325 | },
1326 | "locate-path": {
1327 | "version": "3.0.0",
1328 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
1329 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
1330 | "dev": true,
1331 | "requires": {
1332 | "p-locate": "^3.0.0",
1333 | "path-exists": "^3.0.0"
1334 | }
1335 | },
1336 | "p-locate": {
1337 | "version": "3.0.0",
1338 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
1339 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
1340 | "dev": true,
1341 | "requires": {
1342 | "p-limit": "^2.0.0"
1343 | }
1344 | },
1345 | "path-exists": {
1346 | "version": "3.0.0",
1347 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
1348 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
1349 | "dev": true
1350 | },
1351 | "string-width": {
1352 | "version": "3.1.0",
1353 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
1354 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
1355 | "dev": true,
1356 | "requires": {
1357 | "emoji-regex": "^7.0.1",
1358 | "is-fullwidth-code-point": "^2.0.0",
1359 | "strip-ansi": "^5.1.0"
1360 | }
1361 | },
1362 | "strip-ansi": {
1363 | "version": "5.2.0",
1364 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
1365 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
1366 | "dev": true,
1367 | "requires": {
1368 | "ansi-regex": "^4.1.0"
1369 | }
1370 | },
1371 | "yargs": {
1372 | "version": "14.2.3",
1373 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz",
1374 | "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==",
1375 | "dev": true,
1376 | "requires": {
1377 | "cliui": "^5.0.0",
1378 | "decamelize": "^1.2.0",
1379 | "find-up": "^3.0.0",
1380 | "get-caller-file": "^2.0.1",
1381 | "require-directory": "^2.1.1",
1382 | "require-main-filename": "^2.0.0",
1383 | "set-blocking": "^2.0.0",
1384 | "string-width": "^3.0.0",
1385 | "which-module": "^2.0.0",
1386 | "y18n": "^4.0.0",
1387 | "yargs-parser": "^15.0.1"
1388 | }
1389 | },
1390 | "yargs-parser": {
1391 | "version": "15.0.1",
1392 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz",
1393 | "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==",
1394 | "dev": true,
1395 | "requires": {
1396 | "camelcase": "^5.0.0",
1397 | "decamelize": "^1.2.0"
1398 | }
1399 | }
1400 | }
1401 | }
1402 | }
1403 | }
1404 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "indenticator",
3 | "displayName": "Indenticator",
4 | "description": "Highlights your current indent depth",
5 | "version": "0.7.0",
6 | "publisher": "SirTori",
7 | "homepage": "https://github.com/SirTori/indenticator/blob/master/README.md",
8 | "license": "SEE LICENSE IN LICENSE.txt",
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/SirTori/indenticator"
12 | },
13 | "icon": "img/icon.png",
14 | "galleryBanner": {
15 | "color": "#877d88",
16 | "theme": "dark"
17 | },
18 | "badges": [
19 | {
20 | "url": "https://david-dm.org/sirtori/indenticator.svg",
21 | "href": "https://david-dm.org/sirtori/indenticator",
22 | "description": "Dependency Status"
23 | },
24 | {
25 | "url": "https://travis-ci.org/SirTori/indenticator.svg?branch=master",
26 | "href": "https://travis-ci.org/SirTori/indenticator",
27 | "description": "Build Status"
28 | }
29 | ],
30 | "bugs": {
31 | "url": "https://github.com/SirTori/indenticator/issues"
32 | },
33 | "engines": {
34 | "vscode": "^1.48.0"
35 | },
36 | "categories": [
37 | "Other"
38 | ],
39 | "keywords": [
40 | "guides",
41 | "indentation",
42 | "indentation guides",
43 | "indent",
44 | "indent guides",
45 | "block highlight",
46 | "vertical block line"
47 | ],
48 | "activationEvents": [
49 | "*"
50 | ],
51 | "main": "./out/src/extension",
52 | "scripts": {
53 | "vscode:prepublish": "npm run compile",
54 | "compile": "tsc -p ./",
55 | "lint": "eslint . --ext .ts,.tsx",
56 | "watch": "tsc -watch -p ./",
57 | "pretest": "npm run compile",
58 | "test": "node ./out/test/runTest.js"
59 | },
60 | "devDependencies": {
61 | "@types/glob": "^7.1.1",
62 | "@types/mocha": "^8.0.0",
63 | "@types/node": "^12.0.0",
64 | "@types/vscode": "^1.48.0",
65 | "vscode-test": "^1.4.0",
66 | "glob": "^7.1.4",
67 | "assert": "^2.0.0",
68 | "mocha": "^8.0.0",
69 | "typescript": "^3.3.1"
70 | },
71 | "contributes": {
72 | "configuration": {
73 | "type": "object",
74 | "title": "Indenticator Configuration",
75 | "properties": {
76 | "indenticator.showIndentGuide": {
77 | "type": "boolean",
78 | "default": true,
79 | "description": "Whether to highlight the indent of the block enclosing the current line"
80 | },
81 | "indenticator.color.dark": {
82 | "type": "string",
83 | "default": "#888",
84 | "description": "Color of the indent marker for dark themes"
85 | },
86 | "indenticator.color.light": {
87 | "type": "string",
88 | "default": "#999",
89 | "description": "Color of the indent marker for light themes"
90 | },
91 | "indenticator.width": {
92 | "type": "number",
93 | "default": 1,
94 | "description": "Width of the indent marker in pixels"
95 | },
96 | "indenticator.style": {
97 | "type": "string",
98 | "default": "inset",
99 | "description": "Line style of the indent marker"
100 | },
101 | "indenticator.inner.showIndentGuide": {
102 | "type": "boolean",
103 | "default": false,
104 | "description": "Whether to highlight the indent of the block enclosed by the current line"
105 | },
106 | "indenticator.inner.color.dark": {
107 | "type": "string",
108 | "description": "Color of the inner indent marker for dark themes"
109 | },
110 | "indenticator.inner.color.light": {
111 | "type": "string",
112 | "default": "#999",
113 | "description": "Color of the inner indent marker for light themes"
114 | },
115 | "indenticator.inner.width": {
116 | "type": "number",
117 | "default": 1,
118 | "description": "Width of the inner indent marker in pixels"
119 | },
120 | "indenticator.inner.style": {
121 | "type": "string",
122 | "default": "inset",
123 | "description": "Line style of the inner indent marker"
124 | },
125 | "indenticator.showCurrentDepthInStatusBar": {
126 | "type": "boolean",
127 | "default": true,
128 | "description": "Whether to display the current indent depth on the statusbar"
129 | },
130 | "indenticator.showHover": {
131 | "type": [
132 | "boolean",
133 | "number"
134 | ],
135 | "default": false,
136 | "description": "Whether to display the hover near the indent line, or minimum number of lines in current indent block to activate the hover."
137 | },
138 | "indenticator.hover.highlight": {
139 | "type": "boolean",
140 | "default": true,
141 | "description": "Wether to highlight the contained code block when hovering the indent line. If activated, the peeked content will be shown at top or bottom of the block, otherwise it will be shown at cursor position."
142 | },
143 | "indenticator.hover.peekBack": {
144 | "type": "number",
145 | "default": 1,
146 | "description": "Lines before the current indent to be shown on hover"
147 | },
148 | "indenticator.hover.peekForward": {
149 | "type": "number",
150 | "default": 0,
151 | "description": "Lines after the current indent to be shown on hover"
152 | },
153 | "indenticator.hover.trimLinesShorterThan": {
154 | "type": "number",
155 | "default": 2,
156 | "description": "Remove lines from the hover at the beginning and end that have less characters than this"
157 | },
158 | "indenticator.hover.peekBlockPlaceholder": {
159 | "type": "string",
160 | "default": "...",
161 | "description": "Block placeholder to be written between peeked lines"
162 | },
163 | "indenticator.inner.showHover": {
164 | "type": [
165 | "boolean",
166 | "number"
167 | ],
168 | "default": false,
169 | "description": "Whether to display the hover near the inner indent line, or minimum number of lines in current indent block to activate the hover."
170 | },
171 | "indenticator.inner.hover.highlight": {
172 | "type": "boolean",
173 | "default": true,
174 | "description": "Wether to highlight the contained code block when hovering the inner indent line. If activated, the peeked content will be shown at top or bottom of the block, otherwise it will be shown at cursor position."
175 | },
176 | "indenticator.inner.hover.peekBack": {
177 | "type": "number",
178 | "default": 1,
179 | "description": "Lines before the current inner indent to be shown on hover"
180 | },
181 | "indenticator.inner.hover.peekForward": {
182 | "type": "number",
183 | "default": 0,
184 | "description": "Lines after the current inner indent to be shown on hover"
185 | },
186 | "indenticator.inner.hover.trimLinesShorterThan": {
187 | "type": "number",
188 | "default": 2,
189 | "description": "Remove lines from the inner indent hover at the beginning and end that have less characters than this"
190 | },
191 | "indenticator.inner.hover.peekBlockPlaceholder": {
192 | "type": "string",
193 | "default": "...",
194 | "description": "Block placeholder to be written between peeked lines for the hover of the inner indent"
195 | },
196 | "indenticator.languageSpecific": {
197 | "type": [
198 | "object"
199 | ],
200 | "default": {},
201 | "description": "A construct with language identifiers as properties containing a subset of indenticator options to be applied to that language",
202 | "additionalProperties": false,
203 | "patternProperties": {
204 | "^\\[(\\w+,?\\s*)+\\]$": {
205 | "type": [
206 | "object"
207 | ],
208 | "description": "Language Specific config",
209 | "additionalProperties": false,
210 | "properties": {
211 | "indenticator.showHighlight": {
212 | "type": "boolean",
213 | "default": true,
214 | "description": "Whether to highlight the indent of the block enclosing the current line"
215 | },
216 | "indenticator.color.dark": {
217 | "type": "string",
218 | "default": "#888",
219 | "description": "Color of the indent marker for dark themes"
220 | },
221 | "indenticator.color.light": {
222 | "type": "string",
223 | "default": "#999",
224 | "description": "Color of the indent marker for light themes"
225 | },
226 | "indenticator.width": {
227 | "type": "number",
228 | "default": 1,
229 | "description": "Width of the indent marker in pixels"
230 | },
231 | "indenticator.style": {
232 | "type": "string",
233 | "default": "inset",
234 | "description": "Line style of the indent marker"
235 | },
236 | "indenticator.inner.showHighlight": {
237 | "type": "boolean",
238 | "default": false,
239 | "description": "Whether to highlight the indent of the block enclosed by the current line"
240 | },
241 | "indenticator.inner.color.dark": {
242 | "type": "string",
243 | "default": "#888",
244 | "description": "Color of the indent marker for dark themes"
245 | },
246 | "indenticator.inner.color.light": {
247 | "type": "string",
248 | "default": "#999",
249 | "description": "Color of the indent marker for light themes"
250 | },
251 | "indenticator.inner.width": {
252 | "type": "number",
253 | "default": 1,
254 | "description": "Width of the indent marker in pixels"
255 | },
256 | "indenticator.inner.style": {
257 | "type": "string",
258 | "default": "inset",
259 | "description": "Line style of the indent marker"
260 | },
261 | "indenticator.showCurrentDepthInStatusBar": {
262 | "type": "boolean",
263 | "default": true,
264 | "description": "Whether to display the current indent depth on the statusbar"
265 | },
266 | "indenticator.showHover": {
267 | "type": [
268 | "boolean",
269 | "number"
270 | ],
271 | "default": false,
272 | "description": "Whether to display the hover near the indent line, or minimum number of lines in current indent block to activate the hover."
273 | },
274 | "indenticator.hover.highlight": {
275 | "type": "boolean",
276 | "default": true,
277 | "description": "Wether to highlight the contained code block when hovering the indent line. If activated, the peeked content will be shown at top or bottom of the block, otherwise it will be shown at cursor position."
278 | },
279 | "indenticator.hover.peekBack": {
280 | "type": "number",
281 | "default": 1,
282 | "description": "Lines before the current indent to be shown on hover"
283 | },
284 | "indenticator.hover.peekForward": {
285 | "type": "number",
286 | "default": 0,
287 | "description": "Lines after the current indent to be shown on hover"
288 | },
289 | "indenticator.hover.trimLinesShorterThan": {
290 | "type": "number",
291 | "default": 2,
292 | "description": "Remove lines from the hover at the beginning and end that have less characters than this"
293 | },
294 | "indenticator.hover.peekBlockPlaceholder": {
295 | "type": "string",
296 | "default": "...",
297 | "description": "Block placeholder to be written between peeked lines"
298 | },
299 | "indenticator.inner.showHover": {
300 | "type": [
301 | "boolean",
302 | "number"
303 | ],
304 | "default": false,
305 | "description": "Whether to display the hover near the inner indent line, or minimum number of lines in current indent block to activate the hover."
306 | },
307 | "indenticator.inner.hover.highlight": {
308 | "type": "boolean",
309 | "default": true,
310 | "description": "Wether to highlight the contained code block when hovering the inner indent line. If activated, the peeked content will be shown at top or bottom of the block, otherwise it will be shown at cursor position."
311 | },
312 | "indenticator.inner.hover.peekBack": {
313 | "type": "number",
314 | "default": 1,
315 | "description": "Lines before the current inner indent to be shown on hover"
316 | },
317 | "indenticator.inner.hover.peekForward": {
318 | "type": "number",
319 | "default": 0,
320 | "description": "Lines after the current inner indent to be shown on hover"
321 | },
322 | "indenticator.inner.hover.trimLinesShorterThan": {
323 | "type": "number",
324 | "default": 2,
325 | "description": "Remove lines from the inner indent hover at the beginning and end that have less characters than this"
326 | },
327 | "indenticator.inner.hover.peekBlockPlaceholder": {
328 | "type": "string",
329 | "default": "...",
330 | "description": "Block placeholder to be written between peeked lines for the hover of the inner indent"
331 | }
332 | }
333 | }
334 | }
335 | }
336 | }
337 | }
338 | }
339 | }
340 |
--------------------------------------------------------------------------------
/src/extension.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | // The module 'vscode' contains the VS Code extensibility API
3 | // Import the module and reference it with the alias vscode in your code below
4 | import {window, Disposable, ExtensionContext, StatusBarAlignment,
5 | StatusBarItem, TextDocument, TextEditor, TextEditorOptions,
6 | TextEditorDecorationType, TextLine, Selection, Range,
7 | Position, workspace, env, languages, WorkspaceConfiguration, Hover
8 | } from 'vscode';
9 | // this method is called when your extension is activated
10 | // your extension is activated the very first time the command is executed
11 | export function activate(context: ExtensionContext) {
12 |
13 | let indentSpy = new IndentSpy();
14 | let indentSpyController = new IndentSpyController(indentSpy);
15 |
16 | context.subscriptions.push(indentSpy);
17 | context.subscriptions.push(indentSpyController);
18 | }
19 |
20 | // this method is called when your extension is deactivated
21 | export function deactivate() {
22 | }
23 |
24 | class LanguageConfig {
25 | constructor(public langConfig: any,
26 | public config: WorkspaceConfiguration) {}
27 |
28 | get(name: string, defaultValue?:T ): T {
29 | let v = this.langConfig[`indenticator.${name}`];
30 | if(v !== undefined) {
31 | return v;
32 | }
33 | return this.config.get(name, defaultValue);
34 | }
35 | }
36 |
37 | class IndentConfiguration {
38 | show: boolean;
39 | style: TextEditorDecorationType;
40 | hover: number;
41 | hoverConf: {
42 | highlight: boolean,
43 | peekBack: number,
44 | peekForward: number,
45 | trimLinesShorterThan: number,
46 | peekBlockPlaceholder: string
47 | };
48 | hoverProvider: Disposable
49 | firstLine: number;
50 | lastLine: number;
51 | indentPos: number;
52 | }
53 |
54 | export class IndentSpy {
55 | _locales: Object;
56 | _currentLocale: Object;
57 | _statusBarItem: StatusBarItem;
58 | _outerConf: IndentConfiguration = new IndentConfiguration();
59 | _innerConf: IndentConfiguration = new IndentConfiguration();
60 |
61 | constructor() {
62 | this._locales = {
63 | en: {statusText: `Indents: {indent}`,
64 | statusTooltip: `current indent depth: {indent}`},
65 | de: {statusText: `Einzüge: {indent}`,
66 | statusTooltip: `aktuelle Einzugtiefe: {indent}`},
67 | ja: {statusText: `字下げ: {indent}`,
68 | statusTooltip: `現在のインデントの深さ: {indent}`},
69 | default: {statusText: `Indents: {indent}`,
70 | statusTooltip: `current indent depth: {indent}`},
71 | };
72 | this.updateConfig();
73 | }
74 |
75 | public updateConfig() {
76 | this._clearDecorators();
77 |
78 | let locale = env.language;
79 | let multipartLocale = env.language.indexOf('-');
80 | if(multipartLocale >= 0) {
81 | locale = locale.substring(0, multipartLocale);
82 | }
83 |
84 | if(!this._locales[locale]) {
85 | this._currentLocale = this._locales['default'];
86 | } else {
87 | this._currentLocale = this._locales[locale];
88 | }
89 | let langConfig = {};
90 | let config = workspace.getConfiguration('indenticator');
91 | if(window.activeTextEditor) {
92 | let docLang = window.activeTextEditor.document.languageId
93 | let allLangConfig = config.get("languageSpecific", {});
94 | let docLangKey = Object.keys(allLangConfig).find(k => {
95 | return k.match(`^\\[(.*,\\s*)?${docLang}(,.*)?\\]$`) !== null;
96 | });
97 | if(docLangKey) {
98 | langConfig = allLangConfig[docLangKey] || {};
99 | }
100 | }
101 | let myConf = new LanguageConfig(langConfig, config);
102 |
103 | if(myConf.get('showCurrentDepthInStatusBar')) {
104 | if(!this._statusBarItem) {
105 | this._statusBarItem = window.createStatusBarItem(
106 | StatusBarAlignment.Right, 100);
107 | }
108 | } else if(this._statusBarItem) {
109 | this._statusBarItem.dispose();
110 | this._statusBarItem = undefined;
111 | }
112 |
113 | this._outerConf.show = myConf.get('showIndentGuide');
114 | this._innerConf.show = myConf.get('inner.showIndentGuide');
115 |
116 | this._outerConf.style = window.createTextEditorDecorationType({
117 | dark: {
118 | borderColor: myConf.get('color.dark', '#888'),
119 | borderStyle: myConf.get('style', 'inset'),
120 | borderWidth: myConf.get('width', 1) + "px"
121 | },
122 | light: {
123 | borderColor: myConf.get('color.light', '#999'),
124 | borderStyle: myConf.get('style', 'inset'),
125 | borderWidth: myConf.get('width', 1) + "px"
126 | }
127 | });
128 |
129 | this._innerConf.style = window.createTextEditorDecorationType({
130 | dark: {
131 | borderColor: myConf.get('inner.color.dark', '#888'),
132 | borderStyle: myConf.get('inner.style', 'inset'),
133 | borderWidth: myConf.get('inner.width', 1) + "px"
134 | },
135 | light: {
136 | borderColor: myConf.get('inner.color.light', '#999'),
137 | borderStyle: myConf.get('inner.style', 'inset'),
138 | borderWidth: myConf.get('inner.width', 1) + "px"
139 | }
140 | });
141 |
142 | let showHover:boolean|number = myConf.get('showHover', false);
143 | if(typeof showHover === 'boolean') {
144 | this._outerConf.hover = showHover ? 1 : 0;
145 | } else {
146 | this._outerConf.hover = showHover;
147 | }
148 | if(this._outerConf.hover) {
149 | this._outerConf.hoverConf = {
150 | highlight: myConf.get('hover.highlight', true),
151 | peekBack: myConf.get('hover.peekBack', 1),
152 | peekForward: myConf.get('hover.peekForward', 0),
153 | trimLinesShorterThan: myConf.get(
154 | 'hover.trimLinesShorterThan', 2),
155 | peekBlockPlaceholder: myConf.get(
156 | 'hover.peekBlockPlaceholder', '...')
157 | };
158 | } else if (this._outerConf.hoverProvider) {
159 | this._outerConf.hoverProvider.dispose();
160 | }
161 |
162 | showHover = myConf.get('inner.showHover', false);
163 | if(typeof showHover === 'boolean') {
164 | this._innerConf.hover = showHover ? 1 : 0;
165 | } else {
166 | this._innerConf.hover = showHover;
167 | }
168 | if(this._innerConf.hover) {
169 | this._innerConf.hoverConf = {
170 | highlight: myConf.get('inner.hover.highlight', true),
171 | peekBack: myConf.get('inner.hover.peekBack', 1),
172 | peekForward: myConf.get('inner.hover.peekForward', 0),
173 | trimLinesShorterThan: myConf.get(
174 | 'inner.hover.trimLinesShorterThan', 2),
175 | peekBlockPlaceholder: myConf.get(
176 | 'inner.hover.peekBlockPlaceholder', '...')
177 | };
178 | } else if (this._innerConf.hoverProvider) {
179 | this._innerConf.hoverProvider.dispose();
180 | }
181 |
182 | this.updateCurrentIndent();
183 | }
184 |
185 | public updateCurrentIndent() {
186 | let hideStatusbarIfPossible = () => {
187 | if(this._statusBarItem) {
188 | this._statusBarItem.hide();
189 | }
190 | }
191 |
192 | let editor = window.activeTextEditor;
193 | if (!editor) {
194 | hideStatusbarIfPossible();
195 | return;
196 | }
197 |
198 | let document = editor.document;
199 | if (!document) {
200 | hideStatusbarIfPossible();
201 | return;
202 | }
203 |
204 | let selection = editor.selection;
205 | if (!selection) {
206 | hideStatusbarIfPossible();
207 | return;
208 | }
209 |
210 | let tabSize = this._getTabSize(editor.options);
211 | let selectedIndent = this._getSelectedIndentDepth(document, selection, tabSize);
212 | if(this._outerConf.show || this._outerConf.hover || this._innerConf.show || this._innerConf.hover) {
213 | let activeRanges = this._getActiveIndentRanges(document, selection, selectedIndent, tabSize);
214 | if(this._outerConf.show) {
215 | editor.setDecorations(this._outerConf.style, activeRanges.outer);
216 | }
217 | if(this._outerConf.hover && activeRanges.outer.length >= this._outerConf.hover) {
218 | this._buildHover(editor, tabSize, this._outerConf);
219 | } else if(this._outerConf.hoverProvider) {
220 | this._outerConf.hoverProvider.dispose();
221 | }
222 | if(this._innerConf.show) {
223 | editor.setDecorations(this._innerConf.style, activeRanges.inner);
224 | }
225 | if(this._innerConf.hover && activeRanges.inner.length >= this._innerConf.hover) {
226 | this._buildHover(editor, tabSize, this._innerConf);
227 | } else if(this._innerConf.hoverProvider) {
228 | this._innerConf.hoverProvider.dispose();
229 | }
230 | }
231 |
232 | if(this._statusBarItem){
233 | this._statusBarItem.text = this._currentLocale['statusText']
234 | .replace('{indent}', selectedIndent);
235 | this._statusBarItem.tooltip = this._currentLocale['statusTooltip']
236 | .replace('{indent}', selectedIndent);
237 | this._statusBarItem.show();
238 | }
239 | }
240 |
241 | _buildHover(editor: TextEditor, tabSize: number, conf: IndentConfiguration) {
242 | if (conf.hoverProvider) {
243 | conf.hoverProvider.dispose();
244 | }
245 | conf.hoverProvider = languages.registerHoverProvider(
246 | editor.document.languageId,
247 | {
248 | provideHover: (doc, position) => {
249 | return this._buildHoverprovider(position, editor, tabSize, conf);
250 | }
251 | }
252 | );
253 | }
254 |
255 | _buildHoverprovider(position: Position, editor: TextEditor,
256 | tabSize: number, conf: IndentConfiguration): Hover {
257 | let char = conf.indentPos
258 | if(position.character > char - 1
259 | && position.character < char + 1
260 | && position.line >= conf.firstLine
261 | && position.line <= conf.lastLine) {
262 | let str = this._buildHoverString(editor, tabSize, conf);
263 | let range;
264 | if (conf.hoverConf.highlight) {
265 | range = new Range(conf.firstLine, conf.indentPos,
266 | conf.lastLine, conf.indentPos)
267 | }
268 | if(str) {
269 | return {
270 | range: range,
271 | contents: [
272 | {
273 | language: editor.document.languageId,
274 | value: str
275 | }
276 | ]
277 | };
278 | }
279 | return null;
280 | }
281 | }
282 |
283 | _buildHoverString(editor: TextEditor, tabSize: number,
284 | conf: IndentConfiguration): string {
285 | let hoverLines = [];
286 | let document = editor.document;
287 | let refDepth = this._getLinesIndentDepth(
288 | document.lineAt(conf.firstLine), tabSize);
289 |
290 | let backHoverLines = this._peekBack(editor.document, tabSize, refDepth, conf);
291 | let forwardHoverLines = this._peekForward(editor.document, tabSize, refDepth, conf);
292 |
293 | hoverLines.push(...backHoverLines);
294 | if(forwardHoverLines.length > 0 || backHoverLines.length > 0) {
295 | hoverLines.push(this._buildHoverPlaceholder(editor, tabSize, conf));
296 | }
297 | hoverLines.push(...forwardHoverLines);
298 | return hoverLines.join('\n');
299 | }
300 |
301 | _buildHoverPlaceholder(editor: TextEditor, tabSize: number,
302 | conf: IndentConfiguration): string {
303 | let tabChar = editor.options.insertSpaces?' ':'\t';
304 | let spacing = tabChar.repeat(tabSize);
305 | return `${spacing}${conf.hoverConf.peekBlockPlaceholder}`;
306 | }
307 |
308 | _peekBack(document: TextDocument, tabSize: number,
309 | refDepth: number, conf: IndentConfiguration): Array {
310 | let backHoverLines = [];
311 | if(conf && conf.hoverConf && conf.hoverConf.peekBack > 0) {
312 | let firstPeekLine = Math.max(
313 | conf.firstLine - (conf.hoverConf.peekBack - 1), 0);
314 | let pushedOnce = false;
315 | for(let i = firstPeekLine; i <= conf.firstLine; i++) {
316 | let line = document.lineAt(i)
317 | let lineStr = line.text.trim();
318 | if(!pushedOnce &&
319 | lineStr.length < conf.hoverConf.trimLinesShorterThan) {
320 | continue;
321 | }
322 | let lineDepth = this._getLinesIndentDepth(line, tabSize);
323 | if(lineDepth != refDepth) {
324 | backHoverLines.splice(0);
325 | continue;
326 | }
327 | backHoverLines.push(lineStr);
328 | pushedOnce = true;
329 | }
330 | }
331 | return backHoverLines;
332 | }
333 |
334 | _peekForward(document: TextDocument, tabSize: number,
335 | refDepth: number, conf: IndentConfiguration): Array {
336 | let forwardHoverLines = [];
337 | if(conf && conf.hoverConf && conf.hoverConf.peekForward > 0) {
338 | let lastPeekLine = Math.min(
339 | conf.lastLine + (conf.hoverConf.peekForward - 1),
340 | document.lineCount - 1);
341 | let pushedOnce = false;
342 | for(let i = lastPeekLine; i >= conf.lastLine; i--) {
343 | let line = document.lineAt(i)
344 | let lineStr = line.text.trim();
345 | if(!pushedOnce &&
346 | lineStr.length < conf.hoverConf.trimLinesShorterThan) {
347 | continue;
348 | }
349 | let lineDepth = this._getLinesIndentDepth(line, tabSize);
350 | if(lineDepth != refDepth) {
351 | forwardHoverLines.splice(0);
352 | continue;
353 | }
354 | forwardHoverLines.push(lineStr);
355 | pushedOnce = true;
356 | }
357 | }
358 | return forwardHoverLines.reverse();
359 | }
360 |
361 | _clearDecorators() {
362 | if(this._outerConf.style) {
363 | for(let i = 0; i < window.visibleTextEditors.length; i++) {
364 | window.visibleTextEditors[i].setDecorations(
365 | this._outerConf.style, []);
366 | }
367 |
368 | }
369 | if(this._innerConf.style) {
370 | for(let i = 0; i < window.visibleTextEditors.length; i++) {
371 | window.visibleTextEditors[i].setDecorations(
372 | this._innerConf.style, []);
373 | }
374 |
375 | }
376 | }
377 |
378 | _getTabSize(options: TextEditorOptions) {
379 | return options.insertSpaces?Number(options.tabSize):1;
380 | }
381 |
382 | _getIndentDepth(index: number, tabSize: number) {
383 | return Math.ceil(index / tabSize);
384 | }
385 |
386 | _getLinesIndentDepth(line: TextLine, tabSize: number) {
387 | return this._getIndentDepth(line.firstNonWhitespaceCharacterIndex,
388 | tabSize);
389 | }
390 |
391 | _createIndicatorRange(line: number, character: number) {
392 | return new Range(new Position(line, character),
393 | new Position(line, character));
394 | }
395 |
396 | _getSelectedIndentDepth(document: TextDocument, selection: Selection,
397 | tabSize: number) {
398 | if(selection.isSingleLine) {
399 | let maxlineNum = document.lineCount - 1;
400 | let line = document.lineAt(Math.min(selection.start.line, maxlineNum));
401 | return this._getIndentDepth(
402 | Math.min(selection.start.character,
403 | line.firstNonWhitespaceCharacterIndex),
404 | tabSize);
405 | }
406 | let selectedIndent = Number.MAX_VALUE;
407 | let maxlineNum = Math.min(selection.end.line,document.lineCount - 1);
408 | for(let i = selection.start.line; i <= maxlineNum; i++) {
409 | let line = document.lineAt(i);
410 | if(line.isEmptyOrWhitespace) {
411 | continue;
412 | }
413 | selectedIndent = Math.min(selectedIndent,
414 | this._getLinesIndentDepth(line, tabSize));
415 | }
416 | return selectedIndent;
417 | }
418 |
419 | _getActiveIndentRanges(document: TextDocument, selection: Selection,
420 | selectedIndent: number, tabSize: number){
421 | let activeRanges = [];
422 | let activeInnerRanges = [];
423 | let line: TextLine;
424 | let innerDeactivated: boolean;
425 |
426 | this._outerConf.firstLine = selection.start.line;
427 | this._outerConf.lastLine = selection.end.line;
428 | this._outerConf.indentPos = (selectedIndent - 1) * tabSize;
429 |
430 | this._innerConf.firstLine = selection.start.line;
431 | this._innerConf.lastLine = selection.end.line;
432 | this._innerConf.indentPos = selectedIndent * tabSize;
433 |
434 | let addRanges = (i: number, line: TextLine) => {
435 | let lineAdded = false;
436 | let innerAdded = false;
437 | let lineIndent = this._getLinesIndentDepth(line, tabSize);
438 | if(!innerDeactivated && (
439 | lineIndent > selectedIndent || (
440 | line.isEmptyOrWhitespace && selectedIndent === lineIndent &&
441 | (i !== selection.end.line || selection.end.character !== this._innerConf.indentPos)))) {
442 | activeInnerRanges.push(
443 | this._createIndicatorRange(i, this._innerConf.indentPos));
444 | lineAdded = true;
445 | innerAdded = true;
446 | }
447 | if(this._outerConf.indentPos >= 0 && (
448 | lineIndent >= selectedIndent || (
449 | line.isEmptyOrWhitespace && selectedIndent === 1))) {
450 | activeRanges.push(this._createIndicatorRange(i, this._outerConf.indentPos));
451 | lineAdded = true;
452 | }
453 | return {
454 | 'lineAdded': lineAdded,
455 | 'innerAdded': innerAdded
456 | };
457 | };
458 |
459 | // add ranges for preceeding lines on same indent
460 | innerDeactivated = false;
461 | for(let i = selection.start.line; i >= 0; i--) {
462 | line = document.lineAt(i);
463 | let result = addRanges(i, line)
464 | if(!result.innerAdded && !line.isEmptyOrWhitespace && !innerDeactivated) {
465 | innerDeactivated = true;
466 | this._innerConf.firstLine = i;
467 | }
468 | if(!result.lineAdded && !line.isEmptyOrWhitespace) {
469 | this._outerConf.firstLine = i;
470 | break;
471 | }
472 | }
473 | // add ranges for following lines on same indent
474 | innerDeactivated = false;
475 | for(let i = selection.start.line + 1; i < document.lineCount; i++) {
476 | line = document.lineAt(i);
477 | let result = addRanges(i, line)
478 | if(!result.innerAdded && !line.isEmptyOrWhitespace && !innerDeactivated) {
479 | innerDeactivated = true;
480 | this._innerConf.lastLine = i;
481 | }
482 | if(!result.lineAdded && !line.isEmptyOrWhitespace) {
483 | this._outerConf.lastLine = i;
484 | break;
485 | }
486 | }
487 | return {
488 | outer: activeRanges,
489 | inner: activeInnerRanges
490 | };
491 | }
492 |
493 | dispose() {
494 | if(this._statusBarItem){
495 | this._statusBarItem.dispose();
496 | }
497 | if(this._outerConf.hoverProvider) {
498 | this._outerConf.hoverProvider.dispose();
499 | }
500 | if (this._innerConf.hoverProvider) {
501 | this._innerConf.hoverProvider.dispose();
502 | }
503 | }
504 | }
505 |
506 | class IndentSpyController {
507 |
508 | private _indentSpy: IndentSpy;
509 | private _disposable: Disposable;
510 |
511 | constructor(indentSpy: IndentSpy) {
512 | this._indentSpy = indentSpy;
513 | this._indentSpy.updateCurrentIndent();
514 |
515 | // subscribe to selection change and editor activation events
516 | let subscriptions: Disposable[] = [];
517 | window.onDidChangeTextEditorSelection(
518 | this._onUpdateEvent, this, subscriptions);
519 | window.onDidChangeActiveTextEditor(
520 | this._onChangedEditor, this, subscriptions);
521 |
522 | // subscribe to configuration change events
523 | workspace.onDidChangeConfiguration(
524 | this._onChangedConfigEvent, this, subscriptions);
525 |
526 | this._disposable = Disposable.from(...subscriptions);
527 | }
528 |
529 | dispose() {
530 | this._disposable.dispose();
531 | }
532 |
533 | private _onUpdateEvent(e) {
534 | this._indentSpy.updateCurrentIndent();
535 | }
536 |
537 | private _onChangedEditor(e) {
538 | this._indentSpy.updateConfig();
539 | this._indentSpy.updateCurrentIndent();
540 | }
541 |
542 | private _onChangedConfigEvent(e) {
543 | this._indentSpy.updateConfig();
544 | }
545 | }
--------------------------------------------------------------------------------
/test-fixtures/demo/demo.ts:
--------------------------------------------------------------------------------
1 | class Foobar {
2 | constructor() {
3 | let iterations = Math.floor(Math.random() * 100);
4 | for(let i = 0; i < iterations; i++) {
5 | if(i % 3) {
6 | this.foo();
7 | /*
8 | Lorem ipsum dolor sit amet,
9 | consetetur sadipscing elitr,
10 | sed diam nonumy eirmod tempor
11 | invidunt ut labore et dolore
12 | magna aliquyam erat...
13 | */
14 | } else if(i % 2) {
15 | this.bar();
16 | }
17 | }
18 | }
19 |
20 | foo() {
21 | //do something
22 | }
23 |
24 | bar() {
25 | // do something else
26 | }
27 | }
--------------------------------------------------------------------------------
/test/runTest.ts:
--------------------------------------------------------------------------------
1 | import * as path from "path";
2 | import { runTests } from 'vscode-test';
3 |
4 | async function go() {
5 | try {
6 |
7 | const extensionDevelopmentPath = path.resolve(__dirname, '../../')
8 | const extensionTestsPath = path.resolve(__dirname, './suite')
9 | const testWorkspace = path.resolve(__dirname, '../../test-fixtures')
10 | runTests({
11 | extensionDevelopmentPath,
12 | extensionTestsPath: extensionTestsPath,
13 | launchArgs: [testWorkspace]
14 | });
15 | } catch (err) {
16 | console.error('Failed to run tests');
17 | process.exit(1);
18 | }
19 | }
20 |
21 | go();
--------------------------------------------------------------------------------
/test/suite/extension.test.ts:
--------------------------------------------------------------------------------
1 | //
2 | // Note: This example test is leveraging the Mocha test framework.
3 | // Please refer to their documentation on https://mochajs.org/ for help.
4 | //
5 |
6 | // The module 'assert' provides assertion methods from node
7 | import * as assert from 'assert';
8 | import * as path from "path";
9 |
10 | // You can import and use all API from the 'vscode' module
11 | // as well as import your extension to test it
12 | import * as vscode from 'vscode';
13 | import * as myExtension from '../../src/extension';
14 |
15 | let fs = require('fs');
16 |
17 |
18 | let setEditorContent = (editor: vscode.TextEditor, text: string) => {
19 | return editor.edit((e) => {
20 | e.delete(editor.document.validateRange(
21 | new vscode.Range(0, 0, Number.MAX_VALUE, Number.MAX_VALUE)));
22 | e.insert(new vscode.Position(0,0), text);
23 | });
24 | };
25 |
26 |
27 | suite("Extension Tests", () => {
28 | let tmpFilePath = path.resolve(__dirname) + "/tmp.txt";
29 | let document : vscode.TextDocument;
30 |
31 | suiteSetup(() => {
32 | fs.writeFileSync(tmpFilePath, "foo");
33 | return vscode.workspace.openTextDocument(tmpFilePath).then(
34 | (doc) => document = doc
35 | );
36 | });
37 |
38 | suiteSetup(() => {
39 | return vscode.window.showTextDocument(document);
40 | });
41 |
42 | suiteTeardown(() => {
43 | let fileStatus = fs.statSync(tmpFilePath);
44 | if(fileStatus.isFile()) {
45 | fs.unlinkSync(tmpFilePath);
46 | }
47 | });
48 |
49 | // Defines a Mocha unit test
50 | suite("IndentSpy", () => {
51 | let IndentSpy : myExtension.IndentSpy;
52 |
53 | setup(() => {
54 | IndentSpy = new myExtension.IndentSpy();
55 | });
56 |
57 | suite("_getTabSize", () => {
58 | let options;
59 | let initialValues;
60 |
61 | setup(() => {
62 | options = vscode.window.activeTextEditor.options;
63 | initialValues = {
64 | insertSpaces: options.insertSpaces,
65 | tabSize: options.tabSize
66 | };
67 | });
68 |
69 | teardown(() => {
70 | options.insertSpaces = initialValues.insertSpaces;
71 | options.tabSize = initialValues.tabSize;
72 | })
73 |
74 | test("returns 1 if insertSpaces option is false", () => {
75 | options.insertSpaces = false;
76 | options.tabSize = 5;
77 |
78 | let result = IndentSpy._getTabSize(options);
79 |
80 | assert.strictEqual(result, 1);
81 | });
82 |
83 | test("returns tabSize if insertSpaces option is true", () => {
84 | options.insertSpaces = true;
85 | options.tabSize = 5;
86 |
87 | let result = IndentSpy._getTabSize(options);
88 |
89 | assert.strictEqual(result, 5);
90 | });
91 | });
92 |
93 | suite("_getIndentDepth", () => {
94 |
95 | test("returns the quotient of given parameters", () => {
96 | let index = 12, tabSize = 3;
97 |
98 | let result = IndentSpy._getIndentDepth(index, tabSize);
99 |
100 | assert.strictEqual(result, 4);
101 | });
102 |
103 | test("always rounds up", () => {
104 | let index = 11, tabSize = 5;
105 |
106 | let result = IndentSpy._getIndentDepth(index, tabSize);
107 |
108 | assert.strictEqual(result, 3);
109 | });
110 | });
111 |
112 | suite("_getLinesIndentDepth", () => {
113 |
114 | let editor : vscode.TextEditor;
115 |
116 | suiteSetup(() => {
117 | editor = vscode.window.activeTextEditor;
118 | return setEditorContent(editor, " test");
119 | });
120 |
121 | test("returns the quotient of given leading whitespace" +
122 | " chararcters and tabSize", () => {
123 |
124 | let line = editor.document.lineAt(0);
125 | let tabSize = 3;
126 |
127 | let result = IndentSpy._getLinesIndentDepth(
128 | line, tabSize);
129 |
130 | assert.strictEqual(result, 4);
131 | });
132 |
133 | test("always rounds up", () => {
134 | let line = editor.document.lineAt(0);
135 | let tabSize = 5;
136 |
137 | let result = IndentSpy._getLinesIndentDepth(line, tabSize);
138 |
139 | assert.strictEqual(result, 3);
140 | });
141 | });
142 |
143 | suite("_createIndicatorRange", () => {
144 | test("creates Range object with start equal to start", () => {
145 | let result = IndentSpy._createIndicatorRange(3, 4);
146 | assert.strictEqual(result.start.line, 3);
147 | assert.strictEqual(result.start.line, result.end.line);
148 | assert.strictEqual(result.start.character, 4);
149 | assert.strictEqual(result.start.character, result.end.character);
150 | });
151 | });
152 |
153 | suite("_getSelectedIndentDepth", () => {
154 | let document : vscode.TextDocument, tabSize;
155 |
156 | suiteSetup(() => {
157 | // set tabSize to 2 with whitespaces
158 | vscode.window.activeTextEditor.options.insertSpaces = true;
159 | vscode.window.activeTextEditor.options.tabSize = 2;
160 | tabSize = IndentSpy._getTabSize(
161 | vscode.window.activeTextEditor.options);
162 |
163 | // build stub for TextDocument:
164 | let editor = vscode.window.activeTextEditor;
165 | document = editor.document;
166 | return setEditorContent(editor,
167 | "() => {\n" +
168 | " if(foo()) {\n" +
169 | " bar();\n" +
170 | " return;\n" +
171 | " }\n" +
172 | "}\n"
173 | );
174 | });
175 |
176 | test("returns indent depth of selection start if single line" +
177 | " selected and start before first nonwhitespace character",
178 | () => {
179 | let selection = new vscode.Selection(2, 1, 2, 2);
180 |
181 | let result = IndentSpy._getSelectedIndentDepth(
182 | document, selection, tabSize);
183 |
184 | assert.strictEqual(result, 1);
185 | }
186 | );
187 |
188 | test("returns indent depth of first nonwhitespace character if" +
189 | " single line and selections starts after first" +
190 | " nonwhitespace character",
191 | () => {
192 | let selection = new vscode.Selection(2, 6, 2, 7);
193 |
194 | let result = IndentSpy._getSelectedIndentDepth(
195 | document, selection, tabSize);
196 |
197 | assert.strictEqual(result, 2);
198 | }
199 | );
200 |
201 | test("returns lowest indent depth of the first nonwhitespace" +
202 | " character of any selected line if multiple are selected" ,
203 | () => {
204 | let selection = new vscode.Selection(1, 0, 2, 0);
205 |
206 | let result = IndentSpy._getSelectedIndentDepth(
207 | document, selection, tabSize);
208 |
209 | assert.strictEqual(result, 1);
210 | }
211 | );
212 | });
213 |
214 | suite("_getActiveIndentRanges", () => {
215 | let document : vscode.TextDocument, tabSize;
216 |
217 | let findRangePredicate = (expected) => {
218 | return (value, idx, obj) => {
219 | return (
220 | value.start.line === expected.start.line &&
221 | value.start.character == expected.start.character
222 | );
223 | }
224 | }
225 |
226 | suiteSetup(() => {
227 | // set tabSize to 2 with whitespaces
228 | vscode.window.activeTextEditor.options.insertSpaces = true;
229 | vscode.window.activeTextEditor.options.tabSize = 2;
230 | tabSize = IndentSpy._getTabSize(
231 | vscode.window.activeTextEditor.options);
232 |
233 | let editor = vscode.window.activeTextEditor;
234 | document = editor.document;
235 | return setEditorContent(editor,
236 | "() => {\n" +
237 | " if(foo()) {\n" +
238 | " bar();\n" +
239 | " bar();\n" +
240 | " return;\n" +
241 | " } else {\n" +
242 | " foo();\n" +
243 | " }\n" +
244 | "}\n"
245 | );
246 | });
247 |
248 | test("returns a set of ranges for all lines enclosing the" +
249 | " selection with the same or higher indent as outer" +
250 | " and following line higher indent as inner" +
251 | " and updates configs first/last line and indentPos",
252 | () => {
253 | IndentSpy._innerConf.show = true;
254 | let selection = new vscode.Selection(5, 9, 5, 9);
255 | let selectedIndent = 1;
256 | let result = IndentSpy._getActiveIndentRanges(
257 | document, selection, selectedIndent, tabSize);
258 |
259 | let expectedRanges = [
260 | IndentSpy._createIndicatorRange(1, 0),
261 | IndentSpy._createIndicatorRange(2, 0),
262 | IndentSpy._createIndicatorRange(3, 0),
263 | IndentSpy._createIndicatorRange(4, 0),
264 | IndentSpy._createIndicatorRange(5, 0),
265 | IndentSpy._createIndicatorRange(6, 0),
266 | IndentSpy._createIndicatorRange(7, 0),
267 | ];
268 | let expectedInnerRanges = [
269 | IndentSpy._createIndicatorRange(6, tabSize),
270 | ];
271 |
272 | assert.strictEqual(IndentSpy._innerConf.firstLine, 5);
273 | assert.strictEqual(IndentSpy._innerConf.lastLine, 7);
274 | assert.strictEqual(IndentSpy._innerConf.indentPos, tabSize);
275 |
276 | assert.strictEqual(IndentSpy._outerConf.firstLine, 0);
277 | assert.strictEqual(IndentSpy._outerConf.lastLine, 8);
278 | assert.strictEqual(IndentSpy._outerConf.indentPos, 0);
279 |
280 | assert.strictEqual(result.outer.length, expectedRanges.length);
281 | assert.strictEqual(result.inner.length, expectedInnerRanges.length);
282 | for(let i = 0; i < expectedRanges.length; i++) {
283 | assert(result.outer.find(findRangePredicate(expectedRanges[i])),
284 | `(${expectedRanges[i].start.line}, ${expectedRanges[i].start.character})`);
285 | }
286 | for(let i = 0; i < expectedInnerRanges.length; i++) {
287 | assert(result.inner.find(findRangePredicate(expectedInnerRanges[i])),
288 | `(${expectedInnerRanges[i].start.line}, ${expectedInnerRanges[i].start.character})`);
289 | }
290 | }
291 | );
292 |
293 | test("returns a set of ranges for all lines enclosing the" +
294 | " selection with the same or higher indent stopping at lower" +
295 | " indets as outer",
296 | () => {
297 | IndentSpy._innerConf.show = true;
298 | let selection = new vscode.Selection(3, 6, 3, 6);
299 | let selectedIndent = 2;
300 | let result = IndentSpy._getActiveIndentRanges(
301 | document, selection, selectedIndent, tabSize);
302 |
303 | let expectedRanges = [
304 | IndentSpy._createIndicatorRange(2, tabSize),
305 | IndentSpy._createIndicatorRange(3, tabSize),
306 | IndentSpy._createIndicatorRange(4, tabSize),
307 | ];
308 |
309 | assert.strictEqual(IndentSpy._outerConf.firstLine, 1);
310 | assert.strictEqual(IndentSpy._outerConf.lastLine, 5);
311 | assert.strictEqual(IndentSpy._outerConf.indentPos, 2);
312 |
313 | assert.strictEqual(result.outer.length, expectedRanges.length);
314 | assert.strictEqual(result.inner.length, 0);
315 |
316 | for(let i = 0; i < expectedRanges.length; i++) {
317 | assert(result.outer.find(findRangePredicate(expectedRanges[i])),
318 | `(${expectedRanges[i].start.line}, ${expectedRanges[i].start.character}) not in generated ranges`);
319 | }
320 | }
321 | );
322 |
323 | test("returns a set of ranges for all lines enclosing the" +
324 | " selection with the same or higher indent as outer" +
325 | " and the same ident as inner stopping on lower indent",
326 | () => {
327 | IndentSpy._innerConf.show = true;
328 | let selection = new vscode.Selection(3, 2, 3, 2);
329 | let selectedIndent = 1;
330 | let result = IndentSpy._getActiveIndentRanges(
331 | document, selection, selectedIndent, tabSize);
332 |
333 | let expectedRanges = [
334 | IndentSpy._createIndicatorRange(1, 0),
335 | IndentSpy._createIndicatorRange(2, 0),
336 | IndentSpy._createIndicatorRange(3, 0),
337 | IndentSpy._createIndicatorRange(4, 0),
338 | IndentSpy._createIndicatorRange(5, 0),
339 | IndentSpy._createIndicatorRange(6, 0),
340 | IndentSpy._createIndicatorRange(7, 0)
341 | ];
342 | let expectedInnerRanges = [
343 | IndentSpy._createIndicatorRange(2, tabSize),
344 | IndentSpy._createIndicatorRange(3, tabSize),
345 | IndentSpy._createIndicatorRange(4, tabSize),
346 | ];
347 |
348 | assert.strictEqual(IndentSpy._innerConf.firstLine, 1);
349 | assert.strictEqual(IndentSpy._innerConf.lastLine, 5);
350 | assert.strictEqual(IndentSpy._innerConf.indentPos, tabSize);
351 |
352 | assert.strictEqual(IndentSpy._outerConf.firstLine, 0);
353 | assert.strictEqual(IndentSpy._outerConf.lastLine, 8);
354 | assert.strictEqual(IndentSpy._outerConf.indentPos, 0);
355 |
356 | assert.strictEqual(result.outer.length, expectedRanges.length);
357 | assert.strictEqual(result.inner.length, expectedInnerRanges.length);
358 | for(let i = 0; i < expectedRanges.length; i++) {
359 | assert(result.outer.find(findRangePredicate(expectedRanges[i])),
360 | `(${expectedRanges[i].start.line}, ${expectedRanges[i].start.character})`);
361 | }
362 | for(let i = 0; i < expectedInnerRanges.length; i++) {
363 | assert(result.inner.find(findRangePredicate(expectedInnerRanges[i])),
364 | `(${expectedInnerRanges[i].start.line}, ${expectedInnerRanges[i].start.character})`);
365 | }
366 | }
367 | );
368 |
369 | test("does return a set of ranges for inner even if disabled" +
370 | " to enable peeking",
371 | () => {
372 | IndentSpy._innerConf.show = false;
373 | IndentSpy._outerConf.show = true;
374 | let selection = new vscode.Selection(3, 2, 3, 2);
375 | let selectedIndent = 1;
376 | let result = IndentSpy._getActiveIndentRanges(
377 | document, selection, selectedIndent, tabSize);
378 |
379 | let expectedRanges = [
380 | IndentSpy._createIndicatorRange(1, 0),
381 | IndentSpy._createIndicatorRange(2, 0),
382 | IndentSpy._createIndicatorRange(3, 0),
383 | IndentSpy._createIndicatorRange(4, 0),
384 | IndentSpy._createIndicatorRange(5, 0),
385 | IndentSpy._createIndicatorRange(6, 0),
386 | IndentSpy._createIndicatorRange(7, 0)
387 | ];
388 | let expectedInnerRanges = [
389 | IndentSpy._createIndicatorRange(2, tabSize),
390 | IndentSpy._createIndicatorRange(3, tabSize),
391 | IndentSpy._createIndicatorRange(4, tabSize),];
392 |
393 | assert.strictEqual(IndentSpy._outerConf.firstLine, 0);
394 | assert.strictEqual(IndentSpy._outerConf.lastLine, 8);
395 | assert.strictEqual(IndentSpy._outerConf.indentPos, 0);
396 |
397 | assert.strictEqual(result.outer.length, expectedRanges.length);
398 | assert.strictEqual(result.inner.length, expectedInnerRanges.length);
399 | for(let i = 0; i < expectedRanges.length; i++) {
400 | assert(result.outer.find(findRangePredicate(expectedRanges[i])),
401 | `(${expectedRanges[i].start.line}, ${expectedRanges[i].start.character})`);
402 | }
403 | }
404 | );
405 |
406 | test("does return a set of ranges for outer even if disabled" +
407 | " to enable peeking",
408 | () => {
409 | IndentSpy._innerConf.show = true;
410 | IndentSpy._outerConf.show = false;
411 | let selection = new vscode.Selection(3, 2, 3, 2);
412 | let selectedIndent = 1;
413 | let result = IndentSpy._getActiveIndentRanges(
414 | document, selection, selectedIndent, tabSize);
415 |
416 | let expectedRanges = [
417 | IndentSpy._createIndicatorRange(1, 0),
418 | IndentSpy._createIndicatorRange(2, 0),
419 | IndentSpy._createIndicatorRange(3, 0),
420 | IndentSpy._createIndicatorRange(4, 0),
421 | IndentSpy._createIndicatorRange(5, 0),
422 | IndentSpy._createIndicatorRange(6, 0),
423 | IndentSpy._createIndicatorRange(7, 0)
424 | ];
425 | let expectedInnerRanges = [
426 | IndentSpy._createIndicatorRange(2, tabSize),
427 | IndentSpy._createIndicatorRange(3, tabSize),
428 | IndentSpy._createIndicatorRange(4, tabSize),
429 | ];
430 |
431 | assert.strictEqual(IndentSpy._innerConf.firstLine, 1);
432 | assert.strictEqual(IndentSpy._innerConf.lastLine, 5);
433 | assert.strictEqual(IndentSpy._innerConf.indentPos, tabSize);
434 |
435 | assert.strictEqual(result.outer.length, expectedRanges.length);
436 | assert.strictEqual(result.inner.length, expectedInnerRanges.length);
437 | for(let i = 0; i < expectedInnerRanges.length; i++) {
438 | assert(result.inner.find(findRangePredicate(expectedInnerRanges[i])),
439 | `(${expectedInnerRanges[i].start.line}, ${expectedInnerRanges[i].start.character})`);
440 | }
441 | }
442 | );
443 |
444 | test("does return all ranges evem if both disabled",
445 | () => {
446 | IndentSpy._innerConf.show = false;
447 | IndentSpy._outerConf.show = false;
448 | let selection = new vscode.Selection(3, 2, 3, 2);
449 | let selectedIndent = 1;
450 | let result = IndentSpy._getActiveIndentRanges(
451 | document, selection, selectedIndent, tabSize);
452 |
453 | let expectedRanges = [
454 | IndentSpy._createIndicatorRange(1, 0),
455 | IndentSpy._createIndicatorRange(2, 0),
456 | IndentSpy._createIndicatorRange(3, 0),
457 | IndentSpy._createIndicatorRange(4, 0),
458 | IndentSpy._createIndicatorRange(5, 0),
459 | IndentSpy._createIndicatorRange(6, 0),
460 | IndentSpy._createIndicatorRange(7, 0)
461 | ];
462 | let expectedInnerRanges = [
463 | IndentSpy._createIndicatorRange(2, tabSize),
464 | IndentSpy._createIndicatorRange(3, tabSize),
465 | IndentSpy._createIndicatorRange(4, tabSize),
466 | ];
467 |
468 | assert.strictEqual(result.outer.length, expectedRanges.length);
469 | assert.strictEqual(result.inner.length, expectedInnerRanges.length);
470 | }
471 | );
472 | });
473 |
474 | suite("_peekBack", () => {
475 | let editor : vscode.TextEditor, tabSize;
476 |
477 | suiteSetup(() => {
478 | // set tabSize to 2 with whitespaces
479 | vscode.window.activeTextEditor.options.insertSpaces = true;
480 | vscode.window.activeTextEditor.options.tabSize = 2;
481 | tabSize = IndentSpy._getTabSize(
482 | vscode.window.activeTextEditor.options);
483 |
484 | editor = vscode.window.activeTextEditor;
485 | return setEditorContent(editor,
486 | "() => {\n" +
487 | " //foo?\n" +
488 | " //\n" +
489 | " foo();\n" +
490 | " if(foo()) {\n" +
491 | " bar();\n" +
492 | " return;\n" +
493 | " } else {\n" +
494 | " foo();\n" +
495 | " }\n" +
496 | "}\n"
497 | );
498 | });
499 |
500 | setup(() => {
501 | IndentSpy._outerConf.hoverConf = {
502 | highlight: true,
503 | peekBack: 3,
504 | peekForward: 0,
505 | trimLinesShorterThan: 2,
506 | peekBlockPlaceholder: '...'
507 | };
508 | IndentSpy._outerConf.firstLine = 4;
509 | IndentSpy._outerConf.lastLine = 7;
510 | IndentSpy._outerConf.indentPos = 4;
511 | })
512 |
513 | test("returns empty list if peekBack is lower than 1",
514 | () => {
515 | IndentSpy._outerConf.hoverConf.peekBack = -1;
516 | let lines = IndentSpy._peekBack(editor.document, 2, 1, IndentSpy._outerConf);
517 | assert.strictEqual(lines.length, 0);
518 | });
519 | test("reutrns a list containing the configured number of" +
520 | " lines from before the currently active indent block and" +
521 | " trims their leading whitespace characters",
522 | () => {
523 | let lines = IndentSpy._peekBack(editor.document, 2, 1, IndentSpy._outerConf);
524 | assert.strictEqual(lines.length, 3);
525 | assert.strictEqual(lines[0], "//");
526 | assert.strictEqual(lines[1], "foo();");
527 | assert.strictEqual(lines[2], "if(foo()) {");
528 | });
529 | test("peeks at maximum the confgiured number of lines",
530 | () => {
531 | IndentSpy._outerConf.hoverConf.peekBack = 1;
532 | let lines = IndentSpy._peekBack(editor.document, 2, 1, IndentSpy._outerConf);
533 | assert.strictEqual(lines.length, 1);
534 | assert.strictEqual(lines[0], "if(foo()) {");
535 | });
536 | test("stops at changing indent depth",
537 | () => {
538 | IndentSpy._outerConf.hoverConf.peekBack = 5;
539 | let lines = IndentSpy._peekBack(editor.document, 2, 1, IndentSpy._outerConf);
540 | assert.strictEqual(lines.length, 4);
541 | assert.strictEqual(lines[0], "//foo?");
542 | assert.strictEqual(lines[1], "//");
543 | assert.strictEqual(lines[2], "foo();");
544 | assert.strictEqual(lines[3], "if(foo()) {");
545 | });
546 | test("trims lines shorter than configured value",
547 | () => {
548 | IndentSpy._outerConf.hoverConf.trimLinesShorterThan = 3;
549 | let lines = IndentSpy._peekBack(editor.document, 2, 1, IndentSpy._outerConf);
550 | assert.strictEqual(lines.length, 2);
551 | assert.strictEqual(lines[0], "foo();");
552 | assert.strictEqual(lines[1], "if(foo()) {");
553 | });
554 | test("doesn't trim lines shorter than configured value if" +
555 | " another before line is already peeked",
556 | () => {
557 | IndentSpy._outerConf.hoverConf.peekBack = 4;
558 | IndentSpy._outerConf.hoverConf.trimLinesShorterThan = 4;
559 | let lines = IndentSpy._peekBack(editor.document, 2, 1, IndentSpy._outerConf);
560 | assert.strictEqual(lines.length, 4);
561 | assert.strictEqual(lines[0], "//foo?");
562 | assert.strictEqual(lines[1], "//");
563 | assert.strictEqual(lines[2], "foo();");
564 | assert.strictEqual(lines[3], "if(foo()) {");
565 | });
566 | test("includes first line of file (issue #6)",
567 | () => {
568 | IndentSpy._outerConf.hoverConf.peekBack = 1;
569 | IndentSpy._outerConf.firstLine = 0;
570 | let lines = IndentSpy._peekBack(editor.document, 2, 0, IndentSpy._outerConf);
571 | assert.strictEqual(lines.length, 1);
572 | assert.strictEqual(lines[0], "() => {");
573 | });
574 | });
575 |
576 | suite("_peekForward", () => {
577 | let editor : vscode.TextEditor, tabSize;
578 |
579 | suiteSetup(() => {
580 | // set tabSize to 2 with whitespaces
581 | vscode.window.activeTextEditor.options.insertSpaces = true;
582 | vscode.window.activeTextEditor.options.tabSize = 2;
583 | tabSize = IndentSpy._getTabSize(
584 | vscode.window.activeTextEditor.options);
585 |
586 | editor = vscode.window.activeTextEditor;
587 | return setEditorContent(editor,
588 | "() => {\n" +
589 | " if(foo()) {\n" +
590 | " bar();\n" +
591 | " return;\n" +
592 | " }\n" +
593 | " //foo?\n" +
594 | " //\n" +
595 | " foo();\n" +
596 | "}\n"
597 | );
598 | });
599 |
600 | setup(() => {
601 | IndentSpy._outerConf.hoverConf = {
602 | highlight: true,
603 | peekBack: 0,
604 | peekForward: 3,
605 | trimLinesShorterThan: 2,
606 | peekBlockPlaceholder: '...'
607 | };
608 | IndentSpy._outerConf.firstLine = 1;
609 | IndentSpy._outerConf.lastLine = 4;
610 | IndentSpy._outerConf.indentPos = 4
611 | })
612 |
613 | test("returns empty list if peekForward is lower than 1",
614 | () => {
615 | IndentSpy._outerConf.hoverConf.peekForward = -1;
616 | let lines = IndentSpy._peekForward(editor.document, 2, 1, IndentSpy._outerConf);
617 | assert.strictEqual(lines.length, 0);
618 | });
619 | test("reutrns a list containing the configured number of" +
620 | " lines from after the currently active indent block in " +
621 | " reverse order and trims their leading whitespace characters",
622 | () => {
623 | let lines = IndentSpy._peekForward(editor.document, 2, 1, IndentSpy._outerConf);
624 | assert.strictEqual(lines.length, 3);
625 | assert.strictEqual(lines[0], "}");
626 | assert.strictEqual(lines[1], "//foo?");
627 | assert.strictEqual(lines[2], "//");
628 | });
629 | test("peeks at maximum the confgiured number of lines",
630 | () => {
631 | IndentSpy._outerConf.hoverConf.peekForward = 2;
632 | let lines = IndentSpy._peekForward(editor.document, 2, 1, IndentSpy._outerConf);
633 | assert.strictEqual(lines.length, 2);
634 | assert.strictEqual(lines[0], "}");
635 | assert.strictEqual(lines[1], "//foo?");
636 | });
637 | test("stops at changing indent depth",
638 | () => {
639 | IndentSpy._outerConf.hoverConf.peekForward = 5;
640 | let lines = IndentSpy._peekForward(editor.document, 2, 1, IndentSpy._outerConf);
641 | assert.strictEqual(lines.length, 4);
642 | assert.strictEqual(lines[0], "}");
643 | assert.strictEqual(lines[1], "//foo?");
644 | assert.strictEqual(lines[2], "//");
645 | assert.strictEqual(lines[3], "foo();");
646 | });
647 | test("trims lines shorter than configured value",
648 | () => {
649 | IndentSpy._outerConf.hoverConf.trimLinesShorterThan = 3;
650 | let lines = IndentSpy._peekForward(editor.document, 2, 1, IndentSpy._outerConf);
651 | assert.strictEqual(lines.length, 2);
652 | assert.strictEqual(lines[0], "}");
653 | assert.strictEqual(lines[1], "//foo?");
654 | });
655 | test("doesn't trim lines shorter than configured value if" +
656 | " another before line is already peeked",
657 | () => {
658 | IndentSpy._outerConf.hoverConf.peekForward = 4;
659 | IndentSpy._outerConf.hoverConf.trimLinesShorterThan = 4;
660 | let lines = IndentSpy._peekForward(editor.document, 2, 1, IndentSpy._outerConf);
661 | assert.strictEqual(lines.length, 4);
662 | assert.strictEqual(lines[0], "}");
663 | assert.strictEqual(lines[1], "//foo?");
664 | assert.strictEqual(lines[2], "//");
665 | assert.strictEqual(lines[3], "foo();");
666 | });
667 | test("includes last line of file (issue #6)",
668 | () => {
669 | IndentSpy._outerConf.hoverConf.peekForward = 1;
670 | IndentSpy._outerConf.hoverConf.trimLinesShorterThan = 0;
671 | IndentSpy._outerConf.firstLine = 0;
672 | IndentSpy._outerConf.lastLine = 8;
673 | let lines = IndentSpy._peekForward(editor.document, 2, 0, IndentSpy._outerConf);
674 | assert.strictEqual(lines.length, 1);
675 | assert.strictEqual(lines[0], "}");
676 | });
677 | });
678 |
679 | suite("_buildHoverPlaceholder", () => {
680 | let editor : vscode.TextEditor, tabSize;
681 |
682 | suiteSetup(() => {
683 | editor = vscode.window.activeTextEditor;
684 | });
685 |
686 | setup(() => {
687 | IndentSpy._outerConf.hoverConf = {
688 | highlight: true,
689 | peekBack: 0,
690 | peekForward: 3,
691 | trimLinesShorterThan: 2,
692 | peekBlockPlaceholder: '...'
693 | };
694 | })
695 |
696 | test("returns string with configured peekBlockPlaceholder" +
697 | " with one indent placed before",() => {
698 | editor.options.insertSpaces = true;
699 | editor.options.tabSize = 2;
700 | tabSize = IndentSpy._getTabSize(
701 | vscode.window.activeTextEditor.options);
702 | IndentSpy._outerConf.hoverConf.peekBlockPlaceholder = 'foo!';
703 | let result = IndentSpy._buildHoverPlaceholder(editor, tabSize, IndentSpy._outerConf);
704 | assert.strictEqual(result, " foo!");
705 | });
706 |
707 | test("uses configured indent",() => {
708 | editor.options.insertSpaces = false;
709 | editor.options.tabSize = 3;
710 | tabSize = IndentSpy._getTabSize(
711 | vscode.window.activeTextEditor.options);
712 | IndentSpy._outerConf.hoverConf.peekBlockPlaceholder = 'bar!';
713 | let result = IndentSpy._buildHoverPlaceholder(editor, tabSize, IndentSpy._outerConf);
714 | assert.strictEqual(result, "\tbar!");
715 | });
716 | });
717 |
718 | suite("_buildHoverString", () => {
719 | let editor : vscode.TextEditor, tabSize;
720 |
721 | suiteSetup(() => {
722 | // set tabSize to 2 with whitespaces
723 | vscode.window.activeTextEditor.options.insertSpaces = true;
724 | vscode.window.activeTextEditor.options.tabSize = 2;
725 | tabSize = IndentSpy._getTabSize(
726 | vscode.window.activeTextEditor.options);
727 |
728 | editor = vscode.window.activeTextEditor;
729 | return setEditorContent(editor,
730 | "() => {\n" +
731 | " //foo?\n" +
732 | " //\n" +
733 | " foo();\n" +
734 | " if(foo()) {\n" +
735 | " bar();\n" +
736 | " return;\n" +
737 | " }\n" +
738 | " //foo?\n" +
739 | " //\n" +
740 | " foo();\n" +
741 | "}\n"
742 | );
743 | });
744 |
745 | setup(() => {
746 | IndentSpy._outerConf.hoverConf = {
747 | highlight: true,
748 | peekBack: 3,
749 | peekForward: 3,
750 | trimLinesShorterThan: 3,
751 | peekBlockPlaceholder: '// my indent block'
752 | };
753 | IndentSpy._outerConf.firstLine = 4;
754 | IndentSpy._outerConf.lastLine = 7;
755 | IndentSpy._outerConf.indentPos = 4;
756 | })
757 |
758 | test("returns a block using the configured peek options",
759 | () => {
760 | let block = IndentSpy._buildHoverString(editor, tabSize, IndentSpy._outerConf);
761 | assert.strictEqual(
762 | block,
763 | "foo();\n" +
764 | "if(foo()) {\n" +
765 | " // my indent block\n" +
766 | "}\n" +
767 | "//foo?"
768 | );
769 | });
770 | });
771 | });
772 | });
--------------------------------------------------------------------------------
/test/suite/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(testsRoot: string, cb: (error: any, failures?: number) => void): void {
6 | // Create the mocha test
7 | const mocha = new Mocha({
8 | ui: 'tdd',
9 | color: true
10 | });
11 |
12 | glob('**/**.test.js', { cwd: testsRoot }, (err, files) => {
13 | if (err) {
14 | return cb(err);
15 | }
16 |
17 | // Add files to the test suite
18 | files.forEach(f => mocha.addFile(path.resolve(testsRoot, f)));
19 |
20 | try {
21 | // Run the mocha test
22 | mocha.run(failures => {
23 | cb(null, failures);
24 | });
25 | } catch (err) {
26 | console.error(err);
27 | cb(err);
28 | }
29 | });
30 | }
--------------------------------------------------------------------------------
/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 | },
12 | "include": [
13 | "src",
14 | "test"
15 | ],
16 | "exclude": [
17 | "node_modules",
18 | ".vscode-test"
19 | ]
20 | }
--------------------------------------------------------------------------------
/vsc-extension-quickstart.md:
--------------------------------------------------------------------------------
1 | # Welcome to your first VS Code Extension
2 |
3 | ## What's in the folder
4 | * This folder contains all of the files necessary for your extension
5 | * `package.json` - this is the manifest file in which you declare your extension and command.
6 | The sample plugin registers a command and defines its title and command name. With this information
7 | VS Code can show the command in the command palette. It doesn’t yet need to load the plugin.
8 | * `src/extension.ts` - this is the main file where you will provide the implementation of your command.
9 | The file exports one function, `activate`, which is called the very first time your extension is
10 | activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`.
11 | We pass the function containing the implementation of the command as the second parameter to
12 | `registerCommand`.
13 |
14 | ## Get up and running straight away
15 | * press `F5` to open a new window with your extension loaded
16 | * run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`
17 | * set breakpoints in your code inside `src/extension.ts` to debug your extension
18 | * find output from your extension in the debug console
19 |
20 | ## Make changes
21 | * you can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`
22 | * you can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes
23 |
24 | ## Explore the API
25 | * you can open the full set of our API when you open the file `node_modules/vscode/vscode.d.ts`
26 |
27 | ## Run tests
28 | * open the debug viewlet (`Ctrl+Shift+D` or `Cmd+Shift+D` on Mac) and from the launch configuration dropdown pick `Launch Tests`
29 | * press `F5` to run the tests in a new window with your extension loaded
30 | * see the output of the test result in the debug console
31 | * make changes to `test/extension.test.ts` or create new test files inside the `test` folder
32 | * by convention, the test runner will only consider files matching the name pattern `**.test.ts`
33 | * you can create folders inside the `test` folder to structure your tests any way you want
--------------------------------------------------------------------------------