├── .github └── workflows │ └── publish.yml ├── .gitignore ├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── tasks.json ├── .vscodeignore ├── LICENSE.md ├── README.md ├── SECURITY.md ├── images ├── banner.png ├── icon.png ├── screenshot-config.gif ├── screenshot-env.gif ├── screenshot-middleware.gif ├── screenshot-mix.gif ├── screenshot-route.gif ├── screenshot-section.gif ├── screenshot-trans.gif ├── screenshot-validation.gif └── screenshot-view.gif ├── package-lock.json ├── package.json ├── src ├── AssetProvider.ts ├── AuthProvider.ts ├── BladeProvider.ts ├── ConfigProvider.ts ├── EloquentProvider.ts ├── EnvProvider.ts ├── MiddlewareProvider.ts ├── MixProvider.ts ├── RouteProvider.ts ├── TranslationProvider.ts ├── ValidationProvider.ts ├── ViewProvider.ts ├── ViteProvider.ts ├── extension.ts └── helpers.ts ├── tsconfig.json ├── tslint.json └── webpack.config.js /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | 3 | on: 4 | push: 5 | tags: 6 | - "*" 7 | 8 | jobs: 9 | deploy: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | - uses: actions/setup-node@v1 14 | with: 15 | node-version: 16 16 | - run: npm i 17 | - name: Publish to Visual Studio Marketplace 18 | uses: HaaLeo/publish-vscode-extension@v1 19 | with: 20 | pat: ${{ secrets.VS_MARKETPLACE_TOKEN }} 21 | registryUrl: https://marketplace.visualstudio.com 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | node_modules 3 | .vscode-test/ 4 | *.vsix 5 | dist 6 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "ms-vscode.vscode-typescript-tslint-plugin" 6 | ] 7 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Run Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "runtimeExecutable": "${execPath}", 13 | "args": [ 14 | "--extensionDevelopmentPath=${workspaceFolder}" 15 | ], 16 | "outFiles": [ 17 | "${workspaceFolder}/dist/*.js" 18 | ] 19 | }, 20 | { 21 | "name": "Extension Tests", 22 | "type": "extensionHost", 23 | "request": "launch", 24 | "runtimeExecutable": "${execPath}", 25 | "args": [ 26 | "--extensionDevelopmentPath=${workspaceFolder}", 27 | "--extensionTestsPath=${workspaceFolder}/dist/test" 28 | ], 29 | "outFiles": [ 30 | "${workspaceFolder}/dist/test/*.js" 31 | ] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /.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 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts 10 | "typescript.tsc.autoDetect": "off" 11 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "watch", 9 | "problemMatcher": "$tsc-watch", 10 | "isBackground": true, 11 | "presentation": { 12 | "reveal": "never" 13 | }, 14 | "group": { 15 | "kind": "build", 16 | "isDefault": true 17 | } 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | src/** 4 | images/screenshot.gif 5 | .gitignore 6 | vsc-extension-quickstart.md 7 | **/tsconfig.json 8 | **/tslint.json 9 | **/*.map 10 | **/*.ts 11 | node_modules/** 12 | .vscode 13 | tsconfig.json 14 | webpack.config.js 15 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 amir alizadeh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |

Laravel Extra Intellisense

3 | 4 |
5 | 6 |
7 | 8 | This extension provides [Laravel](https://laravel.com/) routes, views and ... autocomplete for [VSCode](https://code.visualstudio.com/). 9 | 10 | Please read the [security note](#security-note) and [how to configure](#sample-config-to-use-docker) before using the extension. 11 | 12 | ## Autocomplete 13 | * [Route names and route parameters](#route-names-and-route-parameters) 14 | * [Views and variables](#views-and-variables) 15 | * [Configs](#configs) 16 | * [Translations and translation parameters](#translations-and-translation-parameters) 17 | * [Laravel mix and vite functions](#laravel-mix-and-vite-functions) 18 | * [Validation rules](#validation-rules) 19 | * [View sections and stacks](#view-sections-and-stacks) 20 | * [Env](#env) 21 | * [Route Middlewares](#route-middlewares) 22 | * Asset 23 | * Model Attributes (Beta!) 24 | * Blade directives 25 | 26 | ### Route names and route parameters 27 | ![Routes](./images/screenshot-route.gif) 28 | ### Views and variables 29 | ![Views](./images/screenshot-view.gif) 30 | ### Configs 31 | ![Configs](./images/screenshot-config.gif) 32 | ### Translations and translation parameters 33 | ![Translations](./images/screenshot-trans.gif) 34 | ### Laravel mix and vite functions 35 | ![Mix](./images/screenshot-mix.gif) 36 | ### Validation rules 37 | ![Validation rules](./images/screenshot-validation.gif) 38 | ### View sections and stacks 39 | ![View sections](./images/screenshot-section.gif) 40 | ### Env 41 | ![env](./images/screenshot-env.gif) 42 | ### Route Middlewares 43 | ![Middlewares](./images/screenshot-middleware.gif) 44 | 45 | ## Configuration 46 | ### LaravelExtraIntellisense.customValidationRules: 47 | Your custom validation rules snippets. 48 | 49 | Example: 50 | ```json 51 | "LaravelExtraIntellisense.customValidationRules": { 52 | "mobile": "mobile", 53 | "distance_gt": "distance_gt:${0:1km}" 54 | } 55 | ``` 56 | 57 | ### LaravelExtraIntellisense.phpCommand 58 | Command to run PHP codes to interact with your Laravel application. 59 | 60 | Default: 61 | `php -r \"{code}\"` 62 | > Note: {code} is PHP code generated by extension and should be wrapped with "". 63 | 64 | ### LaravelExtraIntellisense.basePath 65 | Base path of your Laravel application. useful if your Laravel project is not at the root of you project directory. 66 | > If the base path starts with `.` (like `./src`) it will be considered a relative path otherwise it will be considered an absolute path. 67 | 68 | ### LaravelExtraIntellisense.basePathForCode 69 | Same as `LaravelExtraIntellisense.basePath` but this one using for `require_once` in generated PHP codes. 70 | 71 | ### LaravelExtraIntellisense.viewDirectorySeparator 72 | You also can use `/` instead of `.` as directory separator for view autocomplete. 73 | 74 | ### LaravelExtraIntellisense.modelsPaths 75 | Array of paths including your models. (Default: `["app", "app/Models"]`) 76 | 77 | ### LaravelExtraIntellisense.modelVariables 78 | Variable names that should provide autocomplete with specific model class. Finding variable type (especially in views) is not easy so you need to manually define variable types. 79 | 80 | Example: The Following setting provides auto completion each time you type `discountedProduct->` with `App\Models\Product` model attributes. 81 | ```json 82 | "LaravelExtraIntellisense.modelVariables": { 83 | "discountedProduct": "App\\Models\\Product" 84 | } 85 | ``` 86 | > All `camelCase` and `snake_case` of model names provide autocomplete by default. 87 | > For example `productDiscount` and `product_discount` provides member autocomplete from `App\Models\ProductDiscount` model. 88 | 89 | ### LaravelExtraIntellisense.modelAttributeCase 90 | Change model attribute names case to `snake_case`, `camelCase` or `default`. (Default = `default`) 91 | 92 | ### LaravelExtraIntellisense.modelAccessorCase 93 | Change model accessor names case to `snake_case`, `camelCase` or `default`. (Default = `snake`) 94 | 95 | ### LaravelExtraIntellisense.disableBlade 96 | If you want to disable blade directives autocomplete set this to true. 97 | 98 | ### LaravelExtraIntellisense.disableAuth 99 | If you want to disable authorization autocomplete set this to true 100 | 101 | ### LaravelExtraIntellisense.disableErrorAlert 102 | Hide error alerts when extension can't get data from your application. 103 | 104 | #### Sample config to use docker 105 | This is a simple configuration to use via [Laradock](https://github.com/laradock/laradock). 106 | 107 | ```json 108 | "LaravelExtraIntellisense.phpCommand": "docker exec -w /var/www/your-project -u laradock laradock_workspace_1 php -r \"{code}\"", 109 | "LaravelExtraIntellisense.basePathForCode": "/var/www/your-project" 110 | ``` 111 | 112 | Another sample for [Laravel Sail](https://laravel.com/docs/sail). 113 | 114 | ```json 115 | "LaravelExtraIntellisense.basePathForCode": "/var/www/html", 116 | "LaravelExtraIntellisense.phpCommand": "docker-compose exec -w /var/www/html YOUR_SERVICE_NAME php -r \"{code}\"" 117 | ``` 118 | Default YOUR_SERVICE_NAME for Laravel sail is `laravel.test`. 119 | 120 | It is possible to use this extension with other docker images or even other virtual machines. 121 | 122 | ## Security Note 123 | This extension runs your Laravel application automatically and periodically to get the information needed to provide autocomplete. 124 | 125 | So if you have any unknown errors in your log make sure the extension not causing it. 126 | 127 | Also if you writing any sensitive code in your service providers, disable the extension temporarily to prevent unwanted application executing. 128 | 129 | ## Release Notes 130 | 131 | ### 0.6.x 132 | * Add blade directives autocomplete (#45). 133 | * Add change case option for model attributes (#46). 134 | * Add support workspace with multiple directory (#54). 135 | * Add nested translations support (#54). 136 | * Add Vite autocompletion support (#131) 137 | 138 | ### 0.5.x 139 | * Add `asset` support. 140 | * Add Model attributes autocomplete (Beta). 141 | 142 | ### 0.4.x 143 | * Add Docker support. 144 | 145 | ### 0.3.x 146 | * `env` autocomplete added. 147 | * Route `middleware` autocomplete added. 148 | * Nested stack and section support added. 149 | * Function parser improvement. 150 | * Performance improvement. 151 | * Bug fixes (#25, #26) 152 | * Add configuration for views separator (#22). 153 | * `can`, `cannot` autocomplete. 154 | * Fix #18. 155 | 156 | ### 0.2.x 157 | * Validation rules autocomplete added. 158 | * works with `Validator` class, `validate` functions and inside request classes. 159 | * `markdown` function added to view functions for autocomplete. 160 | * Using file watcher instead of save event. Better change detect for view autocomplete. 161 | * json translation autocomplete added. 162 | * Auto-Retry removed from all providers. causes some performance issues. 163 | * Disable logging added. 164 | * View parameters autocomplete. 165 | * Route autocomplete bug in linux fixed. 166 | * Blade section autocomplete added. 167 | * Blade stack autocomplete added. 168 | * Duplicate section autocomplete items fixed. 169 | * PHP commands converted to async functions to prevent unresponsive extension host error. 170 | 171 | ### 0.1.x 172 | * Fix problems with linux. 173 | * Add translation autocomplete. 174 | * Improved providers. 175 | * Add mix autocomplete. 176 | * Performance improvments. 177 | * Route action autocomplete added. `Route::get`, *`Route::post`, ... autocompletes controller actions inside app\Http\Controllers. 178 | 179 | ### 0.0.x 180 | * Config autocomplete added. 181 | * Route bug fix. 182 | * View names with namespaces ready to use. 183 | * View functions autocomplete added. 184 | * Blade bug fix. 185 | * Add route autocomplete. 186 | 187 | ## Recommended extensions 188 | * [PHP Intelephense](https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client) 189 | * [PHPCS](https://marketplace.visualstudio.com/items?itemName=ikappas.phpcs) 190 | * [PHP DocBlocker](https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker) 191 | * [PHP formatter](https://marketplace.visualstudio.com/items?itemName=kokororin.vscode-phpfmt) 192 | * [Laravel Blade Snippets](https://marketplace.visualstudio.com/items?itemName=onecentlin.laravel-blade) 193 | * [Laravel goto view](https://marketplace.visualstudio.com/items?itemName=codingyu.laravel-goto-view) 194 | * [Laravel goto controller](https://marketplace.visualstudio.com/items?itemName=stef-k.laravel-goto-controller) 195 | * [DevDb](https://marketplace.visualstudio.com/items?itemName=damms005.devdb) 196 | 197 | ## Credits 198 | * [PHP parser](https://github.com/glayzzle/php-parser) 199 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | If you discover a security vulnerability within Laravel, please send an email to me at amiralizadeh9480@gmail.com. -------------------------------------------------------------------------------- /images/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amir9480/vscode-laravel-extra-intellisense/a6d75a64e7b0d16f14b58abcc928b42290688ed8/images/banner.png -------------------------------------------------------------------------------- /images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amir9480/vscode-laravel-extra-intellisense/a6d75a64e7b0d16f14b58abcc928b42290688ed8/images/icon.png -------------------------------------------------------------------------------- /images/screenshot-config.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amir9480/vscode-laravel-extra-intellisense/a6d75a64e7b0d16f14b58abcc928b42290688ed8/images/screenshot-config.gif -------------------------------------------------------------------------------- /images/screenshot-env.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amir9480/vscode-laravel-extra-intellisense/a6d75a64e7b0d16f14b58abcc928b42290688ed8/images/screenshot-env.gif -------------------------------------------------------------------------------- /images/screenshot-middleware.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amir9480/vscode-laravel-extra-intellisense/a6d75a64e7b0d16f14b58abcc928b42290688ed8/images/screenshot-middleware.gif -------------------------------------------------------------------------------- /images/screenshot-mix.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amir9480/vscode-laravel-extra-intellisense/a6d75a64e7b0d16f14b58abcc928b42290688ed8/images/screenshot-mix.gif -------------------------------------------------------------------------------- /images/screenshot-route.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amir9480/vscode-laravel-extra-intellisense/a6d75a64e7b0d16f14b58abcc928b42290688ed8/images/screenshot-route.gif -------------------------------------------------------------------------------- /images/screenshot-section.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amir9480/vscode-laravel-extra-intellisense/a6d75a64e7b0d16f14b58abcc928b42290688ed8/images/screenshot-section.gif -------------------------------------------------------------------------------- /images/screenshot-trans.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amir9480/vscode-laravel-extra-intellisense/a6d75a64e7b0d16f14b58abcc928b42290688ed8/images/screenshot-trans.gif -------------------------------------------------------------------------------- /images/screenshot-validation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amir9480/vscode-laravel-extra-intellisense/a6d75a64e7b0d16f14b58abcc928b42290688ed8/images/screenshot-validation.gif -------------------------------------------------------------------------------- /images/screenshot-view.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amir9480/vscode-laravel-extra-intellisense/a6d75a64e7b0d16f14b58abcc928b42290688ed8/images/screenshot-view.gif -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laravel-extra-intellisense", 3 | "version": "0.7.2", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "laravel-extra-intellisense", 9 | "version": "0.7.2", 10 | "dependencies": { 11 | "php-parser": "^3.0.2" 12 | }, 13 | "devDependencies": { 14 | "@types/mocha": "^8.2.1", 15 | "@types/node": "^14.14.31", 16 | "@types/vscode": "^1.83.0", 17 | "ts-loader": "^8.0.17", 18 | "tslint": "^6.1.3", 19 | "typescript": "^4.2.2", 20 | "vscode-test": "^1.6.1", 21 | "webpack": "^5.24.2", 22 | "webpack-cli": "^4.5.0" 23 | }, 24 | "engines": { 25 | "vscode": "^1.83.0" 26 | } 27 | }, 28 | "node_modules/@babel/code-frame": { 29 | "version": "7.22.13", 30 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", 31 | "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", 32 | "dev": true, 33 | "dependencies": { 34 | "@babel/highlight": "^7.22.13", 35 | "chalk": "^2.4.2" 36 | }, 37 | "engines": { 38 | "node": ">=6.9.0" 39 | } 40 | }, 41 | "node_modules/@babel/code-frame/node_modules/ansi-styles": { 42 | "version": "3.2.1", 43 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 44 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 45 | "dev": true, 46 | "dependencies": { 47 | "color-convert": "^1.9.0" 48 | }, 49 | "engines": { 50 | "node": ">=4" 51 | } 52 | }, 53 | "node_modules/@babel/code-frame/node_modules/chalk": { 54 | "version": "2.4.2", 55 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 56 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 57 | "dev": true, 58 | "dependencies": { 59 | "ansi-styles": "^3.2.1", 60 | "escape-string-regexp": "^1.0.5", 61 | "supports-color": "^5.3.0" 62 | }, 63 | "engines": { 64 | "node": ">=4" 65 | } 66 | }, 67 | "node_modules/@babel/code-frame/node_modules/color-convert": { 68 | "version": "1.9.3", 69 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 70 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 71 | "dev": true, 72 | "dependencies": { 73 | "color-name": "1.1.3" 74 | } 75 | }, 76 | "node_modules/@babel/code-frame/node_modules/color-name": { 77 | "version": "1.1.3", 78 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 79 | "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", 80 | "dev": true 81 | }, 82 | "node_modules/@babel/code-frame/node_modules/has-flag": { 83 | "version": "3.0.0", 84 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 85 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 86 | "dev": true, 87 | "engines": { 88 | "node": ">=4" 89 | } 90 | }, 91 | "node_modules/@babel/code-frame/node_modules/supports-color": { 92 | "version": "5.5.0", 93 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 94 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 95 | "dev": true, 96 | "dependencies": { 97 | "has-flag": "^3.0.0" 98 | }, 99 | "engines": { 100 | "node": ">=4" 101 | } 102 | }, 103 | "node_modules/@babel/helper-validator-identifier": { 104 | "version": "7.22.20", 105 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", 106 | "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", 107 | "dev": true, 108 | "engines": { 109 | "node": ">=6.9.0" 110 | } 111 | }, 112 | "node_modules/@babel/highlight": { 113 | "version": "7.22.20", 114 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", 115 | "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", 116 | "dev": true, 117 | "dependencies": { 118 | "@babel/helper-validator-identifier": "^7.22.20", 119 | "chalk": "^2.4.2", 120 | "js-tokens": "^4.0.0" 121 | }, 122 | "engines": { 123 | "node": ">=6.9.0" 124 | } 125 | }, 126 | "node_modules/@babel/highlight/node_modules/ansi-styles": { 127 | "version": "3.2.1", 128 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 129 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 130 | "dev": true, 131 | "dependencies": { 132 | "color-convert": "^1.9.0" 133 | }, 134 | "engines": { 135 | "node": ">=4" 136 | } 137 | }, 138 | "node_modules/@babel/highlight/node_modules/chalk": { 139 | "version": "2.4.2", 140 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 141 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 142 | "dev": true, 143 | "dependencies": { 144 | "ansi-styles": "^3.2.1", 145 | "escape-string-regexp": "^1.0.5", 146 | "supports-color": "^5.3.0" 147 | }, 148 | "engines": { 149 | "node": ">=4" 150 | } 151 | }, 152 | "node_modules/@babel/highlight/node_modules/color-convert": { 153 | "version": "1.9.3", 154 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 155 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 156 | "dev": true, 157 | "dependencies": { 158 | "color-name": "1.1.3" 159 | } 160 | }, 161 | "node_modules/@babel/highlight/node_modules/color-name": { 162 | "version": "1.1.3", 163 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 164 | "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", 165 | "dev": true 166 | }, 167 | "node_modules/@babel/highlight/node_modules/has-flag": { 168 | "version": "3.0.0", 169 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 170 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 171 | "dev": true, 172 | "engines": { 173 | "node": ">=4" 174 | } 175 | }, 176 | "node_modules/@babel/highlight/node_modules/supports-color": { 177 | "version": "5.5.0", 178 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 179 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 180 | "dev": true, 181 | "dependencies": { 182 | "has-flag": "^3.0.0" 183 | }, 184 | "engines": { 185 | "node": ">=4" 186 | } 187 | }, 188 | "node_modules/@discoveryjs/json-ext": { 189 | "version": "0.5.7", 190 | "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", 191 | "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", 192 | "dev": true, 193 | "engines": { 194 | "node": ">=10.0.0" 195 | } 196 | }, 197 | "node_modules/@jridgewell/gen-mapping": { 198 | "version": "0.3.3", 199 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", 200 | "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", 201 | "dev": true, 202 | "dependencies": { 203 | "@jridgewell/set-array": "^1.0.1", 204 | "@jridgewell/sourcemap-codec": "^1.4.10", 205 | "@jridgewell/trace-mapping": "^0.3.9" 206 | }, 207 | "engines": { 208 | "node": ">=6.0.0" 209 | } 210 | }, 211 | "node_modules/@jridgewell/resolve-uri": { 212 | "version": "3.1.1", 213 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", 214 | "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", 215 | "dev": true, 216 | "engines": { 217 | "node": ">=6.0.0" 218 | } 219 | }, 220 | "node_modules/@jridgewell/set-array": { 221 | "version": "1.1.2", 222 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", 223 | "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", 224 | "dev": true, 225 | "engines": { 226 | "node": ">=6.0.0" 227 | } 228 | }, 229 | "node_modules/@jridgewell/source-map": { 230 | "version": "0.3.5", 231 | "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", 232 | "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", 233 | "dev": true, 234 | "dependencies": { 235 | "@jridgewell/gen-mapping": "^0.3.0", 236 | "@jridgewell/trace-mapping": "^0.3.9" 237 | } 238 | }, 239 | "node_modules/@jridgewell/sourcemap-codec": { 240 | "version": "1.4.15", 241 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", 242 | "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", 243 | "dev": true 244 | }, 245 | "node_modules/@jridgewell/trace-mapping": { 246 | "version": "0.3.19", 247 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", 248 | "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", 249 | "dev": true, 250 | "dependencies": { 251 | "@jridgewell/resolve-uri": "^3.1.0", 252 | "@jridgewell/sourcemap-codec": "^1.4.14" 253 | } 254 | }, 255 | "node_modules/@tootallnate/once": { 256 | "version": "1.1.2", 257 | "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", 258 | "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", 259 | "dev": true, 260 | "engines": { 261 | "node": ">= 6" 262 | } 263 | }, 264 | "node_modules/@types/eslint": { 265 | "version": "8.44.3", 266 | "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.3.tgz", 267 | "integrity": "sha512-iM/WfkwAhwmPff3wZuPLYiHX18HI24jU8k1ZSH7P8FHwxTjZ2P6CoX2wnF43oprR+YXJM6UUxATkNvyv/JHd+g==", 268 | "dev": true, 269 | "dependencies": { 270 | "@types/estree": "*", 271 | "@types/json-schema": "*" 272 | } 273 | }, 274 | "node_modules/@types/eslint-scope": { 275 | "version": "3.7.5", 276 | "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.5.tgz", 277 | "integrity": "sha512-JNvhIEyxVW6EoMIFIvj93ZOywYFatlpu9deeH6eSx6PE3WHYvHaQtmHmQeNw7aA81bYGBPPQqdtBm6b1SsQMmA==", 278 | "dev": true, 279 | "dependencies": { 280 | "@types/eslint": "*", 281 | "@types/estree": "*" 282 | } 283 | }, 284 | "node_modules/@types/estree": { 285 | "version": "1.0.2", 286 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.2.tgz", 287 | "integrity": "sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==", 288 | "dev": true 289 | }, 290 | "node_modules/@types/json-schema": { 291 | "version": "7.0.13", 292 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", 293 | "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", 294 | "dev": true 295 | }, 296 | "node_modules/@types/mocha": { 297 | "version": "8.2.3", 298 | "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.3.tgz", 299 | "integrity": "sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw==", 300 | "dev": true 301 | }, 302 | "node_modules/@types/node": { 303 | "version": "14.18.63", 304 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", 305 | "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", 306 | "dev": true 307 | }, 308 | "node_modules/@types/vscode": { 309 | "version": "1.83.0", 310 | "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.83.0.tgz", 311 | "integrity": "sha512-3mUtHqLAVz9hegut9au4xehuBrzRE3UJiQMpoEHkNl6XHliihO7eATx2BMHs0odsmmrwjJrlixx/Pte6M3ygDQ==", 312 | "dev": true 313 | }, 314 | "node_modules/@webassemblyjs/ast": { 315 | "version": "1.11.6", 316 | "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", 317 | "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", 318 | "dev": true, 319 | "dependencies": { 320 | "@webassemblyjs/helper-numbers": "1.11.6", 321 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6" 322 | } 323 | }, 324 | "node_modules/@webassemblyjs/floating-point-hex-parser": { 325 | "version": "1.11.6", 326 | "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", 327 | "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", 328 | "dev": true 329 | }, 330 | "node_modules/@webassemblyjs/helper-api-error": { 331 | "version": "1.11.6", 332 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", 333 | "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", 334 | "dev": true 335 | }, 336 | "node_modules/@webassemblyjs/helper-buffer": { 337 | "version": "1.11.6", 338 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", 339 | "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", 340 | "dev": true 341 | }, 342 | "node_modules/@webassemblyjs/helper-numbers": { 343 | "version": "1.11.6", 344 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", 345 | "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", 346 | "dev": true, 347 | "dependencies": { 348 | "@webassemblyjs/floating-point-hex-parser": "1.11.6", 349 | "@webassemblyjs/helper-api-error": "1.11.6", 350 | "@xtuc/long": "4.2.2" 351 | } 352 | }, 353 | "node_modules/@webassemblyjs/helper-wasm-bytecode": { 354 | "version": "1.11.6", 355 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", 356 | "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", 357 | "dev": true 358 | }, 359 | "node_modules/@webassemblyjs/helper-wasm-section": { 360 | "version": "1.11.6", 361 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", 362 | "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", 363 | "dev": true, 364 | "dependencies": { 365 | "@webassemblyjs/ast": "1.11.6", 366 | "@webassemblyjs/helper-buffer": "1.11.6", 367 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6", 368 | "@webassemblyjs/wasm-gen": "1.11.6" 369 | } 370 | }, 371 | "node_modules/@webassemblyjs/ieee754": { 372 | "version": "1.11.6", 373 | "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", 374 | "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", 375 | "dev": true, 376 | "dependencies": { 377 | "@xtuc/ieee754": "^1.2.0" 378 | } 379 | }, 380 | "node_modules/@webassemblyjs/leb128": { 381 | "version": "1.11.6", 382 | "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", 383 | "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", 384 | "dev": true, 385 | "dependencies": { 386 | "@xtuc/long": "4.2.2" 387 | } 388 | }, 389 | "node_modules/@webassemblyjs/utf8": { 390 | "version": "1.11.6", 391 | "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", 392 | "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", 393 | "dev": true 394 | }, 395 | "node_modules/@webassemblyjs/wasm-edit": { 396 | "version": "1.11.6", 397 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", 398 | "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", 399 | "dev": true, 400 | "dependencies": { 401 | "@webassemblyjs/ast": "1.11.6", 402 | "@webassemblyjs/helper-buffer": "1.11.6", 403 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6", 404 | "@webassemblyjs/helper-wasm-section": "1.11.6", 405 | "@webassemblyjs/wasm-gen": "1.11.6", 406 | "@webassemblyjs/wasm-opt": "1.11.6", 407 | "@webassemblyjs/wasm-parser": "1.11.6", 408 | "@webassemblyjs/wast-printer": "1.11.6" 409 | } 410 | }, 411 | "node_modules/@webassemblyjs/wasm-gen": { 412 | "version": "1.11.6", 413 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", 414 | "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", 415 | "dev": true, 416 | "dependencies": { 417 | "@webassemblyjs/ast": "1.11.6", 418 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6", 419 | "@webassemblyjs/ieee754": "1.11.6", 420 | "@webassemblyjs/leb128": "1.11.6", 421 | "@webassemblyjs/utf8": "1.11.6" 422 | } 423 | }, 424 | "node_modules/@webassemblyjs/wasm-opt": { 425 | "version": "1.11.6", 426 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", 427 | "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", 428 | "dev": true, 429 | "dependencies": { 430 | "@webassemblyjs/ast": "1.11.6", 431 | "@webassemblyjs/helper-buffer": "1.11.6", 432 | "@webassemblyjs/wasm-gen": "1.11.6", 433 | "@webassemblyjs/wasm-parser": "1.11.6" 434 | } 435 | }, 436 | "node_modules/@webassemblyjs/wasm-parser": { 437 | "version": "1.11.6", 438 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", 439 | "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", 440 | "dev": true, 441 | "dependencies": { 442 | "@webassemblyjs/ast": "1.11.6", 443 | "@webassemblyjs/helper-api-error": "1.11.6", 444 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6", 445 | "@webassemblyjs/ieee754": "1.11.6", 446 | "@webassemblyjs/leb128": "1.11.6", 447 | "@webassemblyjs/utf8": "1.11.6" 448 | } 449 | }, 450 | "node_modules/@webassemblyjs/wast-printer": { 451 | "version": "1.11.6", 452 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", 453 | "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", 454 | "dev": true, 455 | "dependencies": { 456 | "@webassemblyjs/ast": "1.11.6", 457 | "@xtuc/long": "4.2.2" 458 | } 459 | }, 460 | "node_modules/@webpack-cli/configtest": { 461 | "version": "1.2.0", 462 | "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", 463 | "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", 464 | "dev": true, 465 | "peerDependencies": { 466 | "webpack": "4.x.x || 5.x.x", 467 | "webpack-cli": "4.x.x" 468 | } 469 | }, 470 | "node_modules/@webpack-cli/info": { 471 | "version": "1.5.0", 472 | "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz", 473 | "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", 474 | "dev": true, 475 | "dependencies": { 476 | "envinfo": "^7.7.3" 477 | }, 478 | "peerDependencies": { 479 | "webpack-cli": "4.x.x" 480 | } 481 | }, 482 | "node_modules/@webpack-cli/serve": { 483 | "version": "1.7.0", 484 | "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", 485 | "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", 486 | "dev": true, 487 | "peerDependencies": { 488 | "webpack-cli": "4.x.x" 489 | }, 490 | "peerDependenciesMeta": { 491 | "webpack-dev-server": { 492 | "optional": true 493 | } 494 | } 495 | }, 496 | "node_modules/@xtuc/ieee754": { 497 | "version": "1.2.0", 498 | "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", 499 | "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", 500 | "dev": true 501 | }, 502 | "node_modules/@xtuc/long": { 503 | "version": "4.2.2", 504 | "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", 505 | "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", 506 | "dev": true 507 | }, 508 | "node_modules/acorn": { 509 | "version": "8.10.0", 510 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", 511 | "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", 512 | "dev": true, 513 | "bin": { 514 | "acorn": "bin/acorn" 515 | }, 516 | "engines": { 517 | "node": ">=0.4.0" 518 | } 519 | }, 520 | "node_modules/acorn-import-assertions": { 521 | "version": "1.9.0", 522 | "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", 523 | "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", 524 | "dev": true, 525 | "peerDependencies": { 526 | "acorn": "^8" 527 | } 528 | }, 529 | "node_modules/agent-base": { 530 | "version": "6.0.2", 531 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", 532 | "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", 533 | "dev": true, 534 | "dependencies": { 535 | "debug": "4" 536 | }, 537 | "engines": { 538 | "node": ">= 6.0.0" 539 | } 540 | }, 541 | "node_modules/ajv": { 542 | "version": "6.12.6", 543 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 544 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 545 | "dev": true, 546 | "dependencies": { 547 | "fast-deep-equal": "^3.1.1", 548 | "fast-json-stable-stringify": "^2.0.0", 549 | "json-schema-traverse": "^0.4.1", 550 | "uri-js": "^4.2.2" 551 | }, 552 | "funding": { 553 | "type": "github", 554 | "url": "https://github.com/sponsors/epoberezkin" 555 | } 556 | }, 557 | "node_modules/ajv-keywords": { 558 | "version": "3.5.2", 559 | "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", 560 | "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", 561 | "dev": true, 562 | "peerDependencies": { 563 | "ajv": "^6.9.1" 564 | } 565 | }, 566 | "node_modules/ansi-styles": { 567 | "version": "4.3.0", 568 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 569 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 570 | "dev": true, 571 | "dependencies": { 572 | "color-convert": "^2.0.1" 573 | }, 574 | "engines": { 575 | "node": ">=8" 576 | }, 577 | "funding": { 578 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 579 | } 580 | }, 581 | "node_modules/argparse": { 582 | "version": "1.0.10", 583 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 584 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 585 | "dev": true, 586 | "dependencies": { 587 | "sprintf-js": "~1.0.2" 588 | } 589 | }, 590 | "node_modules/balanced-match": { 591 | "version": "1.0.2", 592 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 593 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 594 | "dev": true 595 | }, 596 | "node_modules/big-integer": { 597 | "version": "1.6.51", 598 | "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", 599 | "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", 600 | "dev": true, 601 | "engines": { 602 | "node": ">=0.6" 603 | } 604 | }, 605 | "node_modules/big.js": { 606 | "version": "5.2.2", 607 | "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", 608 | "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", 609 | "dev": true, 610 | "engines": { 611 | "node": "*" 612 | } 613 | }, 614 | "node_modules/binary": { 615 | "version": "0.3.0", 616 | "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", 617 | "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", 618 | "dev": true, 619 | "dependencies": { 620 | "buffers": "~0.1.1", 621 | "chainsaw": "~0.1.0" 622 | }, 623 | "engines": { 624 | "node": "*" 625 | } 626 | }, 627 | "node_modules/bluebird": { 628 | "version": "3.4.7", 629 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", 630 | "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", 631 | "dev": true 632 | }, 633 | "node_modules/brace-expansion": { 634 | "version": "1.1.11", 635 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 636 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 637 | "dev": true, 638 | "dependencies": { 639 | "balanced-match": "^1.0.0", 640 | "concat-map": "0.0.1" 641 | } 642 | }, 643 | "node_modules/braces": { 644 | "version": "3.0.2", 645 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 646 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 647 | "dev": true, 648 | "dependencies": { 649 | "fill-range": "^7.0.1" 650 | }, 651 | "engines": { 652 | "node": ">=8" 653 | } 654 | }, 655 | "node_modules/browserslist": { 656 | "version": "4.22.1", 657 | "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", 658 | "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", 659 | "dev": true, 660 | "funding": [ 661 | { 662 | "type": "opencollective", 663 | "url": "https://opencollective.com/browserslist" 664 | }, 665 | { 666 | "type": "tidelift", 667 | "url": "https://tidelift.com/funding/github/npm/browserslist" 668 | }, 669 | { 670 | "type": "github", 671 | "url": "https://github.com/sponsors/ai" 672 | } 673 | ], 674 | "dependencies": { 675 | "caniuse-lite": "^1.0.30001541", 676 | "electron-to-chromium": "^1.4.535", 677 | "node-releases": "^2.0.13", 678 | "update-browserslist-db": "^1.0.13" 679 | }, 680 | "bin": { 681 | "browserslist": "cli.js" 682 | }, 683 | "engines": { 684 | "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" 685 | } 686 | }, 687 | "node_modules/buffer-from": { 688 | "version": "1.1.2", 689 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", 690 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", 691 | "dev": true 692 | }, 693 | "node_modules/buffer-indexof-polyfill": { 694 | "version": "1.0.2", 695 | "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", 696 | "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", 697 | "dev": true, 698 | "engines": { 699 | "node": ">=0.10" 700 | } 701 | }, 702 | "node_modules/buffers": { 703 | "version": "0.1.1", 704 | "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", 705 | "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", 706 | "dev": true, 707 | "engines": { 708 | "node": ">=0.2.0" 709 | } 710 | }, 711 | "node_modules/builtin-modules": { 712 | "version": "1.1.1", 713 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", 714 | "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==", 715 | "dev": true, 716 | "engines": { 717 | "node": ">=0.10.0" 718 | } 719 | }, 720 | "node_modules/caniuse-lite": { 721 | "version": "1.0.30001546", 722 | "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001546.tgz", 723 | "integrity": "sha512-zvtSJwuQFpewSyRrI3AsftF6rM0X80mZkChIt1spBGEvRglCrjTniXvinc8JKRoqTwXAgvqTImaN9igfSMtUBw==", 724 | "dev": true, 725 | "funding": [ 726 | { 727 | "type": "opencollective", 728 | "url": "https://opencollective.com/browserslist" 729 | }, 730 | { 731 | "type": "tidelift", 732 | "url": "https://tidelift.com/funding/github/npm/caniuse-lite" 733 | }, 734 | { 735 | "type": "github", 736 | "url": "https://github.com/sponsors/ai" 737 | } 738 | ] 739 | }, 740 | "node_modules/chainsaw": { 741 | "version": "0.1.0", 742 | "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", 743 | "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", 744 | "dev": true, 745 | "dependencies": { 746 | "traverse": ">=0.3.0 <0.4" 747 | }, 748 | "engines": { 749 | "node": "*" 750 | } 751 | }, 752 | "node_modules/chalk": { 753 | "version": "4.1.2", 754 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 755 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 756 | "dev": true, 757 | "dependencies": { 758 | "ansi-styles": "^4.1.0", 759 | "supports-color": "^7.1.0" 760 | }, 761 | "engines": { 762 | "node": ">=10" 763 | }, 764 | "funding": { 765 | "url": "https://github.com/chalk/chalk?sponsor=1" 766 | } 767 | }, 768 | "node_modules/chrome-trace-event": { 769 | "version": "1.0.3", 770 | "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", 771 | "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", 772 | "dev": true, 773 | "engines": { 774 | "node": ">=6.0" 775 | } 776 | }, 777 | "node_modules/clone-deep": { 778 | "version": "4.0.1", 779 | "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", 780 | "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", 781 | "dev": true, 782 | "dependencies": { 783 | "is-plain-object": "^2.0.4", 784 | "kind-of": "^6.0.2", 785 | "shallow-clone": "^3.0.0" 786 | }, 787 | "engines": { 788 | "node": ">=6" 789 | } 790 | }, 791 | "node_modules/color-convert": { 792 | "version": "2.0.1", 793 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 794 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 795 | "dev": true, 796 | "dependencies": { 797 | "color-name": "~1.1.4" 798 | }, 799 | "engines": { 800 | "node": ">=7.0.0" 801 | } 802 | }, 803 | "node_modules/color-name": { 804 | "version": "1.1.4", 805 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 806 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 807 | "dev": true 808 | }, 809 | "node_modules/colorette": { 810 | "version": "2.0.20", 811 | "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", 812 | "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", 813 | "dev": true 814 | }, 815 | "node_modules/commander": { 816 | "version": "2.20.3", 817 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 818 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", 819 | "dev": true 820 | }, 821 | "node_modules/concat-map": { 822 | "version": "0.0.1", 823 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 824 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 825 | "dev": true 826 | }, 827 | "node_modules/core-util-is": { 828 | "version": "1.0.3", 829 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", 830 | "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", 831 | "dev": true 832 | }, 833 | "node_modules/cross-spawn": { 834 | "version": "7.0.3", 835 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 836 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 837 | "dev": true, 838 | "dependencies": { 839 | "path-key": "^3.1.0", 840 | "shebang-command": "^2.0.0", 841 | "which": "^2.0.1" 842 | }, 843 | "engines": { 844 | "node": ">= 8" 845 | } 846 | }, 847 | "node_modules/debug": { 848 | "version": "4.3.4", 849 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 850 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 851 | "dev": true, 852 | "dependencies": { 853 | "ms": "2.1.2" 854 | }, 855 | "engines": { 856 | "node": ">=6.0" 857 | }, 858 | "peerDependenciesMeta": { 859 | "supports-color": { 860 | "optional": true 861 | } 862 | } 863 | }, 864 | "node_modules/diff": { 865 | "version": "4.0.2", 866 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 867 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 868 | "dev": true, 869 | "engines": { 870 | "node": ">=0.3.1" 871 | } 872 | }, 873 | "node_modules/duplexer2": { 874 | "version": "0.1.4", 875 | "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", 876 | "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", 877 | "dev": true, 878 | "dependencies": { 879 | "readable-stream": "^2.0.2" 880 | } 881 | }, 882 | "node_modules/electron-to-chromium": { 883 | "version": "1.4.544", 884 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.544.tgz", 885 | "integrity": "sha512-54z7squS1FyFRSUqq/knOFSptjjogLZXbKcYk3B0qkE1KZzvqASwRZnY2KzZQJqIYLVD38XZeoiMRflYSwyO4w==", 886 | "dev": true 887 | }, 888 | "node_modules/emojis-list": { 889 | "version": "3.0.0", 890 | "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", 891 | "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", 892 | "dev": true, 893 | "engines": { 894 | "node": ">= 4" 895 | } 896 | }, 897 | "node_modules/enhanced-resolve": { 898 | "version": "4.5.0", 899 | "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", 900 | "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", 901 | "dev": true, 902 | "dependencies": { 903 | "graceful-fs": "^4.1.2", 904 | "memory-fs": "^0.5.0", 905 | "tapable": "^1.0.0" 906 | }, 907 | "engines": { 908 | "node": ">=6.9.0" 909 | } 910 | }, 911 | "node_modules/envinfo": { 912 | "version": "7.10.0", 913 | "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.10.0.tgz", 914 | "integrity": "sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==", 915 | "dev": true, 916 | "bin": { 917 | "envinfo": "dist/cli.js" 918 | }, 919 | "engines": { 920 | "node": ">=4" 921 | } 922 | }, 923 | "node_modules/errno": { 924 | "version": "0.1.8", 925 | "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", 926 | "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", 927 | "dev": true, 928 | "dependencies": { 929 | "prr": "~1.0.1" 930 | }, 931 | "bin": { 932 | "errno": "cli.js" 933 | } 934 | }, 935 | "node_modules/es-module-lexer": { 936 | "version": "1.3.1", 937 | "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", 938 | "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", 939 | "dev": true 940 | }, 941 | "node_modules/escalade": { 942 | "version": "3.1.1", 943 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 944 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 945 | "dev": true, 946 | "engines": { 947 | "node": ">=6" 948 | } 949 | }, 950 | "node_modules/escape-string-regexp": { 951 | "version": "1.0.5", 952 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 953 | "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", 954 | "dev": true, 955 | "engines": { 956 | "node": ">=0.8.0" 957 | } 958 | }, 959 | "node_modules/eslint-scope": { 960 | "version": "5.1.1", 961 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", 962 | "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", 963 | "dev": true, 964 | "dependencies": { 965 | "esrecurse": "^4.3.0", 966 | "estraverse": "^4.1.1" 967 | }, 968 | "engines": { 969 | "node": ">=8.0.0" 970 | } 971 | }, 972 | "node_modules/esprima": { 973 | "version": "4.0.1", 974 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 975 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 976 | "dev": true, 977 | "bin": { 978 | "esparse": "bin/esparse.js", 979 | "esvalidate": "bin/esvalidate.js" 980 | }, 981 | "engines": { 982 | "node": ">=4" 983 | } 984 | }, 985 | "node_modules/esrecurse": { 986 | "version": "4.3.0", 987 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 988 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 989 | "dev": true, 990 | "dependencies": { 991 | "estraverse": "^5.2.0" 992 | }, 993 | "engines": { 994 | "node": ">=4.0" 995 | } 996 | }, 997 | "node_modules/esrecurse/node_modules/estraverse": { 998 | "version": "5.3.0", 999 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 1000 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 1001 | "dev": true, 1002 | "engines": { 1003 | "node": ">=4.0" 1004 | } 1005 | }, 1006 | "node_modules/estraverse": { 1007 | "version": "4.3.0", 1008 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 1009 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 1010 | "dev": true, 1011 | "engines": { 1012 | "node": ">=4.0" 1013 | } 1014 | }, 1015 | "node_modules/events": { 1016 | "version": "3.3.0", 1017 | "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", 1018 | "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", 1019 | "dev": true, 1020 | "engines": { 1021 | "node": ">=0.8.x" 1022 | } 1023 | }, 1024 | "node_modules/fast-deep-equal": { 1025 | "version": "3.1.3", 1026 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 1027 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 1028 | "dev": true 1029 | }, 1030 | "node_modules/fast-json-stable-stringify": { 1031 | "version": "2.1.0", 1032 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 1033 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 1034 | "dev": true 1035 | }, 1036 | "node_modules/fastest-levenshtein": { 1037 | "version": "1.0.16", 1038 | "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", 1039 | "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", 1040 | "dev": true, 1041 | "engines": { 1042 | "node": ">= 4.9.1" 1043 | } 1044 | }, 1045 | "node_modules/fill-range": { 1046 | "version": "7.0.1", 1047 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 1048 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 1049 | "dev": true, 1050 | "dependencies": { 1051 | "to-regex-range": "^5.0.1" 1052 | }, 1053 | "engines": { 1054 | "node": ">=8" 1055 | } 1056 | }, 1057 | "node_modules/find-up": { 1058 | "version": "4.1.0", 1059 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 1060 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 1061 | "dev": true, 1062 | "dependencies": { 1063 | "locate-path": "^5.0.0", 1064 | "path-exists": "^4.0.0" 1065 | }, 1066 | "engines": { 1067 | "node": ">=8" 1068 | } 1069 | }, 1070 | "node_modules/fs.realpath": { 1071 | "version": "1.0.0", 1072 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1073 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", 1074 | "dev": true 1075 | }, 1076 | "node_modules/fstream": { 1077 | "version": "1.0.12", 1078 | "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", 1079 | "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", 1080 | "dev": true, 1081 | "dependencies": { 1082 | "graceful-fs": "^4.1.2", 1083 | "inherits": "~2.0.0", 1084 | "mkdirp": ">=0.5 0", 1085 | "rimraf": "2" 1086 | }, 1087 | "engines": { 1088 | "node": ">=0.6" 1089 | } 1090 | }, 1091 | "node_modules/fstream/node_modules/rimraf": { 1092 | "version": "2.7.1", 1093 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", 1094 | "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", 1095 | "dev": true, 1096 | "dependencies": { 1097 | "glob": "^7.1.3" 1098 | }, 1099 | "bin": { 1100 | "rimraf": "bin.js" 1101 | } 1102 | }, 1103 | "node_modules/glob": { 1104 | "version": "7.2.3", 1105 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", 1106 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 1107 | "dev": true, 1108 | "dependencies": { 1109 | "fs.realpath": "^1.0.0", 1110 | "inflight": "^1.0.4", 1111 | "inherits": "2", 1112 | "minimatch": "^3.1.1", 1113 | "once": "^1.3.0", 1114 | "path-is-absolute": "^1.0.0" 1115 | }, 1116 | "engines": { 1117 | "node": "*" 1118 | }, 1119 | "funding": { 1120 | "url": "https://github.com/sponsors/isaacs" 1121 | } 1122 | }, 1123 | "node_modules/glob-to-regexp": { 1124 | "version": "0.4.1", 1125 | "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", 1126 | "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", 1127 | "dev": true 1128 | }, 1129 | "node_modules/graceful-fs": { 1130 | "version": "4.2.11", 1131 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", 1132 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", 1133 | "dev": true 1134 | }, 1135 | "node_modules/has": { 1136 | "version": "1.0.4", 1137 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", 1138 | "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", 1139 | "dev": true, 1140 | "engines": { 1141 | "node": ">= 0.4.0" 1142 | } 1143 | }, 1144 | "node_modules/has-flag": { 1145 | "version": "4.0.0", 1146 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1147 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1148 | "dev": true, 1149 | "engines": { 1150 | "node": ">=8" 1151 | } 1152 | }, 1153 | "node_modules/http-proxy-agent": { 1154 | "version": "4.0.1", 1155 | "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", 1156 | "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", 1157 | "dev": true, 1158 | "dependencies": { 1159 | "@tootallnate/once": "1", 1160 | "agent-base": "6", 1161 | "debug": "4" 1162 | }, 1163 | "engines": { 1164 | "node": ">= 6" 1165 | } 1166 | }, 1167 | "node_modules/https-proxy-agent": { 1168 | "version": "5.0.1", 1169 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", 1170 | "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", 1171 | "dev": true, 1172 | "dependencies": { 1173 | "agent-base": "6", 1174 | "debug": "4" 1175 | }, 1176 | "engines": { 1177 | "node": ">= 6" 1178 | } 1179 | }, 1180 | "node_modules/import-local": { 1181 | "version": "3.1.0", 1182 | "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", 1183 | "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", 1184 | "dev": true, 1185 | "dependencies": { 1186 | "pkg-dir": "^4.2.0", 1187 | "resolve-cwd": "^3.0.0" 1188 | }, 1189 | "bin": { 1190 | "import-local-fixture": "fixtures/cli.js" 1191 | }, 1192 | "engines": { 1193 | "node": ">=8" 1194 | }, 1195 | "funding": { 1196 | "url": "https://github.com/sponsors/sindresorhus" 1197 | } 1198 | }, 1199 | "node_modules/inflight": { 1200 | "version": "1.0.6", 1201 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1202 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 1203 | "dev": true, 1204 | "dependencies": { 1205 | "once": "^1.3.0", 1206 | "wrappy": "1" 1207 | } 1208 | }, 1209 | "node_modules/inherits": { 1210 | "version": "2.0.4", 1211 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1212 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1213 | "dev": true 1214 | }, 1215 | "node_modules/interpret": { 1216 | "version": "2.2.0", 1217 | "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", 1218 | "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", 1219 | "dev": true, 1220 | "engines": { 1221 | "node": ">= 0.10" 1222 | } 1223 | }, 1224 | "node_modules/is-core-module": { 1225 | "version": "2.13.0", 1226 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", 1227 | "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", 1228 | "dev": true, 1229 | "dependencies": { 1230 | "has": "^1.0.3" 1231 | }, 1232 | "funding": { 1233 | "url": "https://github.com/sponsors/ljharb" 1234 | } 1235 | }, 1236 | "node_modules/is-number": { 1237 | "version": "7.0.0", 1238 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1239 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1240 | "dev": true, 1241 | "engines": { 1242 | "node": ">=0.12.0" 1243 | } 1244 | }, 1245 | "node_modules/is-plain-object": { 1246 | "version": "2.0.4", 1247 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", 1248 | "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", 1249 | "dev": true, 1250 | "dependencies": { 1251 | "isobject": "^3.0.1" 1252 | }, 1253 | "engines": { 1254 | "node": ">=0.10.0" 1255 | } 1256 | }, 1257 | "node_modules/isarray": { 1258 | "version": "1.0.0", 1259 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 1260 | "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", 1261 | "dev": true 1262 | }, 1263 | "node_modules/isexe": { 1264 | "version": "2.0.0", 1265 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1266 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 1267 | "dev": true 1268 | }, 1269 | "node_modules/isobject": { 1270 | "version": "3.0.1", 1271 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 1272 | "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", 1273 | "dev": true, 1274 | "engines": { 1275 | "node": ">=0.10.0" 1276 | } 1277 | }, 1278 | "node_modules/jest-worker": { 1279 | "version": "27.5.1", 1280 | "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", 1281 | "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", 1282 | "dev": true, 1283 | "dependencies": { 1284 | "@types/node": "*", 1285 | "merge-stream": "^2.0.0", 1286 | "supports-color": "^8.0.0" 1287 | }, 1288 | "engines": { 1289 | "node": ">= 10.13.0" 1290 | } 1291 | }, 1292 | "node_modules/jest-worker/node_modules/supports-color": { 1293 | "version": "8.1.1", 1294 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", 1295 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", 1296 | "dev": true, 1297 | "dependencies": { 1298 | "has-flag": "^4.0.0" 1299 | }, 1300 | "engines": { 1301 | "node": ">=10" 1302 | }, 1303 | "funding": { 1304 | "url": "https://github.com/chalk/supports-color?sponsor=1" 1305 | } 1306 | }, 1307 | "node_modules/js-tokens": { 1308 | "version": "4.0.0", 1309 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 1310 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 1311 | "dev": true 1312 | }, 1313 | "node_modules/js-yaml": { 1314 | "version": "3.14.1", 1315 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", 1316 | "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", 1317 | "dev": true, 1318 | "dependencies": { 1319 | "argparse": "^1.0.7", 1320 | "esprima": "^4.0.0" 1321 | }, 1322 | "bin": { 1323 | "js-yaml": "bin/js-yaml.js" 1324 | } 1325 | }, 1326 | "node_modules/json-parse-even-better-errors": { 1327 | "version": "2.3.1", 1328 | "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", 1329 | "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", 1330 | "dev": true 1331 | }, 1332 | "node_modules/json-schema-traverse": { 1333 | "version": "0.4.1", 1334 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1335 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1336 | "dev": true 1337 | }, 1338 | "node_modules/json5": { 1339 | "version": "2.2.3", 1340 | "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", 1341 | "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", 1342 | "dev": true, 1343 | "bin": { 1344 | "json5": "lib/cli.js" 1345 | }, 1346 | "engines": { 1347 | "node": ">=6" 1348 | } 1349 | }, 1350 | "node_modules/kind-of": { 1351 | "version": "6.0.3", 1352 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", 1353 | "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", 1354 | "dev": true, 1355 | "engines": { 1356 | "node": ">=0.10.0" 1357 | } 1358 | }, 1359 | "node_modules/listenercount": { 1360 | "version": "1.0.1", 1361 | "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", 1362 | "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", 1363 | "dev": true 1364 | }, 1365 | "node_modules/loader-runner": { 1366 | "version": "4.3.0", 1367 | "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", 1368 | "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", 1369 | "dev": true, 1370 | "engines": { 1371 | "node": ">=6.11.5" 1372 | } 1373 | }, 1374 | "node_modules/loader-utils": { 1375 | "version": "2.0.4", 1376 | "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", 1377 | "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", 1378 | "dev": true, 1379 | "dependencies": { 1380 | "big.js": "^5.2.2", 1381 | "emojis-list": "^3.0.0", 1382 | "json5": "^2.1.2" 1383 | }, 1384 | "engines": { 1385 | "node": ">=8.9.0" 1386 | } 1387 | }, 1388 | "node_modules/locate-path": { 1389 | "version": "5.0.0", 1390 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 1391 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 1392 | "dev": true, 1393 | "dependencies": { 1394 | "p-locate": "^4.1.0" 1395 | }, 1396 | "engines": { 1397 | "node": ">=8" 1398 | } 1399 | }, 1400 | "node_modules/lru-cache": { 1401 | "version": "6.0.0", 1402 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 1403 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 1404 | "dev": true, 1405 | "dependencies": { 1406 | "yallist": "^4.0.0" 1407 | }, 1408 | "engines": { 1409 | "node": ">=10" 1410 | } 1411 | }, 1412 | "node_modules/memory-fs": { 1413 | "version": "0.5.0", 1414 | "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", 1415 | "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", 1416 | "dev": true, 1417 | "dependencies": { 1418 | "errno": "^0.1.3", 1419 | "readable-stream": "^2.0.1" 1420 | }, 1421 | "engines": { 1422 | "node": ">=4.3.0 <5.0.0 || >=5.10" 1423 | } 1424 | }, 1425 | "node_modules/merge-stream": { 1426 | "version": "2.0.0", 1427 | "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", 1428 | "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", 1429 | "dev": true 1430 | }, 1431 | "node_modules/micromatch": { 1432 | "version": "4.0.5", 1433 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", 1434 | "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", 1435 | "dev": true, 1436 | "dependencies": { 1437 | "braces": "^3.0.2", 1438 | "picomatch": "^2.3.1" 1439 | }, 1440 | "engines": { 1441 | "node": ">=8.6" 1442 | } 1443 | }, 1444 | "node_modules/mime-db": { 1445 | "version": "1.52.0", 1446 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 1447 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 1448 | "dev": true, 1449 | "engines": { 1450 | "node": ">= 0.6" 1451 | } 1452 | }, 1453 | "node_modules/mime-types": { 1454 | "version": "2.1.35", 1455 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 1456 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 1457 | "dev": true, 1458 | "dependencies": { 1459 | "mime-db": "1.52.0" 1460 | }, 1461 | "engines": { 1462 | "node": ">= 0.6" 1463 | } 1464 | }, 1465 | "node_modules/minimatch": { 1466 | "version": "3.1.2", 1467 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1468 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1469 | "dev": true, 1470 | "dependencies": { 1471 | "brace-expansion": "^1.1.7" 1472 | }, 1473 | "engines": { 1474 | "node": "*" 1475 | } 1476 | }, 1477 | "node_modules/minimist": { 1478 | "version": "1.2.8", 1479 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 1480 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 1481 | "dev": true, 1482 | "funding": { 1483 | "url": "https://github.com/sponsors/ljharb" 1484 | } 1485 | }, 1486 | "node_modules/mkdirp": { 1487 | "version": "0.5.6", 1488 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", 1489 | "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", 1490 | "dev": true, 1491 | "dependencies": { 1492 | "minimist": "^1.2.6" 1493 | }, 1494 | "bin": { 1495 | "mkdirp": "bin/cmd.js" 1496 | } 1497 | }, 1498 | "node_modules/ms": { 1499 | "version": "2.1.2", 1500 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1501 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1502 | "dev": true 1503 | }, 1504 | "node_modules/neo-async": { 1505 | "version": "2.6.2", 1506 | "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", 1507 | "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", 1508 | "dev": true 1509 | }, 1510 | "node_modules/node-releases": { 1511 | "version": "2.0.13", 1512 | "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", 1513 | "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", 1514 | "dev": true 1515 | }, 1516 | "node_modules/once": { 1517 | "version": "1.4.0", 1518 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1519 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1520 | "dev": true, 1521 | "dependencies": { 1522 | "wrappy": "1" 1523 | } 1524 | }, 1525 | "node_modules/p-limit": { 1526 | "version": "2.3.0", 1527 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 1528 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 1529 | "dev": true, 1530 | "dependencies": { 1531 | "p-try": "^2.0.0" 1532 | }, 1533 | "engines": { 1534 | "node": ">=6" 1535 | }, 1536 | "funding": { 1537 | "url": "https://github.com/sponsors/sindresorhus" 1538 | } 1539 | }, 1540 | "node_modules/p-locate": { 1541 | "version": "4.1.0", 1542 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 1543 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 1544 | "dev": true, 1545 | "dependencies": { 1546 | "p-limit": "^2.2.0" 1547 | }, 1548 | "engines": { 1549 | "node": ">=8" 1550 | } 1551 | }, 1552 | "node_modules/p-try": { 1553 | "version": "2.2.0", 1554 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 1555 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 1556 | "dev": true, 1557 | "engines": { 1558 | "node": ">=6" 1559 | } 1560 | }, 1561 | "node_modules/path-exists": { 1562 | "version": "4.0.0", 1563 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1564 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 1565 | "dev": true, 1566 | "engines": { 1567 | "node": ">=8" 1568 | } 1569 | }, 1570 | "node_modules/path-is-absolute": { 1571 | "version": "1.0.1", 1572 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1573 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 1574 | "dev": true, 1575 | "engines": { 1576 | "node": ">=0.10.0" 1577 | } 1578 | }, 1579 | "node_modules/path-key": { 1580 | "version": "3.1.1", 1581 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1582 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1583 | "dev": true, 1584 | "engines": { 1585 | "node": ">=8" 1586 | } 1587 | }, 1588 | "node_modules/path-parse": { 1589 | "version": "1.0.7", 1590 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 1591 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 1592 | "dev": true 1593 | }, 1594 | "node_modules/php-parser": { 1595 | "version": "3.1.5", 1596 | "resolved": "https://registry.npmjs.org/php-parser/-/php-parser-3.1.5.tgz", 1597 | "integrity": "sha512-jEY2DcbgCm5aclzBdfW86GM6VEIWcSlhTBSHN1qhJguVePlYe28GhwS0yoeLYXpM2K8y6wzLwrbq814n2PHSoQ==" 1598 | }, 1599 | "node_modules/picocolors": { 1600 | "version": "1.0.0", 1601 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 1602 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 1603 | "dev": true 1604 | }, 1605 | "node_modules/picomatch": { 1606 | "version": "2.3.1", 1607 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1608 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1609 | "dev": true, 1610 | "engines": { 1611 | "node": ">=8.6" 1612 | }, 1613 | "funding": { 1614 | "url": "https://github.com/sponsors/jonschlinkert" 1615 | } 1616 | }, 1617 | "node_modules/pkg-dir": { 1618 | "version": "4.2.0", 1619 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", 1620 | "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", 1621 | "dev": true, 1622 | "dependencies": { 1623 | "find-up": "^4.0.0" 1624 | }, 1625 | "engines": { 1626 | "node": ">=8" 1627 | } 1628 | }, 1629 | "node_modules/process-nextick-args": { 1630 | "version": "2.0.1", 1631 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 1632 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", 1633 | "dev": true 1634 | }, 1635 | "node_modules/prr": { 1636 | "version": "1.0.1", 1637 | "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", 1638 | "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", 1639 | "dev": true 1640 | }, 1641 | "node_modules/punycode": { 1642 | "version": "2.3.0", 1643 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", 1644 | "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", 1645 | "dev": true, 1646 | "engines": { 1647 | "node": ">=6" 1648 | } 1649 | }, 1650 | "node_modules/randombytes": { 1651 | "version": "2.1.0", 1652 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 1653 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 1654 | "dev": true, 1655 | "dependencies": { 1656 | "safe-buffer": "^5.1.0" 1657 | } 1658 | }, 1659 | "node_modules/readable-stream": { 1660 | "version": "2.3.8", 1661 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", 1662 | "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", 1663 | "dev": true, 1664 | "dependencies": { 1665 | "core-util-is": "~1.0.0", 1666 | "inherits": "~2.0.3", 1667 | "isarray": "~1.0.0", 1668 | "process-nextick-args": "~2.0.0", 1669 | "safe-buffer": "~5.1.1", 1670 | "string_decoder": "~1.1.1", 1671 | "util-deprecate": "~1.0.1" 1672 | } 1673 | }, 1674 | "node_modules/rechoir": { 1675 | "version": "0.7.1", 1676 | "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", 1677 | "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", 1678 | "dev": true, 1679 | "dependencies": { 1680 | "resolve": "^1.9.0" 1681 | }, 1682 | "engines": { 1683 | "node": ">= 0.10" 1684 | } 1685 | }, 1686 | "node_modules/resolve": { 1687 | "version": "1.22.6", 1688 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", 1689 | "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", 1690 | "dev": true, 1691 | "dependencies": { 1692 | "is-core-module": "^2.13.0", 1693 | "path-parse": "^1.0.7", 1694 | "supports-preserve-symlinks-flag": "^1.0.0" 1695 | }, 1696 | "bin": { 1697 | "resolve": "bin/resolve" 1698 | }, 1699 | "funding": { 1700 | "url": "https://github.com/sponsors/ljharb" 1701 | } 1702 | }, 1703 | "node_modules/resolve-cwd": { 1704 | "version": "3.0.0", 1705 | "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", 1706 | "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", 1707 | "dev": true, 1708 | "dependencies": { 1709 | "resolve-from": "^5.0.0" 1710 | }, 1711 | "engines": { 1712 | "node": ">=8" 1713 | } 1714 | }, 1715 | "node_modules/resolve-from": { 1716 | "version": "5.0.0", 1717 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", 1718 | "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", 1719 | "dev": true, 1720 | "engines": { 1721 | "node": ">=8" 1722 | } 1723 | }, 1724 | "node_modules/rimraf": { 1725 | "version": "3.0.2", 1726 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1727 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1728 | "dev": true, 1729 | "dependencies": { 1730 | "glob": "^7.1.3" 1731 | }, 1732 | "bin": { 1733 | "rimraf": "bin.js" 1734 | }, 1735 | "funding": { 1736 | "url": "https://github.com/sponsors/isaacs" 1737 | } 1738 | }, 1739 | "node_modules/safe-buffer": { 1740 | "version": "5.1.2", 1741 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1742 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 1743 | "dev": true 1744 | }, 1745 | "node_modules/schema-utils": { 1746 | "version": "3.3.0", 1747 | "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", 1748 | "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", 1749 | "dev": true, 1750 | "dependencies": { 1751 | "@types/json-schema": "^7.0.8", 1752 | "ajv": "^6.12.5", 1753 | "ajv-keywords": "^3.5.2" 1754 | }, 1755 | "engines": { 1756 | "node": ">= 10.13.0" 1757 | }, 1758 | "funding": { 1759 | "type": "opencollective", 1760 | "url": "https://opencollective.com/webpack" 1761 | } 1762 | }, 1763 | "node_modules/semver": { 1764 | "version": "7.5.4", 1765 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", 1766 | "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", 1767 | "dev": true, 1768 | "dependencies": { 1769 | "lru-cache": "^6.0.0" 1770 | }, 1771 | "bin": { 1772 | "semver": "bin/semver.js" 1773 | }, 1774 | "engines": { 1775 | "node": ">=10" 1776 | } 1777 | }, 1778 | "node_modules/serialize-javascript": { 1779 | "version": "6.0.1", 1780 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", 1781 | "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", 1782 | "dev": true, 1783 | "dependencies": { 1784 | "randombytes": "^2.1.0" 1785 | } 1786 | }, 1787 | "node_modules/setimmediate": { 1788 | "version": "1.0.5", 1789 | "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", 1790 | "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", 1791 | "dev": true 1792 | }, 1793 | "node_modules/shallow-clone": { 1794 | "version": "3.0.1", 1795 | "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", 1796 | "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", 1797 | "dev": true, 1798 | "dependencies": { 1799 | "kind-of": "^6.0.2" 1800 | }, 1801 | "engines": { 1802 | "node": ">=8" 1803 | } 1804 | }, 1805 | "node_modules/shebang-command": { 1806 | "version": "2.0.0", 1807 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1808 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1809 | "dev": true, 1810 | "dependencies": { 1811 | "shebang-regex": "^3.0.0" 1812 | }, 1813 | "engines": { 1814 | "node": ">=8" 1815 | } 1816 | }, 1817 | "node_modules/shebang-regex": { 1818 | "version": "3.0.0", 1819 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1820 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1821 | "dev": true, 1822 | "engines": { 1823 | "node": ">=8" 1824 | } 1825 | }, 1826 | "node_modules/source-map": { 1827 | "version": "0.6.1", 1828 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1829 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1830 | "dev": true, 1831 | "engines": { 1832 | "node": ">=0.10.0" 1833 | } 1834 | }, 1835 | "node_modules/source-map-support": { 1836 | "version": "0.5.21", 1837 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", 1838 | "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", 1839 | "dev": true, 1840 | "dependencies": { 1841 | "buffer-from": "^1.0.0", 1842 | "source-map": "^0.6.0" 1843 | } 1844 | }, 1845 | "node_modules/sprintf-js": { 1846 | "version": "1.0.3", 1847 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1848 | "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", 1849 | "dev": true 1850 | }, 1851 | "node_modules/string_decoder": { 1852 | "version": "1.1.1", 1853 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1854 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1855 | "dev": true, 1856 | "dependencies": { 1857 | "safe-buffer": "~5.1.0" 1858 | } 1859 | }, 1860 | "node_modules/supports-color": { 1861 | "version": "7.2.0", 1862 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1863 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1864 | "dev": true, 1865 | "dependencies": { 1866 | "has-flag": "^4.0.0" 1867 | }, 1868 | "engines": { 1869 | "node": ">=8" 1870 | } 1871 | }, 1872 | "node_modules/supports-preserve-symlinks-flag": { 1873 | "version": "1.0.0", 1874 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 1875 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 1876 | "dev": true, 1877 | "engines": { 1878 | "node": ">= 0.4" 1879 | }, 1880 | "funding": { 1881 | "url": "https://github.com/sponsors/ljharb" 1882 | } 1883 | }, 1884 | "node_modules/tapable": { 1885 | "version": "1.1.3", 1886 | "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", 1887 | "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", 1888 | "dev": true, 1889 | "engines": { 1890 | "node": ">=6" 1891 | } 1892 | }, 1893 | "node_modules/terser": { 1894 | "version": "5.21.0", 1895 | "resolved": "https://registry.npmjs.org/terser/-/terser-5.21.0.tgz", 1896 | "integrity": "sha512-WtnFKrxu9kaoXuiZFSGrcAvvBqAdmKx0SFNmVNYdJamMu9yyN3I/QF0FbH4QcqJQ+y1CJnzxGIKH0cSj+FGYRw==", 1897 | "dev": true, 1898 | "dependencies": { 1899 | "@jridgewell/source-map": "^0.3.3", 1900 | "acorn": "^8.8.2", 1901 | "commander": "^2.20.0", 1902 | "source-map-support": "~0.5.20" 1903 | }, 1904 | "bin": { 1905 | "terser": "bin/terser" 1906 | }, 1907 | "engines": { 1908 | "node": ">=10" 1909 | } 1910 | }, 1911 | "node_modules/terser-webpack-plugin": { 1912 | "version": "5.3.9", 1913 | "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", 1914 | "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", 1915 | "dev": true, 1916 | "dependencies": { 1917 | "@jridgewell/trace-mapping": "^0.3.17", 1918 | "jest-worker": "^27.4.5", 1919 | "schema-utils": "^3.1.1", 1920 | "serialize-javascript": "^6.0.1", 1921 | "terser": "^5.16.8" 1922 | }, 1923 | "engines": { 1924 | "node": ">= 10.13.0" 1925 | }, 1926 | "funding": { 1927 | "type": "opencollective", 1928 | "url": "https://opencollective.com/webpack" 1929 | }, 1930 | "peerDependencies": { 1931 | "webpack": "^5.1.0" 1932 | }, 1933 | "peerDependenciesMeta": { 1934 | "@swc/core": { 1935 | "optional": true 1936 | }, 1937 | "esbuild": { 1938 | "optional": true 1939 | }, 1940 | "uglify-js": { 1941 | "optional": true 1942 | } 1943 | } 1944 | }, 1945 | "node_modules/to-regex-range": { 1946 | "version": "5.0.1", 1947 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1948 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1949 | "dev": true, 1950 | "dependencies": { 1951 | "is-number": "^7.0.0" 1952 | }, 1953 | "engines": { 1954 | "node": ">=8.0" 1955 | } 1956 | }, 1957 | "node_modules/traverse": { 1958 | "version": "0.3.9", 1959 | "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", 1960 | "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", 1961 | "dev": true, 1962 | "engines": { 1963 | "node": "*" 1964 | } 1965 | }, 1966 | "node_modules/ts-loader": { 1967 | "version": "8.4.0", 1968 | "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.4.0.tgz", 1969 | "integrity": "sha512-6nFY3IZ2//mrPc+ImY3hNWx1vCHyEhl6V+wLmL4CZcm6g1CqX7UKrkc6y0i4FwcfOhxyMPCfaEvh20f4r9GNpw==", 1970 | "dev": true, 1971 | "dependencies": { 1972 | "chalk": "^4.1.0", 1973 | "enhanced-resolve": "^4.0.0", 1974 | "loader-utils": "^2.0.0", 1975 | "micromatch": "^4.0.0", 1976 | "semver": "^7.3.4" 1977 | }, 1978 | "engines": { 1979 | "node": ">=10.0.0" 1980 | }, 1981 | "peerDependencies": { 1982 | "typescript": "*", 1983 | "webpack": "*" 1984 | } 1985 | }, 1986 | "node_modules/tslib": { 1987 | "version": "1.14.1", 1988 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", 1989 | "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", 1990 | "dev": true 1991 | }, 1992 | "node_modules/tslint": { 1993 | "version": "6.1.3", 1994 | "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", 1995 | "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", 1996 | "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", 1997 | "dev": true, 1998 | "dependencies": { 1999 | "@babel/code-frame": "^7.0.0", 2000 | "builtin-modules": "^1.1.1", 2001 | "chalk": "^2.3.0", 2002 | "commander": "^2.12.1", 2003 | "diff": "^4.0.1", 2004 | "glob": "^7.1.1", 2005 | "js-yaml": "^3.13.1", 2006 | "minimatch": "^3.0.4", 2007 | "mkdirp": "^0.5.3", 2008 | "resolve": "^1.3.2", 2009 | "semver": "^5.3.0", 2010 | "tslib": "^1.13.0", 2011 | "tsutils": "^2.29.0" 2012 | }, 2013 | "bin": { 2014 | "tslint": "bin/tslint" 2015 | }, 2016 | "engines": { 2017 | "node": ">=4.8.0" 2018 | }, 2019 | "peerDependencies": { 2020 | "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" 2021 | } 2022 | }, 2023 | "node_modules/tslint/node_modules/ansi-styles": { 2024 | "version": "3.2.1", 2025 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 2026 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 2027 | "dev": true, 2028 | "dependencies": { 2029 | "color-convert": "^1.9.0" 2030 | }, 2031 | "engines": { 2032 | "node": ">=4" 2033 | } 2034 | }, 2035 | "node_modules/tslint/node_modules/chalk": { 2036 | "version": "2.4.2", 2037 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 2038 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 2039 | "dev": true, 2040 | "dependencies": { 2041 | "ansi-styles": "^3.2.1", 2042 | "escape-string-regexp": "^1.0.5", 2043 | "supports-color": "^5.3.0" 2044 | }, 2045 | "engines": { 2046 | "node": ">=4" 2047 | } 2048 | }, 2049 | "node_modules/tslint/node_modules/color-convert": { 2050 | "version": "1.9.3", 2051 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 2052 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 2053 | "dev": true, 2054 | "dependencies": { 2055 | "color-name": "1.1.3" 2056 | } 2057 | }, 2058 | "node_modules/tslint/node_modules/color-name": { 2059 | "version": "1.1.3", 2060 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 2061 | "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", 2062 | "dev": true 2063 | }, 2064 | "node_modules/tslint/node_modules/has-flag": { 2065 | "version": "3.0.0", 2066 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 2067 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 2068 | "dev": true, 2069 | "engines": { 2070 | "node": ">=4" 2071 | } 2072 | }, 2073 | "node_modules/tslint/node_modules/semver": { 2074 | "version": "5.7.2", 2075 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", 2076 | "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", 2077 | "dev": true, 2078 | "bin": { 2079 | "semver": "bin/semver" 2080 | } 2081 | }, 2082 | "node_modules/tslint/node_modules/supports-color": { 2083 | "version": "5.5.0", 2084 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 2085 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 2086 | "dev": true, 2087 | "dependencies": { 2088 | "has-flag": "^3.0.0" 2089 | }, 2090 | "engines": { 2091 | "node": ">=4" 2092 | } 2093 | }, 2094 | "node_modules/tsutils": { 2095 | "version": "2.29.0", 2096 | "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", 2097 | "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", 2098 | "dev": true, 2099 | "dependencies": { 2100 | "tslib": "^1.8.1" 2101 | }, 2102 | "peerDependencies": { 2103 | "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" 2104 | } 2105 | }, 2106 | "node_modules/typescript": { 2107 | "version": "4.9.5", 2108 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", 2109 | "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", 2110 | "dev": true, 2111 | "bin": { 2112 | "tsc": "bin/tsc", 2113 | "tsserver": "bin/tsserver" 2114 | }, 2115 | "engines": { 2116 | "node": ">=4.2.0" 2117 | } 2118 | }, 2119 | "node_modules/unzipper": { 2120 | "version": "0.10.14", 2121 | "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz", 2122 | "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==", 2123 | "dev": true, 2124 | "dependencies": { 2125 | "big-integer": "^1.6.17", 2126 | "binary": "~0.3.0", 2127 | "bluebird": "~3.4.1", 2128 | "buffer-indexof-polyfill": "~1.0.0", 2129 | "duplexer2": "~0.1.4", 2130 | "fstream": "^1.0.12", 2131 | "graceful-fs": "^4.2.2", 2132 | "listenercount": "~1.0.1", 2133 | "readable-stream": "~2.3.6", 2134 | "setimmediate": "~1.0.4" 2135 | } 2136 | }, 2137 | "node_modules/update-browserslist-db": { 2138 | "version": "1.0.13", 2139 | "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", 2140 | "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", 2141 | "dev": true, 2142 | "funding": [ 2143 | { 2144 | "type": "opencollective", 2145 | "url": "https://opencollective.com/browserslist" 2146 | }, 2147 | { 2148 | "type": "tidelift", 2149 | "url": "https://tidelift.com/funding/github/npm/browserslist" 2150 | }, 2151 | { 2152 | "type": "github", 2153 | "url": "https://github.com/sponsors/ai" 2154 | } 2155 | ], 2156 | "dependencies": { 2157 | "escalade": "^3.1.1", 2158 | "picocolors": "^1.0.0" 2159 | }, 2160 | "bin": { 2161 | "update-browserslist-db": "cli.js" 2162 | }, 2163 | "peerDependencies": { 2164 | "browserslist": ">= 4.21.0" 2165 | } 2166 | }, 2167 | "node_modules/uri-js": { 2168 | "version": "4.4.1", 2169 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 2170 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 2171 | "dev": true, 2172 | "dependencies": { 2173 | "punycode": "^2.1.0" 2174 | } 2175 | }, 2176 | "node_modules/util-deprecate": { 2177 | "version": "1.0.2", 2178 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2179 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", 2180 | "dev": true 2181 | }, 2182 | "node_modules/vscode-test": { 2183 | "version": "1.6.1", 2184 | "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.6.1.tgz", 2185 | "integrity": "sha512-086q88T2ca1k95mUzffvbzb7esqQNvJgiwY4h29ukPhFo8u+vXOOmelUoU5EQUHs3Of8+JuQ3oGdbVCqaxuTXA==", 2186 | "deprecated": "This package has been renamed to @vscode/test-electron, please update to the new name", 2187 | "dev": true, 2188 | "dependencies": { 2189 | "http-proxy-agent": "^4.0.1", 2190 | "https-proxy-agent": "^5.0.0", 2191 | "rimraf": "^3.0.2", 2192 | "unzipper": "^0.10.11" 2193 | }, 2194 | "engines": { 2195 | "node": ">=8.9.3" 2196 | } 2197 | }, 2198 | "node_modules/watchpack": { 2199 | "version": "2.4.0", 2200 | "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", 2201 | "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", 2202 | "dev": true, 2203 | "dependencies": { 2204 | "glob-to-regexp": "^0.4.1", 2205 | "graceful-fs": "^4.1.2" 2206 | }, 2207 | "engines": { 2208 | "node": ">=10.13.0" 2209 | } 2210 | }, 2211 | "node_modules/webpack": { 2212 | "version": "5.88.2", 2213 | "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", 2214 | "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", 2215 | "dev": true, 2216 | "dependencies": { 2217 | "@types/eslint-scope": "^3.7.3", 2218 | "@types/estree": "^1.0.0", 2219 | "@webassemblyjs/ast": "^1.11.5", 2220 | "@webassemblyjs/wasm-edit": "^1.11.5", 2221 | "@webassemblyjs/wasm-parser": "^1.11.5", 2222 | "acorn": "^8.7.1", 2223 | "acorn-import-assertions": "^1.9.0", 2224 | "browserslist": "^4.14.5", 2225 | "chrome-trace-event": "^1.0.2", 2226 | "enhanced-resolve": "^5.15.0", 2227 | "es-module-lexer": "^1.2.1", 2228 | "eslint-scope": "5.1.1", 2229 | "events": "^3.2.0", 2230 | "glob-to-regexp": "^0.4.1", 2231 | "graceful-fs": "^4.2.9", 2232 | "json-parse-even-better-errors": "^2.3.1", 2233 | "loader-runner": "^4.2.0", 2234 | "mime-types": "^2.1.27", 2235 | "neo-async": "^2.6.2", 2236 | "schema-utils": "^3.2.0", 2237 | "tapable": "^2.1.1", 2238 | "terser-webpack-plugin": "^5.3.7", 2239 | "watchpack": "^2.4.0", 2240 | "webpack-sources": "^3.2.3" 2241 | }, 2242 | "bin": { 2243 | "webpack": "bin/webpack.js" 2244 | }, 2245 | "engines": { 2246 | "node": ">=10.13.0" 2247 | }, 2248 | "funding": { 2249 | "type": "opencollective", 2250 | "url": "https://opencollective.com/webpack" 2251 | }, 2252 | "peerDependenciesMeta": { 2253 | "webpack-cli": { 2254 | "optional": true 2255 | } 2256 | } 2257 | }, 2258 | "node_modules/webpack-cli": { 2259 | "version": "4.10.0", 2260 | "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz", 2261 | "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", 2262 | "dev": true, 2263 | "dependencies": { 2264 | "@discoveryjs/json-ext": "^0.5.0", 2265 | "@webpack-cli/configtest": "^1.2.0", 2266 | "@webpack-cli/info": "^1.5.0", 2267 | "@webpack-cli/serve": "^1.7.0", 2268 | "colorette": "^2.0.14", 2269 | "commander": "^7.0.0", 2270 | "cross-spawn": "^7.0.3", 2271 | "fastest-levenshtein": "^1.0.12", 2272 | "import-local": "^3.0.2", 2273 | "interpret": "^2.2.0", 2274 | "rechoir": "^0.7.0", 2275 | "webpack-merge": "^5.7.3" 2276 | }, 2277 | "bin": { 2278 | "webpack-cli": "bin/cli.js" 2279 | }, 2280 | "engines": { 2281 | "node": ">=10.13.0" 2282 | }, 2283 | "funding": { 2284 | "type": "opencollective", 2285 | "url": "https://opencollective.com/webpack" 2286 | }, 2287 | "peerDependencies": { 2288 | "webpack": "4.x.x || 5.x.x" 2289 | }, 2290 | "peerDependenciesMeta": { 2291 | "@webpack-cli/generators": { 2292 | "optional": true 2293 | }, 2294 | "@webpack-cli/migrate": { 2295 | "optional": true 2296 | }, 2297 | "webpack-bundle-analyzer": { 2298 | "optional": true 2299 | }, 2300 | "webpack-dev-server": { 2301 | "optional": true 2302 | } 2303 | } 2304 | }, 2305 | "node_modules/webpack-cli/node_modules/commander": { 2306 | "version": "7.2.0", 2307 | "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", 2308 | "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", 2309 | "dev": true, 2310 | "engines": { 2311 | "node": ">= 10" 2312 | } 2313 | }, 2314 | "node_modules/webpack-merge": { 2315 | "version": "5.9.0", 2316 | "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz", 2317 | "integrity": "sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==", 2318 | "dev": true, 2319 | "dependencies": { 2320 | "clone-deep": "^4.0.1", 2321 | "wildcard": "^2.0.0" 2322 | }, 2323 | "engines": { 2324 | "node": ">=10.0.0" 2325 | } 2326 | }, 2327 | "node_modules/webpack-sources": { 2328 | "version": "3.2.3", 2329 | "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", 2330 | "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", 2331 | "dev": true, 2332 | "engines": { 2333 | "node": ">=10.13.0" 2334 | } 2335 | }, 2336 | "node_modules/webpack/node_modules/enhanced-resolve": { 2337 | "version": "5.15.0", 2338 | "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", 2339 | "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", 2340 | "dev": true, 2341 | "dependencies": { 2342 | "graceful-fs": "^4.2.4", 2343 | "tapable": "^2.2.0" 2344 | }, 2345 | "engines": { 2346 | "node": ">=10.13.0" 2347 | } 2348 | }, 2349 | "node_modules/webpack/node_modules/tapable": { 2350 | "version": "2.2.1", 2351 | "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", 2352 | "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", 2353 | "dev": true, 2354 | "engines": { 2355 | "node": ">=6" 2356 | } 2357 | }, 2358 | "node_modules/which": { 2359 | "version": "2.0.2", 2360 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2361 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2362 | "dev": true, 2363 | "dependencies": { 2364 | "isexe": "^2.0.0" 2365 | }, 2366 | "bin": { 2367 | "node-which": "bin/node-which" 2368 | }, 2369 | "engines": { 2370 | "node": ">= 8" 2371 | } 2372 | }, 2373 | "node_modules/wildcard": { 2374 | "version": "2.0.1", 2375 | "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", 2376 | "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", 2377 | "dev": true 2378 | }, 2379 | "node_modules/wrappy": { 2380 | "version": "1.0.2", 2381 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2382 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 2383 | "dev": true 2384 | }, 2385 | "node_modules/yallist": { 2386 | "version": "4.0.0", 2387 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 2388 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 2389 | "dev": true 2390 | } 2391 | } 2392 | } 2393 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laravel-extra-intellisense", 3 | "displayName": "Laravel Extra Intellisense", 4 | "description": "better intellisense for laravel projects.", 5 | "version": "0.7.2", 6 | "publisher": "amiralizadeh9480", 7 | "icon": "images/icon.png", 8 | "engines": { 9 | "vscode": "^1.83.0" 10 | }, 11 | "categories": [ 12 | "Languages" 13 | ], 14 | "activationEvents": [ 15 | "onLanguage:php", 16 | "onLanguage:blade" 17 | ], 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/amir9480/vscode-laravel-extra-intellisense" 21 | }, 22 | "main": "./dist/extension.js", 23 | "contributes": { 24 | "configuration": [ 25 | { 26 | "title": "Laravel Extra Intellisense", 27 | "type": "object", 28 | "properties": { 29 | "LaravelExtraIntellisense.customValidationRules": { 30 | "type": "object", 31 | "default": {}, 32 | "description": "Custom validation rules snippets." 33 | }, 34 | "LaravelExtraIntellisense.viewDirectorySeparator": { 35 | "type": "string", 36 | "default": ".", 37 | "description": ". or /" 38 | }, 39 | "LaravelExtraIntellisense.phpCommand": { 40 | "type": "string", 41 | "default": "php -r \"{code}\"", 42 | "description": "PHP Command using to run PHP codes" 43 | }, 44 | "LaravelExtraIntellisense.basePath": { 45 | "type": "string", 46 | "description": "Base path using to read files." 47 | }, 48 | "LaravelExtraIntellisense.basePathForCode": { 49 | "type": "string", 50 | "description": "This base path using for require_once inside PHP code." 51 | }, 52 | "LaravelExtraIntellisense.modelsPaths": { 53 | "type": "array", 54 | "default": [ 55 | "app", 56 | "app/Models" 57 | ], 58 | "description": "Path of models you put your model codes." 59 | }, 60 | "LaravelExtraIntellisense.modelVariables": { 61 | "type": "object", 62 | "default": { 63 | "user": "App\\Models\\User" 64 | }, 65 | "description": "Variables that should provide model autocomplete." 66 | }, 67 | "LaravelExtraIntellisense.modelAttributeCase": { 68 | "type": "string", 69 | "enum": [ 70 | "default", 71 | "snake", 72 | "camel" 73 | ], 74 | "default": "default", 75 | "description": "Change attribute name case to snake or camel." 76 | }, 77 | "LaravelExtraIntellisense.modelAccessorCase": { 78 | "type": "string", 79 | "enum": [ 80 | "default", 81 | "snake", 82 | "camel" 83 | ], 84 | "default": "snake", 85 | "description": "Change accessor name case to snake or camel." 86 | }, 87 | "LaravelExtraIntellisense.disableBlade": { 88 | "type": "boolean", 89 | "default": false, 90 | "description": "If you want to disable blade directives autocomplete set this to true." 91 | }, 92 | "LaravelExtraIntellisense.disableAuth": { 93 | "type": "boolean", 94 | "default": false, 95 | "description": "If you want to disable authorization autocomplete set this to true." 96 | }, 97 | "LaravelExtraIntellisense.disableErrorAlert": { 98 | "type": "boolean", 99 | "default": false, 100 | "description": "Hide error alerts when extension can't get data from your application." 101 | } 102 | } 103 | } 104 | ] 105 | }, 106 | "scripts": { 107 | "vscode:prepublish": "webpack --mode production", 108 | "compile": "webpack --mode development", 109 | "watch": "webpack --mode development --watch", 110 | "test": "tsc -p ./", 111 | "lint": "eslint . --ext .ts,.tsx" 112 | }, 113 | "dependencies": { 114 | "php-parser": "^3.0.2" 115 | }, 116 | "devDependencies": { 117 | "@types/mocha": "^8.2.1", 118 | "@types/node": "^14.14.31", 119 | "@types/vscode": "^1.83.0", 120 | "ts-loader": "^8.0.17", 121 | "tslint": "^6.1.3", 122 | "typescript": "^4.2.2", 123 | "vscode-test": "^1.6.1", 124 | "webpack": "^5.24.2", 125 | "webpack-cli": "^4.5.0" 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/AssetProvider.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import * as vscode from 'vscode'; 4 | import * as fs from 'fs'; 5 | import Helpers from './helpers'; 6 | 7 | 8 | export default class AssetProvider implements vscode.CompletionItemProvider { 9 | private publicFiles: Array = []; 10 | private timer: any = null; 11 | private watcher: any = null; 12 | 13 | constructor () { 14 | this.loadFiles(); 15 | if (vscode.workspace.workspaceFolders !== undefined) { 16 | this.watcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], "public/**/*")); 17 | this.watcher.onDidChange((e: vscode.Uri) => this.onChange()); 18 | this.watcher.onDidCreate((e: vscode.Uri) => this.onChange()); 19 | this.watcher.onDidDelete((e: vscode.Uri) => this.onChange()); 20 | } 21 | } 22 | 23 | provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Array { 24 | var out:Array = []; 25 | var func = Helpers.parseDocumentFunction(document, position); 26 | if (func === null) { 27 | return out; 28 | } 29 | 30 | if (func && (Helpers.tags.asset.functions.some((fn:string) => func.function.includes(fn)))) { 31 | for (var i in this.publicFiles) { 32 | var completeItem = new vscode.CompletionItem(this.publicFiles[i], vscode.CompletionItemKind.Constant); 33 | completeItem.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 34 | out.push(completeItem); 35 | } 36 | } 37 | 38 | return out; 39 | } 40 | 41 | onChange() { 42 | var self = this; 43 | if (self.timer !== null) { 44 | clearTimeout(self.timer); 45 | } 46 | self.timer = setTimeout(function () { 47 | self.loadFiles(); 48 | self.timer = null; 49 | }, 2000); 50 | } 51 | 52 | loadFiles() { 53 | this.publicFiles = this.getFiles().map((path) => path.replace(/\/?public\/?/g, "")); 54 | } 55 | 56 | getFiles(scanPath: string = "public", depth: number = 0) { 57 | let out: Array = []; 58 | try { 59 | let projectScanPath = Helpers.projectPath(scanPath); 60 | if (depth <= 10 && fs.existsSync(projectScanPath)) { 61 | for (let filePath of fs.readdirSync(projectScanPath)) { 62 | let fullFilePath = projectScanPath + "/" + filePath; 63 | if (fs.lstatSync(fullFilePath).isDirectory()) { 64 | out = out.concat(this.getFiles(scanPath + "/" + filePath, depth + 1)); 65 | } else if (fs.lstatSync(fullFilePath).isFile()) { 66 | if (filePath[0] != '.' && filePath.endsWith(".php") == false) { 67 | out.push(scanPath + "/" + filePath); 68 | } 69 | } 70 | } 71 | } 72 | } catch (exception) { 73 | console.error(exception); 74 | } 75 | 76 | return out; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/AuthProvider.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import * as vscode from 'vscode'; 4 | import Helpers from './helpers'; 5 | 6 | 7 | export default class AuthProvider implements vscode.CompletionItemProvider { 8 | private abilities: Array = []; 9 | private models: Array = []; 10 | 11 | constructor () { 12 | var self = this; 13 | if (vscode.workspace.getConfiguration("LaravelExtraIntellisense").get('disableAuth', false)) { 14 | return; 15 | } 16 | self.loadAbilities(); 17 | setInterval(function () { 18 | self.loadAbilities(); 19 | }, 60000); 20 | } 21 | 22 | provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Array { 23 | var out:Array = []; 24 | var func = Helpers.parseDocumentFunction(document, position); 25 | if (func === null) { 26 | return out; 27 | } 28 | 29 | if (func && ((func.class && Helpers.tags.auth.classes.some((cls:string) => func.class.includes(cls))) || Helpers.tags.auth.functions.some((fn:string) => func.function.includes(fn)))) { 30 | if (func.paramIndex === 1) { 31 | for (let i in this.models) { 32 | let completeItem = new vscode.CompletionItem(this.models[i].replace(/\\/, '\\\\'), vscode.CompletionItemKind.Value); 33 | completeItem.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 34 | out.push(completeItem); 35 | } 36 | } else { 37 | for (let i in this.abilities) { 38 | let completeItem = new vscode.CompletionItem(this.abilities[i], vscode.CompletionItemKind.Value); 39 | completeItem.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 40 | out.push(completeItem); 41 | } 42 | } 43 | } 44 | return out; 45 | } 46 | 47 | loadAbilities() { 48 | try { 49 | var self = this; 50 | Helpers.getModels().then((models) => self.models = models); 51 | Helpers.runLaravel(` 52 | echo json_encode( 53 | array_merge( 54 | array_keys(Illuminate\\Support\\Facades\\Gate::abilities()), 55 | array_values( 56 | array_filter( 57 | array_unique( 58 | Illuminate\\Support\\Arr::flatten( 59 | array_map( 60 | function ($val, $key) { 61 | return array_map( 62 | function ($rm) { 63 | return $rm->getName(); 64 | }, 65 | (new ReflectionClass($val))->getMethods() 66 | ); 67 | }, 68 | Illuminate\\Support\\Facades\\Gate::policies(), 69 | array_keys(Illuminate\\Support\\Facades\\Gate::policies()) 70 | ) 71 | ) 72 | ), 73 | function ($an) {return !in_array($an, ['allow', 'deny']);} 74 | ) 75 | ) 76 | ) 77 | ); 78 | `, 'Auth Data' 79 | ).then(function (result) { 80 | var abilities = JSON.parse(result); 81 | self.abilities = abilities; 82 | }); 83 | } catch (exception) { 84 | console.error(exception); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/BladeProvider.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import * as vscode from 'vscode'; 4 | import Helpers from './helpers'; 5 | 6 | 7 | export default class BladeProvider implements vscode.CompletionItemProvider { 8 | private customDirectives: Array = []; 9 | 10 | constructor () { 11 | var self = this; 12 | self.loadCustomDirectives(); 13 | setInterval(() => self.loadCustomDirectives(), 600000); 14 | } 15 | 16 | provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Array { 17 | let isBlade = document.languageId == 'blade' || document.languageId == 'laravel-blade' || document.fileName.endsWith('.blade.php'); 18 | if (vscode.workspace.getConfiguration("LaravelExtraIntellisense").get('disableBlade', false) || isBlade === false) { 19 | return []; 20 | } 21 | var out:Array = this.getDefaultDirectives(document, position); 22 | 23 | for (var i in this.customDirectives) { 24 | var completeItem = new vscode.CompletionItem('@' + this.customDirectives[i].name + (this.customDirectives[i].hasParams ? '(...)' : ''), vscode.CompletionItemKind.Keyword); 25 | completeItem.insertText = new vscode.SnippetString('@' + this.customDirectives[i].name + (this.customDirectives[i].hasParams ? '(${1})' : '')); 26 | completeItem.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 27 | out.push(completeItem); 28 | } 29 | return out; 30 | } 31 | 32 | loadCustomDirectives() { 33 | try { 34 | var self = this; 35 | // 36 | Helpers.runLaravel( 37 | "$out = [];" + 38 | "foreach (app(Illuminate\\View\\Compilers\\BladeCompiler::class)->getCustomDirectives() as $name => $customDirective) {" + 39 | " if ($customDirective instanceof \\Closure) {" + 40 | " $out[] = ['name' => $name, 'hasParams' => (new ReflectionFunction($customDirective))->getNumberOfParameters() >= 1];" + 41 | " } elseif (is_array($customDirective)) {" + 42 | " $out[] = ['name' => $name, 'hasParams' => (new ReflectionMethod($customDirective[0], $customDirective[1]))->getNumberOfParameters() >= 1];" + 43 | " }" + 44 | "}" + 45 | "echo json_encode($out);", 46 | "Custom Blade Directives" 47 | ) 48 | .then(function (result) { 49 | var customDirectives = JSON.parse(result); 50 | self.customDirectives = customDirectives; 51 | }); 52 | } catch (exception) { 53 | console.error(exception); 54 | } 55 | } 56 | 57 | getDefaultDirectives(document: vscode.TextDocument, position: vscode.Position): Array { 58 | var snippets : any = { 59 | '@if(...)': new vscode.SnippetString('@if (${1})\n' + Helpers.getSpacer() + '${2}\n' + '@endif'), 60 | '@error(...)': new vscode.SnippetString('@error(${1})\n' + Helpers.getSpacer() + '${2}\n' + '@enderror'), 61 | '@if(...) ... @else ... @endif': new vscode.SnippetString('@if (${1})\n' + Helpers.getSpacer() + '${2}\n' + '@else\n' + Helpers.getSpacer() + '${3}\n' + '@endif'), 62 | '@foreach(...)': new vscode.SnippetString('@foreach (${1} as ${2})\n' + Helpers.getSpacer() + '${3}\n' + '@endforeach'), 63 | '@forelse(...)': new vscode.SnippetString('@forelse (${1} as ${2})\n' + Helpers.getSpacer() + '${3}\n' + '@empty\n' + Helpers.getSpacer() + '${4}\n' + '@endforelse'), 64 | '@for(...)': new vscode.SnippetString('@for (${1})\n' + Helpers.getSpacer() + '${2}\n' + '@endfor'), 65 | '@while(...)': new vscode.SnippetString('@while (${1})\n' + Helpers.getSpacer() + '${2}\n' + '@endwhile'), 66 | '@switch(...)': new vscode.SnippetString('@switch(${1})\n' + Helpers.getSpacer() + '@case(${2})\n' + Helpers.getSpacer().repeat(2) + '${3}\n' + Helpers.getSpacer().repeat(2) + '@break\n\n' + Helpers.getSpacer() + '@default\n' + Helpers.getSpacer().repeat(2) + '${4}\n@endswitch'), 67 | '@case(...)': new vscode.SnippetString('@case(${1})\n' + Helpers.getSpacer() + '${2}\n@break'), 68 | '@break': new vscode.SnippetString('@break'), 69 | '@continue': new vscode.SnippetString('@continue'), 70 | '@break(...)': new vscode.SnippetString('@break(${1})'), 71 | '@continue(...)': new vscode.SnippetString('@continue(${1})'), 72 | '@default': new vscode.SnippetString('@default'), 73 | '@extends(...)': new vscode.SnippetString('@extends(${1})'), 74 | '@empty': new vscode.SnippetString('@empty'), 75 | '@verbatim ...': new vscode.SnippetString('@verbatim\n' + Helpers.getSpacer() + '${2}\n' + '@endverbatim'), 76 | '@json(...)': new vscode.SnippetString('@json(${1})'), 77 | '@elseif (...)': new vscode.SnippetString('@elseif (${1})'), 78 | '@else': new vscode.SnippetString('@else'), 79 | '@unless(...)': new vscode.SnippetString('@unless (${1})\n' + Helpers.getSpacer() + '${2}\n' + '@endunless'), 80 | '@isset(...)': new vscode.SnippetString('@isset(${1})\n' + Helpers.getSpacer() + '${2}\n' + '@endisset'), 81 | '@empty(...)': new vscode.SnippetString('@empty(${1})\n' + Helpers.getSpacer() + '${2}\n' + '@endempty'), 82 | '@auth': new vscode.SnippetString('@auth\n' + Helpers.getSpacer() + '${1}\n' + '@endauth'), 83 | '@guest': new vscode.SnippetString('@guest\n' + Helpers.getSpacer() + '${1}\n' + '@endguest'), 84 | '@auth(...)': new vscode.SnippetString('@auth(${1})\n' + Helpers.getSpacer() + '${2}\n' + '@endauth'), 85 | '@guest(...)': new vscode.SnippetString('@guest(${1})\n' + Helpers.getSpacer() + '${2}\n' + '@endguest'), 86 | '@can(...)': new vscode.SnippetString('@can(${1})\n' + Helpers.getSpacer() + '${2}\n' + '@endcan'), 87 | '@cannot(...)': new vscode.SnippetString('@cannot(${1})\n' + Helpers.getSpacer() + '${2}\n' + '@endcannot'), 88 | '@elsecan(...)': new vscode.SnippetString('@elsecan(${1})'), 89 | '@elsecannot(...)': new vscode.SnippetString('@elsecannot(${1})'), 90 | '@production': new vscode.SnippetString('@production\n' + Helpers.getSpacer() + '${1}\n' + '@endproduction'), 91 | '@env(...)': new vscode.SnippetString('@env(${1})\n' + Helpers.getSpacer() + '${2}\n' + '@endenv'), 92 | '@hasSection(...)': new vscode.SnippetString('@hasSection(${1})\n' + Helpers.getSpacer() + '${2}\n' + '@endif'), 93 | '@sectionMissing(...)': new vscode.SnippetString('@sectionMissing(${1})\n' + Helpers.getSpacer() + '${2}\n' + '@endif'), 94 | '@include(...)': new vscode.SnippetString('@include(${1})'), 95 | '@includeIf(...)': new vscode.SnippetString('@includeIf(${1})'), 96 | '@includeWhen(...)': new vscode.SnippetString('@includeWhen(${1}, ${2})'), 97 | '@includeUnless(...)': new vscode.SnippetString('@includeUnless(${1}, ${2})'), 98 | '@includeFirst(...)': new vscode.SnippetString('@includeFirst(${1})'), 99 | '@each(...)': new vscode.SnippetString('@each(${1}, ${2}, ${3})'), 100 | '@once': new vscode.SnippetString('@production\n' + Helpers.getSpacer() + '${1}\n' + '@endonce'), 101 | '@yield(...)': new vscode.SnippetString('@yield(${1})'), 102 | '@slot(...)': new vscode.SnippetString('@slot(${1})'), 103 | '@stack(...)': new vscode.SnippetString('@stack(${1})'), 104 | '@push(...)': new vscode.SnippetString('@push(${1})\n' + Helpers.getSpacer() + '${2}\n' + '@endpush'), 105 | '@prepend(...)': new vscode.SnippetString('@prepend(${1})\n' + Helpers.getSpacer() + '${2}\n' + '@endprepend'), 106 | '@php': new vscode.SnippetString('@php\n' + Helpers.getSpacer() + '${1}\n' + '@endphp'), 107 | '@component(...)': new vscode.SnippetString('@component(${1})\n' + Helpers.getSpacer() + '${2}\n' + '@endcomponent'), 108 | '@section(...) ... @endsection': new vscode.SnippetString('@section(${1})\n' + Helpers.getSpacer() + '${2}\n' + '@endsection'), 109 | '@section(...)': new vscode.SnippetString('@section(${1})'), 110 | '@props(...)': new vscode.SnippetString('@props(${1})'), 111 | '@show': new vscode.SnippetString('@show'), 112 | '@stop': new vscode.SnippetString('@stop'), 113 | '@parent': new vscode.SnippetString('@parent'), 114 | '@csrf': new vscode.SnippetString('@csrf'), 115 | '@method(...)': new vscode.SnippetString('@method(${1})'), 116 | '@inject(...)': new vscode.SnippetString('@inject(${1}, ${2})'), 117 | '@dump(...)': new vscode.SnippetString('@dump(${1})'), 118 | '@dd(...)': new vscode.SnippetString('@dd(${1})'), 119 | '@lang(...)': new vscode.SnippetString('@lang(${1})'), 120 | 121 | '@endif': new vscode.SnippetString('@endif'), 122 | '@enderror': new vscode.SnippetString('@enderror'), 123 | '@endforeach': new vscode.SnippetString('@endforeach'), 124 | '@endforelse': new vscode.SnippetString('@endforelse'), 125 | '@endfor': new vscode.SnippetString('@endfor'), 126 | '@endwhile': new vscode.SnippetString('@endwhile'), 127 | '@endswitch': new vscode.SnippetString('@endswitch'), 128 | '@endverbatim': new vscode.SnippetString('@endverbatim'), 129 | '@endunless': new vscode.SnippetString('@endunless'), 130 | '@endisset': new vscode.SnippetString('@endisset'), 131 | '@endempty': new vscode.SnippetString('@endempty'), 132 | '@endauth': new vscode.SnippetString('@endauth'), 133 | '@endguest': new vscode.SnippetString('@endguest'), 134 | '@endproduction': new vscode.SnippetString('@endproduction'), 135 | '@endenv': new vscode.SnippetString('@endenv'), 136 | '@endonce': new vscode.SnippetString('@endonce'), 137 | '@endpush': new vscode.SnippetString('@endpush'), 138 | '@endprepend': new vscode.SnippetString('@endprepend'), 139 | '@endphp': new vscode.SnippetString('@endphp'), 140 | '@endcomponent': new vscode.SnippetString('@endcomponent'), 141 | '@endsection': new vscode.SnippetString('@endsection'), 142 | '@endslot': new vscode.SnippetString('@endslot'), 143 | '@endcan': new vscode.SnippetString('@endcan'), 144 | '@endcannot': new vscode.SnippetString('@endcannot'), 145 | }; 146 | 147 | var out:Array = []; 148 | for (let snippet in snippets) { 149 | var completeItem = new vscode.CompletionItem(snippet, vscode.CompletionItemKind.Keyword); 150 | if (snippets[snippet] instanceof vscode.SnippetString) { 151 | completeItem.insertText = snippets[snippet]; 152 | } 153 | completeItem.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 154 | out.push(completeItem); 155 | } 156 | return out; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/ConfigProvider.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import * as vscode from 'vscode'; 4 | import Helpers from './helpers'; 5 | 6 | 7 | export default class ConfigProvider implements vscode.CompletionItemProvider { 8 | private timer: any = null; 9 | private configs: Array = []; 10 | private watcher: any = null; 11 | 12 | constructor () { 13 | var self = this; 14 | self.loadConfigs(); 15 | if (vscode.workspace.workspaceFolders !== undefined) { 16 | this.watcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], "config/{,*,**/*}.php")); 17 | this.watcher.onDidChange((e: vscode.Uri) => this.onChange()); 18 | this.watcher.onDidCreate((e: vscode.Uri) => this.onChange()); 19 | this.watcher.onDidDelete((e: vscode.Uri) => this.onChange()); 20 | } 21 | } 22 | 23 | provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Array { 24 | var out:Array = []; 25 | var func = Helpers.parseDocumentFunction(document, position); 26 | if (func === null) { 27 | return out; 28 | } 29 | 30 | if (func && ((func.class && Helpers.tags.config.classes.some((cls:string) => func.class.includes(cls))) || Helpers.tags.config.functions.some((fn:string) => func.function.includes(fn)))) { 31 | for (var i in this.configs) { 32 | var completeItem = new vscode.CompletionItem(this.configs[i].name, vscode.CompletionItemKind.Value); 33 | completeItem.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 34 | if (this.configs[i].value) { 35 | completeItem.detail = this.configs[i].value.toString(); 36 | } 37 | out.push(completeItem); 38 | } 39 | } 40 | return out; 41 | } 42 | 43 | onChange() { 44 | var self = this; 45 | if (self.timer !== null) { 46 | clearTimeout(self.timer); 47 | } 48 | self.timer = setTimeout(function () { 49 | self.loadConfigs(); 50 | self.timer = null; 51 | }, 5000); 52 | } 53 | 54 | loadConfigs() { 55 | try { 56 | var self = this; 57 | Helpers.runLaravel("echo json_encode(config()->all());", "Configs") 58 | .then(function (result) { 59 | var configs = JSON.parse(result); 60 | self.configs = self.getConfigs(configs); 61 | }); 62 | } catch (exception) { 63 | console.error(exception); 64 | } 65 | } 66 | 67 | getConfigs(conf: any): Array { 68 | var out: Array = []; 69 | for (var i in conf) { 70 | if (conf[i] instanceof Array) { 71 | out.push({name: i, value: 'array(...)'}); 72 | } else if (conf[i] instanceof Object) { 73 | out.push({name: i, value: 'array(...)'}); 74 | out = out.concat(this.getConfigs(conf[i]).map(function (c) { 75 | c.name = i + "." + c.name; 76 | return c; 77 | })); 78 | } else { 79 | out.push({name: i, value: conf[i]}); 80 | } 81 | } 82 | return out; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/EloquentProvider.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import * as vscode from 'vscode'; 4 | import Helpers from './helpers'; 5 | 6 | 7 | export default class EloquentProvider implements vscode.CompletionItemProvider { 8 | private timer: any = null; 9 | private models: {[key:string]: any} = {}; 10 | private watchers: Array = []; 11 | 12 | constructor () { 13 | var self = this; 14 | if (vscode.workspace.workspaceFolders !== undefined) { 15 | for (let modelsPath of vscode.workspace.getConfiguration("LaravelExtraIntellisense").get>('modelsPaths', ['app', 'app/Models']).concat(['database/migrations'])) { 16 | let watcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], modelsPath + '/*.php')); 17 | watcher.onDidChange((e: vscode.Uri) => self.onChange()); 18 | watcher.onDidCreate((e: vscode.Uri) => self.onChange()); 19 | watcher.onDidDelete((e: vscode.Uri) => self.onChange()); 20 | this.watchers.push(watcher); 21 | } 22 | } 23 | self.loadModels(); 24 | } 25 | 26 | provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Array { 27 | var out:Array = []; 28 | var func = Helpers.parseDocumentFunction(document, position); 29 | let sourceCode = document.getText(); 30 | let sourceBeforeCursor = sourceCode.substr(0, document.offsetAt(position)); 31 | var isFactory = sourceBeforeCursor.includes("extends Factory") || sourceBeforeCursor.includes("$factory->define("); 32 | var match = null; 33 | var objectName = ""; 34 | var modelName = ""; 35 | var modelClass = ""; 36 | if (func != null || isFactory) { 37 | if (func) { 38 | let modelNameRegex = /([A-z0-9_\\]+)::[^:;]+$/g; 39 | var namespaceRegex = /namespace\s+(.+);/g; 40 | var namespace = ""; 41 | while ((match = modelNameRegex.exec(sourceBeforeCursor)) !== null) { 42 | modelName = match[1]; 43 | } 44 | if (modelName.length === 0) { 45 | let variableNameRegex = /(\$([A-z0-9_\\]+))->[^;]+$/g; 46 | while ((match = variableNameRegex.exec(sourceBeforeCursor)) !== null) { 47 | objectName = match[2]; 48 | } 49 | if (objectName.length > 0) { 50 | modelNameRegex = new RegExp("\\$" + objectName + "\\s*=\\s*([A-z0-9_\\\\]+)::[^:]", "g"); 51 | while ((match = modelNameRegex.exec(sourceBeforeCursor)) !== null) { 52 | modelName = match[1]; 53 | } 54 | } 55 | } 56 | if ((match = namespaceRegex.exec(sourceBeforeCursor)) !== null) { 57 | namespace = match[1]; 58 | } 59 | modelClass = this.getModelClass(modelName, sourceBeforeCursor); 60 | } else { 61 | var factoryModelClassRegex = /(protected \$model = ([A-Za-z0-9_\\]+)::class;)|(\$factory->define\(\s*([A-Za-z0-9_\\]+)::class)/g 62 | if ((match = factoryModelClassRegex.exec(sourceBeforeCursor)) !== null) { 63 | if (typeof match[4] !== 'undefined') { // Laravel 7 < 64 | modelName = match[4]; 65 | } else { // Laravel >= 8 66 | modelName = match[2]; 67 | } 68 | } 69 | modelClass = this.getModelClass(modelName, sourceBeforeCursor); 70 | } 71 | 72 | if (typeof this.models[modelClass] !== 'undefined') { 73 | if (func && Helpers.relationMethods.some((fn:string) => func.function.includes(fn))) { 74 | out = out.concat(this.getCompletionItems(document, position, this.models[modelClass].relations)); 75 | } else { 76 | out = out.concat(this.getCompletionItems(document, position, this.models[modelClass].attributes)); 77 | } 78 | } 79 | } else { 80 | let isArrayObject = false; 81 | let objectRegex = /(\$?([A-z0-9_\[\]]+)|(Auth::user\(\)))\-\>[A-z0-9_]*$/g; 82 | while ((match = objectRegex.exec(sourceBeforeCursor)) !== null) { 83 | objectName = typeof match[2] !== 'undefined' ? match[2] : match[3]; 84 | } 85 | if (objectName.match(/\$?[A-z0-9_]+\[.+\].*$/g)) { 86 | isArrayObject = true; 87 | objectName = objectName.replace(/\[.+\].*$/g, ''); 88 | } 89 | if (objectName.length > 0 && objectName != 'Auth::user()') { 90 | let modelNameRegex = new RegExp("\\$" + objectName + "\\s*=\\s*([A-z0-9_\\\\]+)::[^:;]", "g"); 91 | while ((match = modelNameRegex.exec(sourceBeforeCursor)) !== null) { 92 | modelName = match[1]; 93 | } 94 | modelClass = this.getModelClass(modelName, sourceBeforeCursor); 95 | } 96 | if (modelClass == 'Auth' || objectName == 'Auth::user()') { 97 | if (typeof this.models['App\\User'] !== 'undefined') { 98 | out = out.concat(this.getModelAttributesCompletionItems(document, position, 'App\\User')); 99 | } else if (typeof this.models['App\\Models\\User'] !== 'undefined') { 100 | out = out.concat(this.getModelAttributesCompletionItems(document, position, 'App\\Models\\User')); 101 | } 102 | } 103 | let customVariables = vscode.workspace.getConfiguration("LaravelExtraIntellisense").get('modelVariables', {}); 104 | for (let customVariable in customVariables) { 105 | if (customVariable === objectName && typeof this.models[customVariables[customVariable]] !== 'undefined') { 106 | out = out.concat(this.getModelAttributesCompletionItems(document, position, customVariables[customVariable])); 107 | } 108 | } 109 | for (let i in this.models) { 110 | if (i == modelClass || 111 | (this.models[i].camelCase == objectName || this.models[i].snakeCase == objectName) || 112 | (isArrayObject == true && (this.models[i].pluralCamelCase == objectName || this.models[i].pluralSnakeCase == objectName)) 113 | ) { 114 | out = out.concat(this.getModelAttributesCompletionItems(document, position, i)); 115 | } 116 | } 117 | } 118 | out = out.filter((v, i, a) => a.map((ai) => ai.label).indexOf(v.label) === i); // Remove duplicate items 119 | return out; 120 | } 121 | 122 | getModelClass(modelName: string, sourceBeforeCursor: string) { 123 | let match = null; 124 | let modelClass = ""; 125 | if (modelName.length === 0) { 126 | return ""; 127 | } 128 | var modelClassRegex = new RegExp("use (.+)" + modelName + ";", "g"); 129 | if (modelName.substr(0, 1) === '\\') { 130 | modelClass = modelName.substr(1); 131 | } else if ((match = modelClassRegex.exec(sourceBeforeCursor)) !== null) { 132 | modelClass = match[1] + modelName; 133 | } else { 134 | modelClass = modelName; 135 | } 136 | return modelClass; 137 | } 138 | 139 | getModelAttributesCompletionItems(document: vscode.TextDocument, position: vscode.Position, modelClass: string) : Array { 140 | let out: Array = []; 141 | if (typeof this.models[modelClass] !== 'undefined') { 142 | out = out.concat(this.getCompletionItems(document, position, this.models[modelClass].attributes.map((attr: any) => attr[vscode.workspace.getConfiguration("LaravelExtraIntellisense").get('modelAttributeCase', 'default')]))); 143 | out = out.concat(this.getCompletionItems(document, position, this.models[modelClass].accessors.map((attr: any) => attr[vscode.workspace.getConfiguration("LaravelExtraIntellisense").get('modelAccessorCase', 'snake')]), vscode.CompletionItemKind.Constant)); 144 | out = out.concat(this.getCompletionItems(document, position, this.models[modelClass].relations, vscode.CompletionItemKind.Value)); 145 | } 146 | return out; 147 | } 148 | 149 | getCompletionItems(document: vscode.TextDocument, position: vscode.Position, items: Array, type: vscode.CompletionItemKind = vscode.CompletionItemKind.Property) : Array { 150 | let out: Array = []; 151 | for (let item of items) { 152 | var completeItem = new vscode.CompletionItem(item, type); 153 | completeItem.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 154 | out.push(completeItem); 155 | } 156 | return out; 157 | } 158 | 159 | onChange() { 160 | var self = this; 161 | if (self.timer !== null) { 162 | clearTimeout(self.timer); 163 | } 164 | self.timer = setTimeout(function () { 165 | self.loadModels(); 166 | self.timer = null; 167 | }, 5000); 168 | } 169 | 170 | loadModels() { 171 | var self = this; 172 | try { 173 | Helpers.runLaravel( 174 | "foreach (['" + vscode.workspace.getConfiguration("LaravelExtraIntellisense").get>('modelsPaths', ['app', 'app/Models']).join('\', \'') + "'] as $modelPath) {" + 175 | " if (is_dir(base_path($modelPath))) {" + 176 | " foreach (scandir(base_path($modelPath)) as $sourceFile) {" + 177 | " if (substr($sourceFile, -4) == '.php' && is_file(base_path(\"$modelPath/$sourceFile\"))) {" + 178 | " include_once base_path(\"$modelPath/$sourceFile\");" + 179 | " }" + 180 | " }" + 181 | " }" + 182 | "}" + 183 | "$modelClasses = array_values(array_filter(get_declared_classes(), function ($declaredClass) {" + 184 | " return is_subclass_of($declaredClass, 'Illuminate\\Database\\Eloquent\\Model') && $declaredClass != 'Illuminate\\Database\\Eloquent\\Relations\\Pivot' && $declaredClass != 'Illuminate\\Foundation\\Auth\\User';" + 185 | "}));" + 186 | "$output = [];" + 187 | "foreach ($modelClasses as $modelClass) {" + 188 | " $classReflection = new \\ReflectionClass($modelClass);" + 189 | " $output[$modelClass] = [" + 190 | " 'name' => $classReflection->getShortName()," + 191 | " 'camelCase' => Illuminate\\Support\\Str::camel($classReflection->getShortName())," + 192 | " 'snakeCase' => Illuminate\\Support\\Str::snake($classReflection->getShortName())," + 193 | " 'pluralCamelCase' => Illuminate\\Support\\Str::camel(Illuminate\\Support\\Str::plural($classReflection->getShortName()))," + 194 | " 'pluralSnakeCase' => Illuminate\\Support\\Str::snake(Illuminate\\Support\\Str::plural($classReflection->getShortName()))," + 195 | " 'attributes' => []," + 196 | " 'accessors' => []," + 197 | " 'relations' => []" + 198 | " ];" + 199 | " try {" + 200 | " $modelInstance = $modelClass::first();" + 201 | " $attributes = array_values(array_unique(array_merge(app($modelClass)->getFillable(), array_keys($modelInstance ? $modelInstance->getAttributes() : []))));" + 202 | " $output[$modelClass]['attributes'] = array_map(function ($attribute) {" + 203 | " return ['default' => $attribute, 'snake' => Illuminate\\Support\\Str::snake($attribute), 'camel' => Illuminate\\Support\\Str::camel($attribute)];" + 204 | " }, $attributes);" + 205 | " } catch (\\Throwable $e) {}" + 206 | " foreach ($classReflection->getMethods() as $classMethod) {" + 207 | " try {" + 208 | " if (" + 209 | " $classMethod->isStatic() == false &&" + 210 | " $classMethod->isPublic() == true &&" + 211 | " substr($classMethod->getName(), 0, 3) != 'get' &&" + 212 | " substr($classMethod->getName(), 0, 3) != 'set' &&" + 213 | " count($classMethod->getParameters()) == 0 &&" + 214 | " preg_match('/belongsTo|hasMany|hasOne|morphOne|morphMany|morphTo/', implode('', array_slice(file($classMethod->getFileName()), $classMethod->getStartLine(), $classMethod->getEndLine() - $classMethod->getStartLine() - 1)))" + 215 | " ) {" + 216 | " $output[$modelClass]['relations'][] = $classMethod->getName();" + 217 | " } elseif (" + 218 | " substr($classMethod->getName(), 0, 3) == 'get' && " + 219 | " substr($classMethod->getName(), -9) == 'Attribute' &&" + 220 | " !empty(substr($classMethod->getName(), 3, -9))" + 221 | " ) {" + 222 | " $attributeName = substr($classMethod->getName(), 3, -9);" + 223 | " $output[$modelClass]['accessors'][] = ['default' => $attributeName, 'snake' => Illuminate\\Support\\Str::snake($attributeName), 'camel' => Illuminate\\Support\\Str::camel($attributeName)];" + 224 | " }" + 225 | " } catch (\\Throwable $e) {}" + 226 | " }" + 227 | " sort($output[$modelClass]['attributes']);" + 228 | " sort($output[$modelClass]['relations']);" + 229 | "}" + 230 | "echo json_encode($output);", 231 | "Eloquent Attributes and Relations" 232 | ).then(function (result) { 233 | let models = JSON.parse(result); 234 | self.models = models; 235 | }).catch(function (e) { 236 | console.error(e); 237 | }); 238 | } catch (exception) { 239 | console.error(exception); 240 | } 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /src/EnvProvider.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import * as vscode from 'vscode'; 4 | import * as fs from 'fs'; 5 | import Helpers from './helpers'; 6 | 7 | 8 | export default class EnvProvider implements vscode.CompletionItemProvider { 9 | private enviroments: { [key: string]: string } = {}; 10 | private timer: any = null; 11 | private watcher: any = null; 12 | 13 | constructor () { 14 | this.loadEnv(); 15 | if (vscode.workspace.workspaceFolders !== undefined) { 16 | this.watcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], ".env")); 17 | this.watcher.onDidChange((e: vscode.Uri) => this.onChange()); 18 | this.watcher.onDidCreate((e: vscode.Uri) => this.onChange()); 19 | this.watcher.onDidDelete((e: vscode.Uri) => this.onChange()); 20 | } 21 | } 22 | 23 | provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Array { 24 | var out:Array = []; 25 | var func = Helpers.parseDocumentFunction(document, position); 26 | if (func === null) { 27 | return out; 28 | } 29 | 30 | if (func && (Helpers.tags.env.functions.some((fn:string) => func.function.includes(fn)))) { 31 | for (var i in this.enviroments) { 32 | var completeItem = new vscode.CompletionItem(i, vscode.CompletionItemKind.Constant); 33 | completeItem.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 34 | completeItem.detail = this.enviroments[i]; 35 | out.push(completeItem); 36 | } 37 | } 38 | return out; 39 | } 40 | 41 | onChange() { 42 | var self = this; 43 | if (self.timer !== null) { 44 | clearTimeout(self.timer); 45 | } 46 | self.timer = setTimeout(function () { 47 | self.loadEnv(); 48 | self.timer = null; 49 | }, 5000); 50 | } 51 | 52 | loadEnv() { 53 | try { 54 | if (fs.existsSync(Helpers.projectPath(".env"))) { 55 | let enviroments: any = {}; 56 | let envs = fs.readFileSync(Helpers.projectPath('.env'), 'utf8').split("\n"); 57 | for (let i in envs) { 58 | let envKeyValue = envs[i].split('='); 59 | if (envKeyValue.length == 2) { 60 | enviroments[envKeyValue[0]] = envKeyValue[1]; 61 | } 62 | } 63 | this.enviroments = enviroments; 64 | } 65 | } catch (exception) { 66 | console.error(exception); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/MiddlewareProvider.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import * as vscode from 'vscode'; 4 | import Helpers from './helpers'; 5 | 6 | 7 | export default class MiddlewareProvider implements vscode.CompletionItemProvider { 8 | private timer: any = null; 9 | private middlewares: Array = []; 10 | private watcher: any = null; 11 | 12 | 13 | constructor () { 14 | var self = this; 15 | self.loadMiddlewares(); 16 | if (vscode.workspace.workspaceFolders !== undefined) { 17 | this.watcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], "app/Http/Kernel.php")); 18 | this.watcher.onDidChange((e: vscode.Uri) => this.onChange()); 19 | } 20 | } 21 | 22 | provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Array { 23 | var out:Array = []; 24 | var func = Helpers.parseDocumentFunction(document, position); 25 | if (func === null) { 26 | return out; 27 | } 28 | 29 | if (func.function.includes("middleware")) { 30 | for (let i in this.middlewares) { 31 | var completeItem = new vscode.CompletionItem(i, vscode.CompletionItemKind.Enum); 32 | completeItem.detail = this.middlewares[i]; 33 | completeItem.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 34 | out.push(completeItem); 35 | } 36 | } 37 | return out; 38 | } 39 | 40 | onChange() { 41 | var self = this; 42 | if (self.timer !== null) { 43 | clearTimeout(self.timer); 44 | } 45 | self.timer = setTimeout(function () { 46 | self.loadMiddlewares(); 47 | self.timer = null; 48 | }, 5000); 49 | } 50 | 51 | loadMiddlewares() { 52 | if (vscode.workspace.workspaceFolders instanceof Array && vscode.workspace.workspaceFolders.length > 0) { 53 | try { 54 | var self = this; 55 | // array_map(function ($rh) {return $rh->getName();}, array_filter((new ReflectionMethod('App\Http\Middleware\Authenticate', 'handle'))->getParameters(), function ($rc) {return $rc->getName() != 'request' && $rc->getName() != 'next';})) 56 | Helpers.runLaravel( 57 | "$middlewares = array_merge(app('Illuminate\\Contracts\\Http\\Kernel')->getMiddlewareGroups(), app('Illuminate\\Contracts\\Http\\Kernel')->getRouteMiddleware());" + 58 | "foreach ($middlewares as $key => &$value) {" + 59 | " if (is_array($value)) {" + 60 | " $value = null;" + 61 | " } else {" + 62 | " $parameters = array_filter((new ReflectionMethod($value, 'handle'))->getParameters(), function ($rc) {" + 63 | " return $rc->getName() != 'request' && $rc->getName() != 'next';" + 64 | " });" + 65 | " $value = implode(',', array_map(function ($rh) {" + 66 | " return $rh->getName() . ($rh->isVariadic() ? '...' : '');" + 67 | " }, $parameters));" + 68 | " if (empty($value)) {" + 69 | " $value = null;" + 70 | " }" + 71 | " };" + 72 | "}" + 73 | "echo json_encode($middlewares);", 74 | "Middlewares" 75 | ) 76 | .then(function (result) { 77 | let middlewares = JSON.parse(result); 78 | self.middlewares = middlewares; 79 | }); 80 | } catch (exception) { 81 | console.error(exception); 82 | } 83 | } 84 | } 85 | } 86 | 87 | -------------------------------------------------------------------------------- /src/MixProvider.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import * as vscode from 'vscode'; 4 | import * as fs from 'fs'; 5 | import Helpers from './helpers'; 6 | 7 | 8 | export default class MixProvider implements vscode.CompletionItemProvider { 9 | private mixes: Array = []; 10 | 11 | constructor () { 12 | this.loadMix(); 13 | setInterval(() => this.loadMix(), 60000); 14 | } 15 | 16 | provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Array { 17 | var out:Array = []; 18 | var func = Helpers.parseDocumentFunction(document, position); 19 | if (func === null) { 20 | return out; 21 | } 22 | 23 | if (func && (Helpers.tags.mix.functions.some((fn:string) => func.function.includes(fn)))) { 24 | for (var i in this.mixes) { 25 | var completeItem = new vscode.CompletionItem(this.mixes[i], vscode.CompletionItemKind.Value); 26 | completeItem.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 27 | out.push(completeItem); 28 | } 29 | } 30 | return out; 31 | } 32 | 33 | loadMix() { 34 | try { 35 | if (fs.existsSync(Helpers.projectPath("public/mix-manifest.json"))) { 36 | var mixes = JSON.parse(fs.readFileSync(Helpers.projectPath('public/mix-manifest.json'), 'utf8')); 37 | this.mixes = Object.keys(mixes).map((mixFile) => mixFile.replace(/^\//g, '')); 38 | } 39 | } catch (exception) { 40 | console.error(exception); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/RouteProvider.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import * as vscode from 'vscode'; 4 | import * as fs from 'fs'; 5 | import Helpers from './helpers'; 6 | 7 | 8 | export default class RouteProvider implements vscode.CompletionItemProvider { 9 | private timer: any = null; 10 | private routes: Array = []; 11 | private controllers: Array = []; 12 | private watcher: any = null; 13 | 14 | 15 | constructor () { 16 | var self = this; 17 | self.loadRoutes(); 18 | self.loadControllers(); 19 | if (vscode.workspace.workspaceFolders !== undefined) { 20 | this.watcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], "{,**/}{Controllers,[Rr]oute}{,s}{.php,/*.php,/**/*.php}")); 21 | this.watcher.onDidChange((e: vscode.Uri) => this.onChange()); 22 | this.watcher.onDidCreate((e: vscode.Uri) => this.onChange()); 23 | this.watcher.onDidDelete((e: vscode.Uri) => this.onChange()); 24 | } 25 | } 26 | 27 | provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Array { 28 | var out:Array = []; 29 | var func = Helpers.parseDocumentFunction(document, position); 30 | if (func === null) { 31 | return out; 32 | } 33 | 34 | if (func && ((func.class && Helpers.tags.route.classes.some((cls:string) => func.class.includes(cls))) || Helpers.tags.route.functions.some((fn:string) => func.function.includes(fn)))) { 35 | if (func.class === 'Route' && ['get', 'post', 'put', 'patch', 'delete', 'options', 'any', 'match'].some((fc:string) => func.function.includes(fc))) { 36 | if ((func.function === 'match' && func.paramIndex === 2) || (func.function !== 'match' && func.paramIndex === 1)) { 37 | // Route action autocomplete. 38 | for (let i in this.controllers) { 39 | if (typeof this.controllers[i] === "string" && this.controllers[i].length > 0) { 40 | var completeItem2 = new vscode.CompletionItem(this.controllers[i], vscode.CompletionItemKind.Enum); 41 | completeItem2.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 42 | out.push(completeItem2); 43 | } 44 | } 45 | } 46 | } else if (func.function.includes('middleware') === false) { 47 | if (func.paramIndex === 1) { 48 | // route parameters autocomplete 49 | for (let i in this.routes) { 50 | if (this.routes[i].name === func.parameters[0]) { 51 | for (var j in this.routes[i].parameters) { 52 | var completeItem = new vscode.CompletionItem(this.routes[i].parameters[j], vscode.CompletionItemKind.Variable); 53 | completeItem.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 54 | out.push(completeItem); 55 | } 56 | return out; 57 | } 58 | } 59 | } 60 | 61 | // Route name autocomplete 62 | for (let i in this.routes) { 63 | if (typeof this.routes[i].name === "string" && this.routes[i].name.length > 0) { 64 | var completeItem3 = new vscode.CompletionItem(this.routes[i].name, vscode.CompletionItemKind.Enum); 65 | completeItem3.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 66 | completeItem3.detail = this.routes[i].action + 67 | "\n\n" + 68 | this.routes[i].method + 69 | ":" + 70 | this.routes[i].uri; 71 | out.push(completeItem3); 72 | } 73 | } 74 | } 75 | } 76 | return out; 77 | } 78 | 79 | onChange() { 80 | var self = this; 81 | if (self.timer !== null) { 82 | clearTimeout(self.timer); 83 | } 84 | self.timer = setTimeout(function () { 85 | self.loadRoutes(); 86 | self.loadControllers(); 87 | self.timer = null; 88 | }, 5000); 89 | } 90 | 91 | loadRoutes() { 92 | if (vscode.workspace.workspaceFolders instanceof Array && vscode.workspace.workspaceFolders.length > 0) { 93 | try { 94 | var self = this; 95 | Helpers.runLaravel( 96 | "echo json_encode(array_map(function ($route) {" + 97 | " return ['method' => implode('|', array_filter($route->methods(), function ($method) {" + 98 | " return $method != 'HEAD';" + 99 | " })), 'uri' => $route->uri(), 'name' => $route->getName(), 'action' => str_replace('App\\\\Http\\\\Controllers\\\\', '', $route->getActionName()), 'parameters' => $route->parameterNames()];" + 100 | "}, app('router')->getRoutes()->getRoutes()));", 101 | "HTTP Routes" 102 | ) 103 | .then(function (result) { 104 | var routes = JSON.parse(result); 105 | routes = routes.filter((route: any) => route !== 'null'); 106 | self.routes = routes; 107 | }); 108 | } catch (exception) { 109 | console.error(exception); 110 | } 111 | } 112 | } 113 | 114 | loadControllers() { 115 | try { 116 | this.controllers = this.getControllers(Helpers.projectPath("app/Http/Controllers")).map((contoller) => contoller.replace(/@__invoke/, '')); 117 | this.controllers = this.controllers.filter((v, i, a) => a.indexOf(v) === i); 118 | } catch (exception) { 119 | console.error(exception); 120 | } 121 | } 122 | 123 | getControllers(path: string): Array { 124 | var self = this; 125 | var controllers: Array = []; 126 | if (path.substr(-1) !== '/' && path.substr(-1) !== '\\') { 127 | path += "/"; 128 | } 129 | if (fs.existsSync(path) && fs.lstatSync(path).isDirectory()) { 130 | fs.readdirSync(path).forEach(function (file) { 131 | if (fs.lstatSync(path+file).isDirectory()) { 132 | controllers = controllers.concat(self.getControllers(path + file + "/")); 133 | } else { 134 | if (file.includes(".php")) { 135 | var controllerContent = fs.readFileSync(path + file, 'utf8'); 136 | if (controllerContent.length < 50000) { 137 | var match = ((/class\s+([A-Za-z0-9_]+)\s+extends\s+.+/g).exec(controllerContent)); 138 | var matchNamespace = ((/namespace .+\\Http\\Controllers\\?([A-Za-z0-9_]*)/g).exec(controllerContent)); 139 | var functionRegex = /public\s+function\s+([A-Za-z0-9_]+)\(.*\)/g; 140 | if (match !== null && matchNamespace) { 141 | var className = match[1]; 142 | var namespace = matchNamespace[1]; 143 | while ((match = functionRegex.exec(controllerContent)) !== null && match[1] !== '__construct') { 144 | if (namespace.length > 0) { 145 | controllers.push(namespace + '\\' + className + '@' + match[1]); 146 | } 147 | controllers.push(className + '@' + match[1]); 148 | } 149 | } 150 | } 151 | } 152 | } 153 | }); 154 | } 155 | return controllers; 156 | } 157 | } 158 | 159 | -------------------------------------------------------------------------------- /src/TranslationProvider.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import * as vscode from 'vscode'; 4 | import * as fs from "fs"; 5 | import Helpers from './helpers'; 6 | 7 | 8 | export default class TranslationProvider implements vscode.CompletionItemProvider { 9 | private timer: any = null; 10 | private translations: Array = []; 11 | private watcher: any = null; 12 | 13 | constructor () { 14 | var self = this; 15 | self.loadTranslations(); 16 | if (vscode.workspace.workspaceFolders !== undefined) { 17 | this.watcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], "{,**/}{lang,localization,localizations,trans,translation,translations}/{*,**/*}")); 18 | this.watcher.onDidChange((e: vscode.Uri) => this.onChange()); 19 | this.watcher.onDidCreate((e: vscode.Uri) => this.onChange()); 20 | this.watcher.onDidDelete((e: vscode.Uri) => this.onChange()); 21 | } 22 | } 23 | 24 | provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Array { 25 | var out:Array = []; 26 | var func = Helpers.parseDocumentFunction(document, position); 27 | if (func === null) { 28 | return out; 29 | } 30 | 31 | if (func && ((func.class && Helpers.tags.trans.classes.some((cls:string) => func.class.includes(cls))) || Helpers.tags.trans.functions.some((fn:string) => func.function.includes(fn)))) { 32 | if (func.paramIndex === 1) { 33 | // parameters autocomplete 34 | var paramRegex = /\:([A-Za-z0-9_]+)/g; 35 | var match = null; 36 | 37 | for (let i in this.translations) { 38 | if (this.translations[i].name === func.parameters[0]) { 39 | while ((match = paramRegex.exec(this.translations[i].value)) !== null) { 40 | var completeItem = new vscode.CompletionItem(match[1], vscode.CompletionItemKind.Variable); 41 | completeItem.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 42 | out.push(completeItem); 43 | } 44 | return out; 45 | } 46 | } 47 | return out; 48 | } 49 | 50 | for (let i in this.translations) { 51 | var completeItem = new vscode.CompletionItem(this.translations[i].name, vscode.CompletionItemKind.Value); 52 | completeItem.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 53 | if (this.translations[i].value) { 54 | completeItem.detail = this.translations[i].value.toString(); 55 | } 56 | out.push(completeItem); 57 | } 58 | } 59 | return out; 60 | } 61 | 62 | onChange() { 63 | var self = this; 64 | if (self.timer) { 65 | clearTimeout(self.timer); 66 | } 67 | self.timer = setTimeout(function () { 68 | self.loadTranslations(); 69 | self.timer = null; 70 | }, 5000); 71 | } 72 | 73 | loadTranslations () { 74 | var translations:Array = []; 75 | try { 76 | var self = this; 77 | Helpers.runLaravel("echo json_encode(app('translator')->getLoader()->namespaces());", "Translation namespaces") 78 | .then(async function (result) { 79 | var tranlationNamespaces = JSON.parse(result); 80 | for (let i in tranlationNamespaces) { 81 | tranlationNamespaces[i + '::'] = tranlationNamespaces[i]; 82 | delete tranlationNamespaces[i]; 83 | } 84 | let langPath = JSON.parse(await Helpers.runLaravel('echo json_encode(app()->langPath());', "Translation Path")); 85 | tranlationNamespaces[''] = langPath; 86 | var nestedTranslationGroups = function (basePath:string, relativePath: string = '') : Array { 87 | let path = basePath + '/' + relativePath; 88 | let out: Array = []; 89 | if (fs.existsSync(path) && fs.lstatSync(path).isDirectory()) { 90 | fs.readdirSync(path).forEach(function (file) { 91 | if (fs.lstatSync(path + '/' + file).isFile()) { 92 | out.push(relativePath + '/' + file.replace(/\.php/, '')); 93 | } else if (fs.lstatSync(path + '/' + file).isDirectory()) { 94 | let nestedOut = nestedTranslationGroups(basePath, (relativePath.length > 0 ? relativePath + '/' : '') + file); 95 | for (let nested of nestedOut) { 96 | out.push(nested); 97 | } 98 | } 99 | }); 100 | } 101 | return out; 102 | } 103 | var translationGroups:any = []; 104 | fs.readdirSync(langPath).forEach(function (langDir) { 105 | var path:any = langPath + '/' + langDir; 106 | if (fs.existsSync(path) && fs.lstatSync(path).isDirectory()) { 107 | fs.readdirSync(path).forEach(function (subDirectory) { 108 | let subDirectoryPath = path + '/' + subDirectory; 109 | if (fs.existsSync(subDirectoryPath) && fs.lstatSync(subDirectoryPath).isDirectory()) { 110 | let nestedDirectories = nestedTranslationGroups(path, subDirectory); 111 | for (let nestedDirectory of nestedDirectories) { 112 | translationGroups.push(nestedDirectory); 113 | } 114 | } 115 | }); 116 | } 117 | }); 118 | for (let i in tranlationNamespaces) { 119 | if (fs.existsSync(tranlationNamespaces[i]) && fs.lstatSync(tranlationNamespaces[i]).isDirectory()) { 120 | fs.readdirSync(tranlationNamespaces[i]).forEach(function (langDir) { 121 | var path:any = tranlationNamespaces[i] + '/' + langDir; 122 | if (fs.existsSync(path) && fs.lstatSync(path).isDirectory()) { 123 | fs.readdirSync(path).forEach(function (file) { 124 | if (fs.lstatSync(path + '/' + file).isFile()) { 125 | translationGroups.push(i + file.replace(/\.php/, '')); 126 | } 127 | }); 128 | } 129 | }); 130 | } 131 | } 132 | translationGroups = translationGroups.filter(function(item:any, index:any, array:any){ return array.indexOf(item) === index; }); 133 | Helpers.runLaravel("echo json_encode([" + translationGroups.map((transGroup: string) => "'" + transGroup + "' => __('" + transGroup + "')").join(",") + "]);", "Translations inside namespaces") 134 | .then(function (translationGroupsResult) { 135 | translationGroups = JSON.parse(translationGroupsResult); 136 | for(var i in translationGroups) { 137 | translations = translations.concat(self.getTranslations(translationGroups[i], i)); 138 | } 139 | self.translations = translations; 140 | Helpers.runLaravel("echo json_encode(__('*'));", "Default path Translations") 141 | .then(function (jsontransResult) { 142 | translations = translations.concat(self.getTranslations(JSON.parse(jsontransResult), '').map(function (transInfo) { 143 | transInfo.name = transInfo.name.replace(/^\./, ''); 144 | return transInfo; 145 | })); 146 | self.translations = translations; 147 | }); 148 | }); 149 | }); 150 | } catch (exception) { 151 | console.error(exception); 152 | } 153 | } 154 | 155 | getTranslations(translations: Array, prefix: string): Array { 156 | var out: Array = []; 157 | for (var i in translations) { 158 | if (translations[i] instanceof Object) { 159 | out.push({name: prefix + '.' + i, value: "array(...)"}); 160 | out = out.concat(this.getTranslations(translations[i], prefix + '.' + i)); 161 | } else { 162 | out.push({name: prefix + '.' + i, value: translations[i]}); 163 | } 164 | } 165 | return out; 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/ValidationProvider.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import * as vscode from 'vscode'; 4 | import Helpers from './helpers'; 5 | 6 | 7 | export default class ValidationProvider implements vscode.CompletionItemProvider { 8 | private rules: any = { 9 | 'accepted' : 'accepted', 10 | 'active_url' : 'active_url', 11 | 'after_or_equal' : 'after_or_equal:${0:date}', 12 | 'after' : 'after:date', 13 | 'alpha_dash' : 'alpha_dash', 14 | 'alpha_num' : 'alpha_num', 15 | 'alpha' : 'alpha', 16 | 'array' : 'array', 17 | 'ascii' : 'ascii', 18 | 'bail' : 'bail', 19 | 'before_or_equal' : 'before_or_equal:${1:date}', 20 | 'before' : 'before:${1:date}', 21 | 'between' : 'between:${1:min},${2:max}', 22 | 'boolean' : 'boolean', 23 | 'confirmed' : 'confirmed', 24 | 'current_password' : 'current_password:${1:api}', 25 | 'date_equals' : 'date_equals:${1:date}', 26 | 'date_format' : 'date_format:${1:format}', 27 | 'date' : 'date', 28 | 'decimal' : 'decimal:${1:min},${2:max}', 29 | 'declined_if' : 'declined_if:${1:anotherfield},${2:value}', 30 | 'declined' : 'declined', 31 | 'different' : 'different:${1:field}', 32 | 'digits_between' : 'digits_between:${1:min},${2:max}', 33 | 'digits' : 'digits:${1:value}', 34 | 'dimensions' : 'dimensions', 35 | 'distinct' : 'distinct', 36 | 'doesnt_end_with' : 'doesnt_end_with:${1:foo},${2:bar}', 37 | 'doesnt_start_with' : 'doesnt_start_with:${1:foo},${2:bar}', 38 | 'email' : 'email', 39 | 'ends_with' : 'ends_with:${1}', 40 | 'exists' : 'exists:${2:table},${3:column}', 41 | 'file' : 'file', 42 | 'filled' : 'filled', 43 | 'gt' : 'gt:${1:field}', 44 | 'gte' : 'gte:${1:field}', 45 | 'image' : 'image', 46 | 'in_array' : 'in_array:${1:anotherfield.*}', 47 | 'in' : 'in:${1:something},${2:something else}', 48 | 'integer' : 'integer', 49 | 'ip' : 'ip', 50 | 'ipv4' : 'ipv4', 51 | 'ipv6' : 'ipv6', 52 | 'json' : 'json', 53 | 'lowercase' : 'lowercase', 54 | 'lt' : 'lt:${1:field}', 55 | 'lte' : 'lte:${1:field}', 56 | 'mac_address' : 'mac_address', 57 | 'max_digits' : 'max_digits:${1:value}', 58 | 'max' : 'max:${1:value}', 59 | 'mimes' : 'mimes:${1:png,jpg}', 60 | 'mimetypes' : 'mimetypes:${1:text/plain}', 61 | 'min_digits' : 'min_digits:${1:value}', 62 | 'min' : 'min:${1:value}', 63 | 'multiple_of' : 'multiple_of:${1:value}', 64 | 'not_in' : 'not_in:${1:something},${2:something else}', 65 | 'not_regex' : 'not_regex:${1:pattern}', 66 | 'nullable' : 'nullable', 67 | 'numeric' : 'numeric', 68 | 'password' : 'password', 69 | 'present' : 'present', 70 | 'prohibited_if' : 'prohibited_if:${1:anotherfield},${2:value}', 71 | 'prohibited_unless' : 'prohibited_unless:${1:anotherfield},${2:value}', 72 | 'prohibited' : 'prohibited', 73 | 'regex' : 'regex:${1:pattern}', 74 | 'required_array_keys' : 'required_array_keys:${1:foo},${2:bar}', 75 | 'required_if' : 'required_if:${1:anotherfield},${2:value}', 76 | 'required_unless' : 'required_unless:${1:anotherfield},${2:value}', 77 | 'required_with_all' : 'required_with_all:${1:anotherfield},${2:anotherfield}', 78 | 'required_with' : 'required_with:${1:anotherfield}', 79 | 'required_without_all' : 'required_without_all:${1:anotherfield},${2:anotherfield}', 80 | 'required_without' : 'required_without:${1:anotherfield}', 81 | 'required' : 'required', 82 | 'same' : 'same:${1:field}', 83 | 'size' : 'size:${1:value}', 84 | 'sometimes' : 'sometimes', 85 | 'starts_with' : 'starts_with:${1:foo},${2:bar}', 86 | 'string' : 'string', 87 | 'timezone' : 'timezone', 88 | 'unique' : 'unique:${1:table},${2:column},${3:except},${4:id}', 89 | 'uppercase' : 'uppercase', 90 | 'url' : 'url', 91 | 'uuid' : 'uuid', 92 | }; 93 | 94 | provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Array { 95 | var out:Array = []; 96 | var func = Helpers.parseDocumentFunction(document, position); 97 | 98 | if ( 99 | (func && func.paramIndex !== null && func.function && Helpers.tags.validation.functions.some((fn:string) => func.function.includes(fn))) || 100 | (func && func.paramIndex !== null && func.class && Helpers.tags.validation.classes.some((cls:string) => func.class.includes(cls))) || 101 | (document 102 | .getText() 103 | .match(/class .* extends (\S+Request)/g) || 104 | document 105 | .getText() 106 | .match( 107 | /use (Illuminate\\Foundation\\Http\\FormRequest)/g 108 | )) 109 | ) { 110 | var rules = this.rules; 111 | Object.assign(rules, vscode.workspace.getConfiguration("LaravelExtraIntellisense.customValidationRules")); 112 | for (var i in rules) { 113 | var completeItem = new vscode.CompletionItem(i, vscode.CompletionItemKind.Enum); 114 | completeItem.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 115 | completeItem.insertText = new vscode.SnippetString(this.rules[i]); 116 | out.push(completeItem); 117 | } 118 | } 119 | return out; 120 | } 121 | } -------------------------------------------------------------------------------- /src/ViewProvider.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import * as vscode from 'vscode'; 4 | import * as fs from "fs"; 5 | import Helpers from './helpers'; 6 | 7 | export default class ViewProvider implements vscode.CompletionItemProvider { 8 | private timer: any = null; 9 | private views: {[key:string]: string} = {}; 10 | private watcher: any = null; 11 | 12 | constructor () { 13 | var self = this; 14 | self.loadViews(); 15 | if (vscode.workspace.workspaceFolders !== undefined) { 16 | this.watcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], "{,**/}{view,views}/{*,**/*}")); 17 | this.watcher.onDidCreate((e: vscode.Uri) => this.onChange()); 18 | this.watcher.onDidDelete((e: vscode.Uri) => this.onChange()); 19 | } 20 | } 21 | 22 | provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Array { 23 | var out:Array = []; 24 | var func = Helpers.parseDocumentFunction(document, position); 25 | if (func === null) { 26 | return out; 27 | } 28 | 29 | if (func && ((func.class && Helpers.tags.view.classes.some((cls:string) => func.class.includes(cls))) || Helpers.tags.view.functions.some((fn:string) => func.function.includes(fn)))) { 30 | if (func.paramIndex === 0) { 31 | for (let i in this.views) { 32 | var completeItem = new vscode.CompletionItem(i, vscode.CompletionItemKind.Constant); 33 | completeItem.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 34 | out.push(completeItem); 35 | } 36 | } else if (typeof this.views[func.parameters[0]] !== 'undefined') { 37 | var viewContent = fs.readFileSync(this.views[func.parameters[0]], 'utf8'); 38 | var variableRegex = /\$([A-Za-z_][A-Za-z0-9_]*)/g; 39 | var r:any = []; 40 | var variableNames = []; 41 | while (r = variableRegex.exec(viewContent)) { 42 | variableNames.push(r[1]); 43 | } 44 | variableNames = variableNames.filter((v, i, a) => a.indexOf(v) === i); 45 | for (let i in variableNames) { 46 | var variableCompleteItem = new vscode.CompletionItem(variableNames[i], vscode.CompletionItemKind.Constant); 47 | variableCompleteItem.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 48 | out.push(variableCompleteItem); 49 | } 50 | } 51 | } else if (func && (func.function === '@section' || func.function === '@push')) { 52 | out = this.getYields(func.function, document.getText()); 53 | } 54 | return out; 55 | } 56 | 57 | getYields(func:string, documentText: string): Array { 58 | var out: Array = []; 59 | var extendsRegex = /@extends\s*\([\'\"](.+)[\'\"]\)/g; 60 | var regexResult:any = []; 61 | if (regexResult = extendsRegex.exec(documentText)) { 62 | if (typeof this.views[regexResult[1]] !== 'undefined') { 63 | var parentContent = fs.readFileSync(this.views[regexResult[1]], 'utf8'); 64 | var yieldRegex = /@yield\s*\([\'\"]([A-Za-z0-9_\-\.]+)[\'\"](,.*)?\)/g; 65 | if (func === '@push') { 66 | yieldRegex = /@stack\s*\([\'\"]([A-Za-z0-9_\-\.]+)[\'\"](,.*)?\)/g; 67 | } 68 | var yieldNames = []; 69 | while (regexResult = yieldRegex.exec(parentContent)) { 70 | yieldNames.push(regexResult[1]); 71 | } 72 | yieldNames = yieldNames.filter((v, i, a) => a.indexOf(v) === i); 73 | for (var i in yieldNames) { 74 | var yieldCompleteItem = new vscode.CompletionItem(yieldNames[i], vscode.CompletionItemKind.Constant); 75 | out.push(yieldCompleteItem); 76 | } 77 | out = out.concat(this.getYields(func, parentContent)); 78 | } 79 | } 80 | return out; 81 | } 82 | 83 | onChange() { 84 | var self = this; 85 | if (self.timer) { 86 | clearTimeout(self.timer); 87 | } 88 | self.timer = setTimeout(function () { 89 | self.loadViews(); 90 | self.timer = null; 91 | }, 5000); 92 | } 93 | 94 | loadViews () { 95 | try { 96 | var self = this; 97 | var code = "echo json_encode(app('view')->getFinder()->getHints());"; 98 | Helpers.runLaravel(code.replace("getHints", "getPaths"), "Views paths") 99 | .then(function (viewPathsResult) { 100 | var viewPaths = JSON.parse(viewPathsResult); 101 | Helpers.runLaravel(code, "Views") 102 | .then(function (viewNamespacesResult) { 103 | var viewNamespaces = JSON.parse(viewNamespacesResult); 104 | for (let i in viewPaths) { 105 | viewPaths[i] = viewPaths[i].replace(Helpers.projectPath('/', true), Helpers.projectPath('/')); 106 | } 107 | for (let i in viewNamespaces) { 108 | for (let j in viewNamespaces[i]) { 109 | viewNamespaces[i][j] = viewNamespaces[i][j].replace(Helpers.projectPath('/', true), Helpers.projectPath('/')); 110 | } 111 | } 112 | let views:any = {}; 113 | for (let i in viewPaths) { 114 | views = Object.assign(views, self.getViews(viewPaths[i])); 115 | } 116 | for (let i in viewNamespaces) { 117 | for (var j in viewNamespaces[i]) { 118 | var viewsInNamespace = self.getViews(viewNamespaces[i][j]); 119 | for (var k in viewsInNamespace) { 120 | views[i + "::" + k] = viewNamespaces[k]; 121 | } 122 | } 123 | } 124 | self.views = views; 125 | }); 126 | }); 127 | } catch (exception) { 128 | console.error(exception); 129 | } 130 | } 131 | 132 | getViews(path: string): {[key:string]: string} { 133 | if (path.substr(-1) !== '/' && path.substr(-1) !== '\\') { 134 | path += "/"; 135 | } 136 | var out: {[key:string]: string} = {}; 137 | var self = this; 138 | if (fs.existsSync(path) && fs.lstatSync(path).isDirectory()) { 139 | fs.readdirSync(path).forEach(function (file) { 140 | if (fs.lstatSync(path+file).isDirectory()) { 141 | var viewsInDirectory = self.getViews(path + file + "/"); 142 | for (var i in viewsInDirectory) { 143 | out[file + vscode.workspace.getConfiguration("LaravelExtraIntellisense").get('viewDirectorySeparator') + i] = viewsInDirectory[i]; 144 | } 145 | } else { 146 | if (file.includes("blade.php")) { 147 | out[file.replace(".blade.php", "")] = path + file; 148 | } 149 | } 150 | }); 151 | } 152 | return out; 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/ViteProvider.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import * as vscode from 'vscode'; 4 | import * as fs from 'fs'; 5 | import Helpers from './helpers'; 6 | 7 | export default class ViteProvider implements vscode.CompletionItemProvider { 8 | private viteAssets: Array = []; 9 | 10 | constructor() { 11 | this.loadViteManifest(); 12 | setInterval(() => this.loadViteManifest(), 60000); 13 | } 14 | 15 | provideCompletionItems( 16 | document: vscode.TextDocument, 17 | position: vscode.Position, 18 | token: vscode.CancellationToken, 19 | context: vscode.CompletionContext 20 | ): Array { 21 | const completions: Array = []; 22 | const func = Helpers.parseDocumentFunction(document, position); 23 | 24 | if (func === null) { 25 | return completions; 26 | } 27 | 28 | if (func && (Helpers.tags.vite.functions.some((fn: string) => func.function.includes(fn)))) { 29 | for (const asset of this.viteAssets) { 30 | const item = new vscode.CompletionItem(asset, vscode.CompletionItemKind.Value); 31 | item.range = document.getWordRangeAtPosition(position, Helpers.wordMatchRegex); 32 | completions.push(item); 33 | } 34 | } 35 | 36 | return completions; 37 | } 38 | 39 | private loadViteManifest() { 40 | try { 41 | const manifestPath = Helpers.projectPath('public/build/manifest.json'); 42 | if (fs.existsSync(manifestPath)) { 43 | const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')); 44 | this.viteAssets = Object.keys(manifest); 45 | } 46 | } catch (exception) { 47 | console.error(exception); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /src/extension.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import * as vscode from 'vscode'; 4 | import * as fs from "fs"; 5 | import Helpers from "./helpers"; 6 | 7 | import RouteProvider from "./RouteProvider"; 8 | import ViewProvider from "./ViewProvider"; 9 | import ConfigProvider from './ConfigProvider'; 10 | import TranslationProvider from './TranslationProvider'; 11 | import MixProvider from './MixProvider'; 12 | import ViteProvider from './ViteProvider'; 13 | import ValidationProvider from './ValidationProvider'; 14 | import EnvProvider from './EnvProvider'; 15 | import MiddlewareProvider from './MiddlewareProvider'; 16 | import AuthProvider from './AuthProvider'; 17 | import AssetProvider from './AssetProvider'; 18 | import EloquentProvider from './EloquentProvider'; 19 | import BladeProvider from './BladeProvider'; 20 | import { sep } from 'path'; 21 | 22 | 23 | export function activate(context: vscode.ExtensionContext) { 24 | showWelcomeMessage(context); 25 | vscode.workspace.onDidOpenTextDocument((document) => { 26 | if (isDatabaseRelatedFile(document)) { 27 | suggestDevDbExtension(context); 28 | } 29 | }); 30 | 31 | if (vscode.workspace.workspaceFolders instanceof Array && vscode.workspace.workspaceFolders.length > 0) { 32 | if (fs.existsSync(Helpers.projectPath("artisan"))) { 33 | if (Helpers.outputChannel === null) { 34 | Helpers.outputChannel = vscode.window.createOutputChannel("Laravel Extra Intellisense", {log: true}); 35 | Helpers.outputChannel.info("Laravel Extra Intellisense Started..."); 36 | } 37 | 38 | const LANGUAGES = 39 | [ 40 | { scheme: 'file', language: 'php' }, 41 | { scheme: 'file', language: 'blade' }, 42 | { scheme: 'file', language: 'laravel-blade' } 43 | ]; 44 | const TRIGGER_CHARACTERS = "\"'".split(""); 45 | 46 | context.subscriptions.push(vscode.languages.registerCompletionItemProvider(LANGUAGES, new RouteProvider, ...TRIGGER_CHARACTERS)); 47 | context.subscriptions.push(vscode.languages.registerCompletionItemProvider(LANGUAGES, new ViewProvider, ...TRIGGER_CHARACTERS)); 48 | context.subscriptions.push(vscode.languages.registerCompletionItemProvider(LANGUAGES, new ConfigProvider, ...TRIGGER_CHARACTERS)); 49 | context.subscriptions.push(vscode.languages.registerCompletionItemProvider(LANGUAGES, new TranslationProvider, ...TRIGGER_CHARACTERS)); 50 | context.subscriptions.push(vscode.languages.registerCompletionItemProvider(LANGUAGES, new MixProvider, ...TRIGGER_CHARACTERS)); 51 | context.subscriptions.push(vscode.languages.registerCompletionItemProvider(LANGUAGES, new ViteProvider(), ...TRIGGER_CHARACTERS)); 52 | context.subscriptions.push(vscode.languages.registerCompletionItemProvider(LANGUAGES, new ValidationProvider, ...TRIGGER_CHARACTERS.concat(['|']))); 53 | context.subscriptions.push(vscode.languages.registerCompletionItemProvider(LANGUAGES, new EnvProvider, ...TRIGGER_CHARACTERS)); 54 | context.subscriptions.push(vscode.languages.registerCompletionItemProvider(LANGUAGES, new MiddlewareProvider, ...TRIGGER_CHARACTERS)); 55 | context.subscriptions.push(vscode.languages.registerCompletionItemProvider(LANGUAGES, new AuthProvider, ...TRIGGER_CHARACTERS)); 56 | context.subscriptions.push(vscode.languages.registerCompletionItemProvider(LANGUAGES, new AssetProvider, ...TRIGGER_CHARACTERS)); 57 | context.subscriptions.push(vscode.languages.registerCompletionItemProvider(LANGUAGES, new EloquentProvider, ...TRIGGER_CHARACTERS.concat(['>']))); 58 | context.subscriptions.push(vscode.languages.registerCompletionItemProvider(LANGUAGES, new BladeProvider, '@')); 59 | } 60 | } 61 | } 62 | 63 | export function deactivate() {} 64 | 65 | function showWelcomeMessage(context: vscode.ExtensionContext) { 66 | let previousVersion = context.globalState.get('laravel-extra-intellisense-version'); 67 | let currentVersion = vscode.extensions.getExtension('amiralizadeh9480.laravel-extra-intellisense')?.packageJSON?.version; 68 | let message : string | null = null; 69 | let previousVersionArray = previousVersion ? previousVersion.split('.').map((s: string) => Number(s)) : [0, 0, 0]; 70 | let currentVersionArray = currentVersion.split('.').map((s: string) => Number(s)); 71 | if (previousVersion === undefined || previousVersion.length === 0) { 72 | message = "Thanks for using Laravel Extra Intellisense. Please consider configure the extension settings, so it can boot your Laravel project currectly and get data needed for autocompletion."; 73 | } else if (currentVersion !== previousVersion && ( 74 | // (previousVersionArray[0] === currentVersionArray[0] && previousVersionArray[1] === currentVersionArray[1] && previousVersionArray[2] < currentVersionArray[2]) || 75 | (previousVersionArray[0] === currentVersionArray[0] && previousVersionArray[1] < currentVersionArray[1]) || 76 | (previousVersionArray[0] < currentVersionArray[0]) 77 | ) 78 | ) { 79 | message = "Laravel Extra Intellisense updated to " + currentVersion + " - New Feature✨ : Add Vite autocompletion support."; 80 | } 81 | if (message) { 82 | vscode.window.showInformationMessage(message, '⭐️ Star on Github', '🐞 Report Bug') 83 | .then(function (val: string | undefined) { 84 | if (val === '⭐️ Rate') { 85 | vscode.env.openExternal(vscode.Uri.parse('https://marketplace.visualstudio.com/items?itemName=amiralizadeh9480.laravel-extra-intellisense')); 86 | } else if (val === '🐞 Report Bug') { 87 | vscode.env.openExternal(vscode.Uri.parse('https://github.com/amir9480/vscode-laravel-extra-intellisense/issues')); 88 | } else if (val === '⭐️ Star on Github') { 89 | vscode.env.openExternal(vscode.Uri.parse('https://github.com/amir9480/vscode-laravel-extra-intellisense')); 90 | } 91 | }); 92 | context.globalState.update('laravel-extra-intellisense-version', currentVersion); 93 | } 94 | } 95 | 96 | function isDatabaseRelatedFile(document: vscode.TextDocument): boolean { 97 | const filePath = document.uri.fsPath; 98 | const isInModelsPath = filePath.includes(`app${sep}Models`); 99 | const isInDatabasePath = filePath.includes(`database${sep}`); 100 | 101 | return isInModelsPath || isInDatabasePath 102 | } 103 | 104 | async function suggestDevDbExtension(context: vscode.ExtensionContext) { 105 | const DEVDB_EXTENSION_ID = 'damms005.devdb'; 106 | const RECOMMENDATION_KEY = 'laravel-extra-intellisense-devdb-extension-recommendation'; 107 | const NOT_INTERESTED_KEY = 'laravel-extra-intellisense-devdb-extension-not-interested'; 108 | const isDevDbExtensionInstalled = vscode.extensions.getExtension(DEVDB_EXTENSION_ID) !== undefined; 109 | 110 | if (isDevDbExtensionInstalled || context.globalState.get(NOT_INTERESTED_KEY)) { 111 | return; 112 | } 113 | 114 | const currentTime = Date.now(); 115 | const lastRecommendation = context.globalState.get(RECOMMENDATION_KEY); 116 | const aYearSinceLastRecommendation = lastRecommendation && (((currentTime - lastRecommendation) > 365 * 24 * 60 * 60 * 1000)); 117 | 118 | if (!lastRecommendation || aYearSinceLastRecommendation) { 119 | const selection = await vscode.window.showInformationMessage( 120 | 'Would you like to have Laravel Eloquent model code lens and query explainer?', 121 | 'Check it Out', 122 | 'Not Interested', 123 | 'Remind Me Later' 124 | ); 125 | 126 | if (selection === 'Check it Out') { 127 | vscode.commands.executeCommand( 128 | 'extension.open', 129 | DEVDB_EXTENSION_ID 130 | ); 131 | } else if (selection === 'Not Interested') { 132 | context.globalState.update(NOT_INTERESTED_KEY, true); 133 | } else if (selection === 'Remind Me Later') { 134 | context.globalState.update(RECOMMENDATION_KEY, currentTime); 135 | } 136 | } 137 | } -------------------------------------------------------------------------------- /src/helpers.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import * as vscode from 'vscode'; 4 | import * as cp from 'child_process'; 5 | import * as fs from 'fs'; 6 | import * as os from 'os'; 7 | import { resolve } from 'path'; 8 | 9 | export default class Helpers { 10 | 11 | static wordMatchRegex = /[\w\d\-_\.\:\\\/@]+/g; 12 | static phpParser:any = null; 13 | static cachedParseFunction:any = null; 14 | static modelsCache: Array; 15 | static modelsCacheTime: number = 0; 16 | static outputChannel: vscode.LogOutputChannel|null = null; 17 | static lastErrorMessage: number = 0; 18 | static disableErrorMessage: boolean = false; 19 | 20 | static tags:any = { 21 | config: {classes: ['Config'] , functions: ['config']}, 22 | mix: {classes: [] , functions: ['mix']}, 23 | vite: {classes: [] , functions: ['vite', '@vite']}, 24 | route: {classes: ['Route'] , functions: ['route', 'signedRoute']}, 25 | trans: {classes: ['Lang'] , functions: ['__', 'trans', '@lang']}, 26 | validation: {classes: ['Validator'] , functions: ['validate', 'sometimes', 'rules']}, 27 | view: {classes: ['View'] , functions: ['view', 'markdown', 'links', '@extends', '@component', '@include', '@each']}, 28 | env: {classes: [] , functions: ['env']}, 29 | auth: {classes: ['Gate'] , functions: ['can', '@can', '@cannot', '@canany']}, 30 | asset: {classes: [] , functions: ['asset']}, 31 | model: {classes: [] , functions: []}, 32 | }; 33 | static functionRegex: any = null; 34 | 35 | static relationMethods = ['has', 'orHas', 'whereHas', 'orWhereHas', 'whereDoesntHave', 'orWhereDoesntHave', 36 | 'doesntHave', 'orDoesntHave', 'hasMorph', 'orHasMorph', 'doesntHaveMorph', 'orDoesntHaveMorph', 37 | 'whereHasMorph', 'orWhereHasMorph', 'whereDoesntHaveMorph', 'orWhereDoesntHaveMorph', 38 | 'withAggregate', 'withCount', 'withMax', 'withMin', 'withSum', 'withAvg']; 39 | 40 | /** 41 | * Create full path from project file name 42 | * 43 | * @param path 44 | * @param forCode 45 | * @param string 46 | */ 47 | static projectPath(path:string, forCode: boolean = false) : string { 48 | if (path[0] !== '/') { 49 | path = '/' + path; 50 | } 51 | 52 | let basePath = vscode.workspace.getConfiguration("LaravelExtraIntellisense").get('basePath'); 53 | if (forCode === false && basePath && basePath.length > 0) { 54 | if (basePath.startsWith('.') && vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) { 55 | basePath = resolve(vscode.workspace.workspaceFolders[0].uri.fsPath, basePath); 56 | } 57 | basePath = basePath.replace(/[\/\\]$/, ""); 58 | return basePath + path; 59 | } 60 | 61 | let basePathForCode = vscode.workspace.getConfiguration("LaravelExtraIntellisense").get('basePathForCode'); 62 | if (forCode && basePathForCode && basePathForCode.length > 0) { 63 | if (basePathForCode.startsWith('.') && vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) { 64 | basePathForCode = resolve(vscode.workspace.workspaceFolders[0].uri.fsPath, basePathForCode); 65 | } 66 | basePathForCode = basePathForCode.replace(/[\/\\]$/, ""); 67 | return basePathForCode + path; 68 | } 69 | 70 | if (vscode.workspace.workspaceFolders instanceof Array && vscode.workspace.workspaceFolders.length > 0) { 71 | for (let workspaceFolder of vscode.workspace.workspaceFolders) { 72 | if (fs.existsSync(workspaceFolder.uri.fsPath + "/artisan")) { 73 | return workspaceFolder.uri.fsPath + path; 74 | } 75 | } 76 | } 77 | return ""; 78 | } 79 | 80 | static arrayUnique(value:any, index:any, self:Array) { 81 | return self.indexOf(value) === index; 82 | } 83 | 84 | static showErrorPopup() { 85 | let disableErrorAlert = vscode.workspace.getConfiguration("LaravelExtraIntellisense").get('disableErrorAlert'); 86 | if ( 87 | disableErrorAlert == false && 88 | Helpers.disableErrorMessage == false && 89 | Helpers.lastErrorMessage + 10 < Date.now()/1000 90 | ) { 91 | Helpers.lastErrorMessage = Date.now()/1000; 92 | 93 | vscode.window.showErrorMessage('Laravel Extra Intellisense error', 'View Error', 'Don\'t show again') 94 | .then(function (val: string | undefined) { 95 | if (val === 'Don\'t show again') { 96 | Helpers.disableErrorMessage = true; 97 | } else if (val === 'View Error') { 98 | Helpers.outputChannel?.show(true); 99 | } 100 | }); 101 | } 102 | } 103 | 104 | /** 105 | * Boot laravel and run simple php code. 106 | * 107 | * @param code 108 | */ 109 | static runLaravel(code: string, description: string|null = null) : Promise { 110 | code = code.replace(/(?:\r\n|\r|\n)/g, ' '); 111 | if (fs.existsSync(Helpers.projectPath("vendor/autoload.php")) && fs.existsSync(Helpers.projectPath("bootstrap/app.php"))) { 112 | var command = 113 | "define('LARAVEL_START', microtime(true));" + 114 | "require_once '" + Helpers.projectPath("vendor/autoload.php", true) + "';" + 115 | "$app = require_once '" + Helpers.projectPath("bootstrap/app.php", true) + "';" + 116 | "class VscodeLaravelExtraIntellisenseProvider extends \\Illuminate\\Support\\ServiceProvider" + 117 | "{" + 118 | " public function register() {}" + 119 | " public function boot()" + 120 | " {" + 121 | " if (method_exists($this->app['log'], 'setHandlers')) {" + 122 | " $this->app['log']->setHandlers([new \\Monolog\\Handler\\ProcessHandler()]);" + 123 | " }" + 124 | " }" + 125 | "}" + 126 | "$app->register(new VscodeLaravelExtraIntellisenseProvider($app));" + 127 | "$kernel = $app->make(Illuminate\\Contracts\\Console\\Kernel::class);" + 128 | 129 | "$status = $kernel->handle(" + 130 | "$input = new Symfony\\Component\\Console\\Input\\ArgvInput," + 131 | "new Symfony\\Component\\Console\\Output\\ConsoleOutput" + 132 | ");" + 133 | "if ($status == 0) {" + 134 | " echo '___VSCODE_LARAVEL_EXTRA_INSTELLISENSE_OUTPUT___';" + 135 | code + 136 | " echo '___VSCODE_LARAVEL_EXTRA_INSTELLISENSE_END_OUTPUT___';" + 137 | "}" + 138 | "$kernel->terminate($input, $status);" + 139 | "exit($status);" 140 | 141 | var self = this; 142 | 143 | return new Promise(function (resolve, error) { 144 | self.runPhp(command, description) 145 | .then(function (result: string) { 146 | var out : string | null | RegExpExecArray = result; 147 | out = /___VSCODE_LARAVEL_EXTRA_INSTELLISENSE_OUTPUT___(.*)___VSCODE_LARAVEL_EXTRA_INSTELLISENSE_END_OUTPUT___/g.exec(out); 148 | if (out) { 149 | resolve(out[1]); 150 | } else { 151 | error("PARSE ERROR: " + result); 152 | 153 | Helpers.outputChannel?.error("Laravel Extra Intellisense Parse Error:\n " + (description ?? '') + '\n\n' + result); 154 | Helpers.showErrorPopup(); 155 | } 156 | }) 157 | .catch(function (e : Error) { 158 | error(e); 159 | }); 160 | }); 161 | } 162 | return new Promise((resolve, error) => resolve("")); 163 | } 164 | 165 | /** 166 | * run simple php code. 167 | * 168 | * @param code 169 | */ 170 | static async runPhp(code: string, description: string|null = null) : Promise { 171 | code = code.replace(/\"/g, "\\\""); 172 | if (['linux', 'openbsd', 'sunos', 'darwin'].some(unixPlatforms => os.platform().includes(unixPlatforms))) { 173 | code = code.replace(/\$/g, "\\$"); 174 | code = code.replace(/\\\\'/g, '\\\\\\\\\''); 175 | code = code.replace(/\\\\"/g, '\\\\\\\\\"'); 176 | } 177 | let commandTemplate = vscode.workspace.getConfiguration("LaravelExtraIntellisense").get('phpCommand') ?? "php -r \"{code}\""; 178 | let command = commandTemplate.replace("{code}", code); 179 | let out = new Promise(function (resolve, error) { 180 | if (description != null) { 181 | Helpers.outputChannel?.info("Laravel Extra Intellisense command started: " + description); 182 | } 183 | 184 | cp.exec(command, 185 | { cwd: vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0 ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined }, 186 | function (err, stdout, stderr) { 187 | if (err == null) { 188 | if (description != null) { 189 | Helpers.outputChannel?.info("Laravel Extra Intellisense Resolved: " + description); 190 | } 191 | resolve(stdout); 192 | } else { 193 | const errorOutput = stderr.length > 0 ? stderr : stdout; 194 | Helpers.outputChannel?.error("Laravel Extra Intellisense Error:\n " + (description ?? '') + '\n\n' + errorOutput); 195 | Helpers.showErrorPopup(); 196 | error(errorOutput); 197 | } 198 | } 199 | ); 200 | }); 201 | return out; 202 | } 203 | 204 | /** 205 | * Parse php code with 'php-parser' package. 206 | * @param code 207 | */ 208 | static parsePhp(code: string): any { 209 | if (! Helpers.phpParser) { 210 | var PhpEngine = require('php-parser'); 211 | Helpers.phpParser = new PhpEngine({ 212 | parser: { 213 | extractDoc: true, 214 | php7: true 215 | }, 216 | ast: { 217 | withPositions: true 218 | } 219 | }); 220 | } 221 | try { 222 | return Helpers.phpParser.parseCode(code); 223 | } catch (exception) { 224 | return null; 225 | } 226 | } 227 | 228 | /** 229 | * Convert php variable defination to javascript variable. 230 | * @param code 231 | */ 232 | static evalPhp(code: string): any { 233 | var out = Helpers.parsePhp('= match.index && match[0] && position < match.index + match[0].length) { 269 | if ((match2 = inlineFunctionMatch.exec(match[0])) !== null && typeof match2[3] === 'string' && typeof match[1] === 'string' && typeof match[6] === 'string' && typeof match2[1] === 'string') { 270 | out = this.parseFunction(match2[3], position - (match.index + match[1].length + match[6].length + match2[1].length), level + 1); 271 | } else if (typeof match[1] === 'string' && typeof match[6]=== 'string' && typeof match[7]=== 'string') { 272 | var textParameters = []; 273 | var paramIndex = null; 274 | var paramIndexCounter = 0; 275 | var paramsPosition = position - (match.index + match[1].length + match[6].length); 276 | 277 | var functionInsideParameter; 278 | if (match[7].length >= 4 && (functionInsideParameter = this.parseFunction(match[7], paramsPosition))) { 279 | return functionInsideParameter; 280 | } 281 | 282 | while ((match2 = paramsRegex.exec(match[7])) !== null) { 283 | textParameters.push(match2[3]); 284 | if (paramsPosition >= match2.index && typeof match2[0] === 'string' && paramsPosition <= match2.index + match2[0].length) { 285 | paramIndex = paramIndexCounter; 286 | } 287 | paramIndexCounter++; 288 | } 289 | var functionParametrs = []; 290 | for (let i in textParameters) { 291 | functionParametrs.push(this.evalPhp(textParameters[i])); 292 | } 293 | out = { 294 | class: match[3], 295 | function: match[4], 296 | paramIndex: paramIndex, 297 | parameters: functionParametrs, 298 | textParameters: textParameters 299 | }; 300 | } 301 | if (level === 0) { 302 | Helpers.cachedParseFunction = {text, position, out}; 303 | } 304 | } 305 | } 306 | } 307 | return out; 308 | } 309 | 310 | /** 311 | * Parse php function call from vscode editor. 312 | * 313 | * @param document 314 | * @param position 315 | */ 316 | static parseDocumentFunction(document: vscode.TextDocument, position: vscode.Position) { 317 | var pos = document.offsetAt(position); 318 | return Helpers.parseFunction(document.getText(), pos); 319 | } 320 | 321 | /** 322 | * Get laravel models as array. 323 | * 324 | * @returns array 325 | */ 326 | static getModels() : Promise> { 327 | var self = this; 328 | return new Promise>(function (resolve, reject) { 329 | if (Math.floor(Date.now()/1000) - self.modelsCacheTime < 60) { 330 | return resolve(self.modelsCache); 331 | } else { 332 | Helpers.runLaravel(` 333 | echo json_encode(array_values(array_filter(array_map(function ($name) {return app()->getNamespace().str_replace([app_path().'/', app_path().'\\\\', '.php', '/'], ['', '', '', '\\\\'], $name);}, array_merge(glob(app_path('*')), glob(app_path('Models/*')))), function ($class) { 334 | return class_exists($class) && is_subclass_of($class, 'Illuminate\\\\Database\\\\Eloquent\\\\Model'); 335 | }))); 336 | `, "Application Models").then(function (result) { 337 | var models = JSON.parse(result); 338 | self.modelsCache = models; 339 | resolve(models); 340 | }) 341 | .catch(function (error) { 342 | console.error(error); 343 | resolve([]); 344 | }); 345 | } 346 | }); 347 | } 348 | 349 | /** 350 | * Get indent space based on user configuration 351 | */ 352 | static getSpacer() : string { 353 | const editor = vscode.window.activeTextEditor; 354 | if (editor && editor.options.insertSpaces) { 355 | return ' '.repeat(editor.options.tabSize); 356 | } 357 | return '\t'; 358 | } 359 | } 360 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2019", 5 | "lib": ["ES2019"], 6 | "outDir": "out", 7 | "sourceMap": true, 8 | "strict": true, 9 | "rootDir": "src" 10 | }, 11 | "include": [ 12 | "src/**/*.ts", 13 | "./node_modules/vscode/vscode.d.ts", 14 | "./node_modules/vscode/lib/*", 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-string-throw": true, 4 | "no-unused-expression": true, 5 | "no-duplicate-variable": true, 6 | "curly": true, 7 | "class-name": true, 8 | "semicolon": [ 9 | true, 10 | "always" 11 | ], 12 | "triple-equals": true 13 | }, 14 | "defaultSeverity": "warning" 15 | } 16 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | //@ts-check 2 | 3 | 'use strict'; 4 | 5 | const path = require('path'); 6 | 7 | /**@type {import('webpack').Configuration}*/ 8 | const config = { 9 | target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/ 10 | 11 | entry: './src/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/ 12 | output: { // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/ 13 | path: path.resolve(__dirname, 'dist'), 14 | filename: 'extension.js', 15 | libraryTarget: "commonjs2", 16 | devtoolModuleFilenameTemplate: "../[resource-path]", 17 | }, 18 | devtool: 'source-map', 19 | cache: false, 20 | externals: { 21 | vscode: "commonjs vscode" // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/ 22 | }, 23 | resolve: { // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader 24 | extensions: ['.ts', '.js'] 25 | }, 26 | module: { 27 | rules: [ 28 | { 29 | test: /\.ts$/, 30 | exclude: /node_modules/, 31 | use: [ 32 | { 33 | loader: 'ts-loader', 34 | options: { 35 | compilerOptions: { 36 | "module": "es6" // override `tsconfig.json` so that TypeScript emits native JavaScript modules. 37 | } 38 | } 39 | } 40 | ] 41 | } 42 | ] 43 | } 44 | }; 45 | module.exports = config; 46 | --------------------------------------------------------------------------------