├── .DS_Store ├── .eslintrc.yml ├── .github └── workflows │ └── test.yml ├── .gitignore ├── .vscode ├── launch.json └── tasks.json ├── .vscodeignore ├── CHANGELOG.md ├── DEVELOPER_README.md ├── LICENSE ├── README.md ├── client ├── python_validation.py └── src │ ├── client_constants.ts │ └── extension.ts ├── icon.png ├── images ├── .DS_Store ├── extension_features.gif └── extension_python_env.gif ├── package-lock.json ├── package.json ├── requirements.txt ├── server ├── __init__.py ├── __main__.py ├── feature_hover.py ├── feature_validation.py ├── server.py ├── spacy_server.py ├── tests │ ├── __init__.py │ ├── requirements.txt │ └── test_features.py └── util.py └── tsconfig.json /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/explosion/spacy-vscode/9fa92737b967e85ef0d0c8019c3004c3e249c9f2/.DS_Store -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es2021: true 3 | node: true 4 | extends: 5 | - 'eslint:recommended' 6 | - 'plugin:@typescript-eslint/recommended' 7 | parser: '@typescript-eslint/parser' 8 | parserOptions: 9 | ecmaVersion: 12 10 | sourceType: module 11 | plugins: 12 | - '@typescript-eslint' 13 | rules: {} 14 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: [push, pull_request, workflow_call] 4 | 5 | jobs: 6 | test: 7 | name: Run tests 8 | runs-on: ${{ matrix.os }} 9 | strategy: 10 | matrix: 11 | os: [ubuntu-latest, macos-latest, windows-latest] 12 | python-version: [3.8] 13 | steps: 14 | - uses: actions/checkout@v3 15 | - uses: actions/setup-python@v4 16 | with: 17 | python-version: ${{ matrix.python-version }} 18 | cache: "pip" # caching pip dependencies 19 | 20 | - name: Install python requirements 21 | run: pip install -r requirements.txt 22 | 23 | - name: Install dev python requirements 24 | run: pip install -r server/tests/requirements.txt 25 | 26 | - name: Run mypy 27 | run: mypy server 28 | 29 | - name: Run black 30 | run: black server --check 31 | 32 | - name: Run pytest 33 | run: pytest server 34 | 35 | - uses: actions/setup-node@v3 36 | with: 37 | node-version: 18 38 | 39 | - name: Install node requirements 40 | run: npm install 41 | 42 | - name: Run npm linter 43 | run: npm run lint 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | node_modules 3 | client/server 4 | .vscode-test 5 | .vscode/settings.json 6 | working_env 7 | *.vsix 8 | *.log 9 | __pycache__ 10 | .pytest_cache 11 | .mypy_cache 12 | test.py -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | { 3 | "version": "0.3.0", 4 | "configurations": [ 5 | { 6 | "name": "Launch Debug", 7 | "type": "extensionHost", 8 | "request": "launch", 9 | "runtimeExecutable": "${execPath}", 10 | "args": [ 11 | "--extensionDevelopmentPath=${workspaceRoot}" 12 | ], 13 | "outFiles": [ 14 | "${workspaceRoot}/client/out/**/*.js" 15 | ], 16 | "preLaunchTask": { 17 | "type": "npm", 18 | "script": "compile" 19 | }, 20 | "env": { 21 | "VSCODE_DEBUG_MODE": "true" 22 | } 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "npm", 6 | "script": "compile", 7 | "group": "build", 8 | "presentation": { 9 | "panel": "dedicated", 10 | "reveal": "never" 11 | }, 12 | "problemMatcher": ["$tsc"] 13 | }, 14 | { 15 | "type": "npm", 16 | "script": "watch", 17 | "isBackground": true, 18 | "group": { 19 | "kind": "build", 20 | "isDefault": true 21 | }, 22 | "presentation": { 23 | "panel": "dedicated", 24 | "reveal": "never" 25 | }, 26 | "problemMatcher": ["$tsc-watch"] 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .gitignore 3 | .github 4 | client/out/*.map 5 | client/src/ 6 | tsconfig.json 7 | tslint.json 8 | package.json 9 | package-lock.json 10 | working_env 11 | images 12 | .pytest_cache 13 | .mypy_cache 14 | *.vsix 15 | *.log -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | We try to follow semantic versioning (semver) if possible: 6 | 7 | - **MAJOR** version when you make incompatible API changes 8 | - **MINOR** version when you add functionality in a backwards compatible manner 9 | - **PATCH** version when you make backwards compatible bug fixes 10 | 11 | > Given a version number 1.2.3, 1 is the major number, 2 the minor and 3 the patch number. 12 | 13 | ## [1.0.1] - 02/06/2023 14 | 15 | ### Fixed 16 | 17 | - File bug in windows 18 | 19 | ## [1.0.0] - 02/05/2023 20 | 21 | ### Fixed 22 | 23 | - Hover functionality formatting 24 | - Publish for public release 25 | 26 | ## [0.6.0] - 05/04/2023 27 | 28 | ### Fixed 29 | 30 | - Environment Selection Bug 31 | 32 | ## [0.5.0] - 28/02/2023 33 | 34 | ### Added 35 | 36 | - Add config validation functionality 37 | - Add more info to developer docs 38 | 39 | ### Changed 40 | 41 | - Improved python interpreter search 42 | - Improved logging 43 | 44 | ### Fixed 45 | 46 | - mypy and linting issues 47 | 48 | ## [0.4.0] - 06/02/2023 49 | 50 | ### Added 51 | 52 | - Hover feature for variables 53 | - Links to code for registry functions 54 | - Github testing 55 | 56 | ### Changed 57 | 58 | ### Fixed 59 | 60 | - Improved formatting for hover displays 61 | 62 | ## [0.3.0] - 01/02/2023 63 | 64 | ### Added 65 | 66 | - Hover feature for sections 67 | - Documentation and argument/return types for the functions in the hover feature 68 | - Improved Python Environment Management 69 | - Moved checks to extra python script 70 | - Added checks if python modules fulfill version range 71 | - Added checks if `Python Extension` is enabled/installed 72 | - Added `client_constants` 73 | 74 | ### Changed 75 | 76 | - Refactored code within the `detect_registry_names` hover feature function 77 | - Changed logging to `LogOutputChannel` 78 | - Removed automated python interpreter selection 79 | - Added options to select specific interpreter or currently selected interpreter via dialog 80 | 81 | ### Fixed 82 | 83 | - Statusbar color is using color theme instead of hardcoded color 84 | - Added python prefix check for windows OS 85 | 86 | ## [0.2.0] - 26/01/2023 87 | 88 | ### Added 89 | 90 | - Added Python Environment Management 91 | - Selecting Python Interpreter restarts the server on new interpreter 92 | - Added checks if Python Interpreters have all required modules 93 | - Added `OutputChannel` for logging client server 94 | - Added `StatusBar` icon 95 | - Added more commands for debugging 96 | 97 | ### Changed 98 | 99 | - Increased version node modules (e.g. `vscode-languageclient`) 100 | 101 | ## [0.1.0] - 12/01/2023 102 | 103 | ### Added 104 | 105 | - Added `Hover` functionality 106 | - Resolving spaCy registry entries through hover display (e.g `@architecture`, `factory`, `@tokenizer`, etc.) 107 | 108 | ### Changed 109 | 110 | - Moved from `pygls` v0.13.1 to v1.0.0 111 | -------------------------------------------------------------------------------- /DEVELOPER_README.md: -------------------------------------------------------------------------------- 1 | # spaCy VSCode Extension 2 | 3 | Version 1.0.1 4 | 5 | ## Introduction 6 | 7 | This VSCode extension is designed to help users with spaCy's configuration files (`.cfg`) by enabling hover features that give more context to users about architectures, variables and sections and provides features like autocompletion, validation and other "quality of life features" for working with the config system. 8 | 9 | ## Language Server Protocol 10 | 11 | For the extension we need spaCy functionality (registry lookups, autocompletion, etc.), but since VScode runs on `Node.js` we can't use Python natively. For these specific cases we can use [LSP (Language Server Protocol)](https://microsoft.github.io/language-server-protocol/overviews/lsp/overview/) which allows us to create a Language Server written in any language to communicate with the VScode extension client. For our Python Language Server we use [pygls (pronounced py-glass)](https://github.com/openlawlibrary/pygls) which has all the LSP functionality implemented. We have two main folders [`client`](./extension/client/) (TypeScript, client-side code) and [`server`](./extension/server/) (Python, server-side code). 12 | 13 | > More ressources about `LSP` and `pygls` here: 14 | > [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/) 15 | 16 | > [pygls Docs](https://pygls.readthedocs.io/en/latest/) 17 | 18 | ### Setup for development 19 | 20 | Make sure you have `Node >= 18.6.0` installed and use `npm install` to install all node modules. Then create a virtual python environment and install the following python requirements: 21 | 22 | - `pygls >= 1.0.0` 23 | - `spaCy >= 3.4.0` 24 | 25 | > You can also use `pip install -r requirement.txt`. 26 | 27 | Create the file `setting.json` in the `.vscode/` folder and add the following line `"python.defaultInterpreterPath": ""`. This makes sure that VScode uses your specified python environment when developing and testing the extension. 28 | 29 | ## How to run the extension (Development) 30 | 31 | Use `F5` or the Debug menu to run `DEBUG MODE`, after that a debug symbol will appear on the bottom left. 32 | 33 | > All possible launch settings are here `.vscode/launch.json` 34 | 35 | Most of the feature logic will go into in the [`server.py` file](.server/server.py). 36 | 37 | ### Project structure 38 | 39 | For every feature, there will be a dedicated script (e.g. `feature_hover.py`) which will implement all the required functionality. They will be used in the `server.py` script to link the functions to their respective event (e.g. `@spacy_server.feature(HOVER)`). If a function/method can be reused for other features, you can move it to the `util.py` script. 40 | 41 | ### Extension Features 42 | 43 | #### Hover Functionality 44 | 45 | The hover feature provides three different types of information. 46 | 47 | 1. **The function registry** 48 | Functions within the config file are registered within [spaCy's registry system](https://spacy.io/api/top-level#registry). When one of these functions is hovered over, the feature will provide information about the function and its arguments, along with a link to the code for the function, if available. 49 | 50 | 2. **Resolving references to variables** 51 | Variables are denoted in the config file as `${}`. When a variable is hovered over, the feature will provide the value of that variable specified in the config file. 52 | 53 | 3. **Section titles** 54 | The config system is separated by sections such as `[training.batcher]` or `[components]`. When a section, such as "training" or "components", or subsection, such as "batcher", is hovered over, the feature will provide a description of it, if available. 55 | 56 | #### Configurations/Settings 57 | 58 | - `pythonInterpreter = ""` - Use this setting to specify which python interpreter should be used by the extension. The environment needs to have all required modules installed. 59 | 60 | #### Python Environment Management 61 | 62 | The spaCy Extension allows the user to either select a path to their desired python interpreter or use the current used interpreter. The selection can be done by clicking on the `spaCy` status bar which shows a dialog window with the two options. 63 | 64 | ### Building the extension 65 | 66 | To build and publish the extension we use [Visual Studio Code Extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension#vsce) 67 | 68 | > `npm install -g @vscode/vsce`. 69 | 70 | To package the extension use `vsce package` 71 | It will create an installable `.vsix` file which can be used to install the extension locally. 72 | You can right-click on the `.vsix` file to install it to VScode. 73 | 74 | ### Logging / Debugging 75 | 76 | #### Client Server (TypeScript) 77 | 78 | The Client Server creates an Output Channel called `spaCy Extension Log` which outputs information about the current state of the Client Server. You can add logs to it by using `logging.info()`,`logging.warn()`, or `logging.error()`. 79 | 80 | #### Language Server (Python) 81 | 82 | To provide more information of the current state of the Language Server we use `logging.debug` which writes logs to `pygls.log`. 83 | 84 | You can use `server.show_message()` to show vscode message boxes or `server.show_message_log()` to log directly to the `spaCy Extension Log` output channel. 85 | 86 | #### Statusbar 87 | 88 | The extension adds a status bar which can be used to see whether the server is active and to select a python interpreter. 89 | 90 | ### Writing unit tests 91 | 92 | #### Python 93 | 94 | All python tests are contained in the [tests folder](./server/tests/) 95 | Please make sure to have a modules installed, they can be found in the `tests/requirements.txt` file and installed via `pip install -e requirements.txt`. 96 | 97 | - To run all tests use `pytest ./tests` or if you're in the tests folder you can also simply use `pytest` 98 | - To run a specific test file use `pytest tests/test_file.py` 99 | - To run a specific test function in a file use `pytest test/test_file.py::test_function` 100 | 101 | > You can read more about [pytest](https://docs.pytest.org/en/7.2.x/) in their [docs](https://docs.pytest.org/en/7.2.x/how-to/index.html) 102 | 103 | #### TypeScript 104 | 105 | (TODO) 106 | 107 | ### Testing the codebase 108 | 109 | To validate and test the code, please install all requirements listed [here](server/tests/requirements.txt): 110 | 111 | - `pytest` 112 | - `mock` 113 | - `types-mock` 114 | - `mypy` 115 | - `black` 116 | 117 | - Use `mypy server` to check any type errors 118 | - Use `black server --check` to check black formatting 119 | - Use `pytest server` to run all tests 120 | - Use `npm run lint` to lint all typescript code 121 | 122 | We have dedicated test workflows for this on github. 123 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Explosion 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 | # spaCy VSCode Extension 2 | 3 | Version 1.0.1 4 | 5 | The spaCy VSCode Extension provides additional tooling and features for working with spaCy's config files. Version 1.0.0 includes hover descriptions for registry functions, variables, and section names within the config as an installable extension. 6 | 7 | [![spaCy](https://img.shields.io/static/v1?label=made%20with%20%E2%9D%A4%20for&message=spaCy&color=09a3d5&style=flat-square)](https://spacy.io) 8 | 9 | ## 🚀 Quickstart 10 | 11 | - **Step 1.** Install a supported version of Python on your system (`>=3.7`) 12 | - **Step 2.** Install the [Python Extension for Visual Studio Code](https://code.visualstudio.com/docs/python/python-tutorial) 13 | - **Step 3.** Create a [virtual python environment](https://docs.python.org/3/library/venv.html) 14 | - **Step 4.** Install all python requirements 15 | 16 | - `spaCy >= 3.4.0` 17 | - `pygls >= 1.0.0` 18 | 19 | - **Step 5.** Install [spaCy Extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=Explosion.spacy-extension) 20 | - **Step 6.** Select your python environment 21 | 22 | 23 | 24 | - **Step 7.** You are ready to work with `.cfg` files in spaCy! 25 | 26 | ## 🔥 Features 27 | 28 | The extension displays additional information on hover for some components and validates the config file on open. 29 | 30 | 31 | 32 | ### Hover 33 | 34 | The hover feature provides three different types of information. 35 | 36 | 1. **The function registry** 37 | Functions within the config file are registered within [spaCy's registry system](https://spacy.io/api/top-level#registry). When one of these functions is hovered over, the feature will provide information about the function and its arguments, along with a link to the code for the function, if available. 38 | 39 | 2. **Resolving references to variables** 40 | Variables are denoted in the config file as `${}`. When a variable is hovered over, the feature will provide the value of that variable specified in the config file. 41 | 42 | 3. **Section titles** 43 | The config system is separated by sections such as `[training.batcher]` or `[components]`. When a section, such as "training" or "components", or subsection, such as "batcher", is hovered over, the feature will provide a description of it, if available. 44 | 45 | ## ℹ️ Support 46 | 47 | If you have questions about the extension, please ask on the [spaCy discussion forum](https://github.com/explosion/spaCy/discussions). 48 | -------------------------------------------------------------------------------- /client/python_validation.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from distutils.version import LooseVersion 3 | import argparse 4 | 5 | if sys.version_info < (3, 9): 6 | import importlib_metadata as metadata 7 | else: 8 | import importlib.metadata as metadata 9 | 10 | parser = argparse.ArgumentParser(description="Script to validate python interpreter") 11 | parser.add_argument("pygls_version", help="Required version of pygls") 12 | parser.add_argument("spacy_version", help="Required version of spaCy") 13 | args = parser.parse_args() 14 | 15 | 16 | try: 17 | pygls_version = metadata.version("pygls") 18 | if LooseVersion(pygls_version) >= LooseVersion(args.pygls_version): 19 | spacy_version = metadata.version("spacy") 20 | try: 21 | if LooseVersion(spacy_version) >= LooseVersion(args.spacy_version): 22 | sys.stdout.write("I003") 23 | sys.exit() 24 | else: 25 | sys.stdout.write("E009") 26 | sys.exit() 27 | except ModuleNotFoundError as e: 28 | sys.stdout.write("E007") 29 | sys.exit() 30 | else: 31 | sys.stdout.write("E008") 32 | sys.exit() 33 | 34 | except ModuleNotFoundError as e: 35 | sys.stdout.write("E006") 36 | sys.exit() 37 | -------------------------------------------------------------------------------- /client/src/client_constants.ts: -------------------------------------------------------------------------------- 1 | export const spacy_version = "3.4.4"; 2 | export const pygls_version = "1.0.0"; 3 | export const python_args = pygls_version + " " + spacy_version; 4 | 5 | export const errors = { 6 | E001: "[E001] Python Extension not installed ", 7 | E002: "[E002] Selected python interpreter path does not exist: ", 8 | E003: "[E003] Missing modules to run spaCy Extension: ", 9 | E004: "[E004] Module versions not compatible: ", 10 | E005: "[E005] Error when using python interpreter: ", 11 | E006: "[E006] Module pygls not found ", 12 | E007: "[E007] Module spaCy not found ", 13 | E008: 14 | "[E008] Version of pygls not compatible. Please make sure your pygls version is >=" + 15 | pygls_version, 16 | E009: 17 | "[E009] Version of spaCy not compatible. Please make sure your spaCy version is >=" + 18 | spacy_version, 19 | E010: "[E010] Python Interpreter not compatible", 20 | }; 21 | 22 | export const warnings = { 23 | W001: "[W001] Please select a python interpreter ", 24 | }; 25 | 26 | export const infos = { 27 | I001: "[I001] spaCy Extension started ", 28 | I002: "[I002] spaCy Extension stopped ", 29 | I003: "[I003] Python interpreter compatible: ", 30 | }; 31 | 32 | export const status = { 33 | S001: "spaCy Extension active on: ", 34 | S002: "spaCy Extension not active. Please select Python interpreter.", 35 | S003: "Selected python interpreter not compatible. See the output for more information.", 36 | }; 37 | -------------------------------------------------------------------------------- /client/src/extension.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | import * as path from "path"; 4 | import { ExtensionContext, ExtensionMode, workspace } from "vscode"; 5 | import * as vscode from "vscode"; 6 | import { 7 | LanguageClient, 8 | LanguageClientOptions, 9 | ServerOptions, 10 | } from "vscode-languageclient/node"; 11 | import { exec } from "child_process"; 12 | 13 | import { 14 | python_args, 15 | warnings, // eslint-disable-line 16 | infos, 17 | errors, 18 | status, 19 | } from "./client_constants"; 20 | 21 | import * as fs from "fs"; // eslint-disable-line 22 | 23 | // Server 24 | let client: LanguageClient; 25 | 26 | // Status Logging 27 | const logging = vscode.window.createOutputChannel("spaCy Extension Log", { 28 | log: true, 29 | }); 30 | logging.show(); 31 | 32 | let statusBar: vscode.StatusBarItem; 33 | let clientActive = false; 34 | 35 | // Environment Compatibility 36 | let currentPythonEnvironment = "None"; 37 | 38 | const clientOptions: LanguageClientOptions = { 39 | // Register the server for .cfg files 40 | documentSelector: [ 41 | { scheme: "file", pattern: "**/*.cfg" }, 42 | { scheme: "untitled", pattern: "**/*.cfg" }, 43 | ], 44 | outputChannel: logging, 45 | synchronize: { 46 | // Notify the server about file changes to '.clientrc files contain in the workspace 47 | fileEvents: workspace.createFileSystemWatcher("**/.clientrc"), 48 | }, 49 | }; 50 | 51 | // Server Functionality 52 | function startLangServer( 53 | command: string, 54 | args: string[], 55 | cwd: string 56 | ): LanguageClient { 57 | /** 58 | * Starts the client server 59 | */ 60 | const serverOptions: ServerOptions = { 61 | args, 62 | command, 63 | options: { cwd }, 64 | }; 65 | return new LanguageClient(command, serverOptions, clientOptions); 66 | } 67 | 68 | async function startProduction() { 69 | /** 70 | * Starts the client and python server 71 | * @returns LanguageClient 72 | */ 73 | const cwd = path.join(__dirname, "..", ".."); 74 | // Check whether active python environment has all modules installed (pygls, spacy) 75 | const python_interpreter_compat = await verifyPythonEnvironment( 76 | currentPythonEnvironment 77 | ); 78 | if (python_interpreter_compat.includes("I")) { 79 | return startLangServer( 80 | currentPythonEnvironment + "", 81 | ["-m", "server"], 82 | cwd 83 | ); 84 | } else { 85 | showServerStatus(); 86 | } 87 | } 88 | 89 | async function restartClient() { 90 | // Restart the server 91 | if (client) { 92 | await client.stop(); 93 | setClientActiveStatus(false); 94 | } 95 | client = await startProduction(); 96 | if (client) { 97 | await client.start(); 98 | setClientActiveStatus(true); 99 | } 100 | } 101 | 102 | async function showServerStatus() { 103 | // Return current status of the server and enable user to select new interpreter 104 | const options: vscode.MessageOptions = { detail: "", modal: false }; 105 | const option_select_interpreter = "Select interpreter"; 106 | const option_current_interpreter = "Select current interpreter"; 107 | 108 | let message: string; 109 | let pythonPath: string; 110 | const cwd = path.join(__dirname, "..", ".."); 111 | 112 | if (clientActive) { 113 | message = status["S001"] + currentPythonEnvironment; 114 | } else { 115 | message = status["S002"]; 116 | } 117 | 118 | const selection = await vscode.window.showInformationMessage( 119 | message, 120 | options, 121 | ...[option_select_interpreter, option_current_interpreter] 122 | ); 123 | 124 | if (selection == option_select_interpreter) { 125 | // Select python interpreter from file system 126 | logging.info("Selecting from Python Interpreter from Directory"); 127 | const uris = await vscode.window.showOpenDialog({ 128 | filters: {}, 129 | canSelectFiles: false, 130 | canSelectFolders: true, 131 | canSelectMany: false, 132 | openLabel: "Select python interpreter", 133 | }); 134 | if (uris) { 135 | pythonPath = getPythonExec(uris[0].fsPath); 136 | } 137 | } else if (selection == option_current_interpreter) { 138 | // Select current python interpreter 139 | logging.info("Selecting current Python Interpreter"); 140 | pythonPath = await vscode.commands.executeCommand( 141 | "python.interpreterPath", 142 | { workspaceFolder: cwd } 143 | ); 144 | } 145 | 146 | if (pythonPath) { 147 | logging.info("Python Path retrieved: " + pythonPath); 148 | const pythonSet = await setPythonEnvironment(pythonPath); 149 | if (pythonSet) { 150 | restartClient(); 151 | } else { 152 | vscode.window.showWarningMessage(status["S003"]); 153 | } 154 | } else { 155 | logging.info("Python Path could not be retrieved"); 156 | } 157 | } 158 | 159 | function getAllFiles(dir: string, _files: string[] = []): string[] { 160 | /** Get all files and sub-files from a directory */ 161 | const filter = ["bin", "Scripts", "shims"]; 162 | _files = _files || []; 163 | const files = fs.readdirSync(dir); 164 | for (const i in files) { 165 | const name = dir + "/" + files[i]; 166 | if (fs.statSync(name).isDirectory() && filter.includes(files[i])) { 167 | getAllFiles(name, _files); 168 | } else if (files[i].includes("python")) { 169 | _files.push(name); 170 | } 171 | } 172 | return _files; 173 | } 174 | 175 | function getPythonExec(dir: string): string { 176 | /** Return path of python executable of a list of files */ 177 | const files = getAllFiles(dir, []); 178 | for (const i in files) { 179 | if (files[i].endsWith("python") || files[i].endsWith("python.exe")) { 180 | return files[i]; 181 | } 182 | } 183 | return dir; 184 | } 185 | 186 | // Python Functionality 187 | async function setPythonEnvironment(pythonPath: string) { 188 | /** 189 | * Verify python environment and set it as currentPythonEnvironment and make it persistent 190 | * @param pythonPath - Path to the interpreter 191 | * @returns boolean - Whether the verification succeeded or failed 192 | */ 193 | if (!fs.existsSync(pythonPath)) { 194 | logging.error(errors["E003"] + pythonPath); 195 | return false; 196 | } 197 | const python_interpreter_compat = await verifyPythonEnvironment(pythonPath); 198 | if (python_interpreter_compat.includes("E")) { 199 | logging.error(errors[python_interpreter_compat]); 200 | return false; 201 | } else if (python_interpreter_compat.includes("I")) { 202 | currentPythonEnvironment = pythonPath; 203 | workspace 204 | .getConfiguration("spacy-extension") 205 | .update("pythonInterpreter", currentPythonEnvironment); 206 | logging.info(infos[python_interpreter_compat] + currentPythonEnvironment); 207 | return true; 208 | } else { 209 | logging.error(errors["E010"]); 210 | return false; 211 | } 212 | } 213 | 214 | async function verifyPythonEnvironment(pythonPath: string): Promise { 215 | /** 216 | * Runs a child process to verify whether the selected python environment has all modules 217 | * @param pythonPath - Path to the python environment 218 | * @returns Promise 219 | */ 220 | 221 | return await importPythonCommand( 222 | pythonPath + 223 | ` ${path.join( 224 | __dirname, 225 | "..", 226 | "..", 227 | "client", 228 | "python_validation.py" 229 | )} ` + 230 | python_args 231 | ); 232 | } 233 | 234 | function importPythonCommand(cmd): Promise { 235 | /** 236 | * Starts a child process and runs the python import command 237 | * Handles whether python modules are missing or the wrong versions are installed 238 | * @param cmd: string - Import command to execute 239 | * @returns Promise 240 | */ 241 | return new Promise((resolve, reject) => { 242 | exec(cmd, (error, stdout, stderr) => { 243 | resolve(stdout); 244 | }); 245 | }); 246 | } 247 | 248 | // Helper Functions 249 | function setupStatusBar() { 250 | // Setup Status Bar 251 | statusBar = vscode.window.createStatusBarItem( 252 | vscode.StatusBarAlignment.Right, 253 | 100 254 | ); 255 | statusBar.command = "spacy-extension.showStatus"; 256 | statusBar.color = "red"; 257 | statusBar.tooltip = "Get the status of the spaCy Extension"; 258 | statusBar.text = "spaCy"; 259 | statusBar.show(); 260 | 261 | return statusBar; 262 | } 263 | 264 | function setClientActiveStatus(b: boolean) { 265 | /** 266 | * Set the status bar color depending whether the client is active or not 267 | * @params b: boolean - Is Client Active? 268 | */ 269 | clientActive = b; 270 | if (clientActive) { 271 | statusBar.color = new vscode.ThemeColor("activityBar.foreground"); 272 | logging.info(infos["I001"]); 273 | } else { 274 | statusBar.color = "red"; 275 | logging.info(infos["I002"]); 276 | } 277 | } 278 | 279 | export async function activate(context: ExtensionContext) { 280 | // Check if Python Extension is installed 281 | if (!vscode.extensions.getExtension("ms-python.python")) { 282 | logging.error(errors["E001"]); 283 | return null; 284 | } 285 | 286 | const _showStatus = vscode.commands.registerCommand( 287 | "spacy-extension.showStatus", 288 | showServerStatus 289 | ); 290 | context.subscriptions.push(_showStatus); 291 | 292 | context.subscriptions.push(setupStatusBar()); 293 | 294 | // Start Client 295 | if (context.extensionMode === ExtensionMode.Development) { 296 | // Development 297 | const settings = require("../../.vscode/settings.json"); // eslint-disable-line 298 | currentPythonEnvironment = getPythonExec( 299 | settings["python.defaultInterpreterPath"] 300 | ); 301 | } else { 302 | // Production 303 | currentPythonEnvironment = workspace 304 | .getConfiguration("spacy-extension") 305 | .get("pythonInterpreter"); 306 | } 307 | 308 | await setPythonEnvironment(currentPythonEnvironment); 309 | client = await startProduction(); 310 | 311 | if (client) { 312 | await client.start(); 313 | setClientActiveStatus(true); 314 | } 315 | } 316 | 317 | export function deactivate(): Thenable { 318 | setClientActiveStatus(false); 319 | statusBar.hide(); 320 | return client ? client.stop() : Promise.resolve(); 321 | } 322 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/explosion/spacy-vscode/9fa92737b967e85ef0d0c8019c3004c3e249c9f2/icon.png -------------------------------------------------------------------------------- /images/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/explosion/spacy-vscode/9fa92737b967e85ef0d0c8019c3004c3e249c9f2/images/.DS_Store -------------------------------------------------------------------------------- /images/extension_features.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/explosion/spacy-vscode/9fa92737b967e85ef0d0c8019c3004c3e249c9f2/images/extension_features.gif -------------------------------------------------------------------------------- /images/extension_python_env.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/explosion/spacy-vscode/9fa92737b967e85ef0d0c8019c3004c3e249c9f2/images/extension_python_env.gif -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spacy-extension", 3 | "version": "1.0.1", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "spacy-extension", 9 | "version": "1.0.1", 10 | "license": "MIT", 11 | "dependencies": { 12 | "vscode-languageclient": "^8.0.2" 13 | }, 14 | "devDependencies": { 15 | "@types/node": "16.11.43", 16 | "@types/vscode": "^1.74.0", 17 | "@typescript-eslint/eslint-plugin": "^5.3.0", 18 | "@typescript-eslint/parser": "^5.3.0", 19 | "eslint": "^8.2.0", 20 | "typescript": "^4.4.4" 21 | }, 22 | "engines": { 23 | "vscode": "^1.74.0" 24 | } 25 | }, 26 | "node_modules/@eslint/eslintrc": { 27 | "version": "1.0.4", 28 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz", 29 | "integrity": "sha512-h8Vx6MdxwWI2WM8/zREHMoqdgLNXEL4QX3MWSVMdyNJGvXVOs+6lp+m2hc3FnuMHDc4poxFNI20vCk0OmI4G0Q==", 30 | "dev": true, 31 | "dependencies": { 32 | "ajv": "^6.12.4", 33 | "debug": "^4.3.2", 34 | "espree": "^9.0.0", 35 | "globals": "^13.9.0", 36 | "ignore": "^4.0.6", 37 | "import-fresh": "^3.2.1", 38 | "js-yaml": "^4.1.0", 39 | "minimatch": "^3.0.4", 40 | "strip-json-comments": "^3.1.1" 41 | }, 42 | "engines": { 43 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 44 | } 45 | }, 46 | "node_modules/@eslint/eslintrc/node_modules/ignore": { 47 | "version": "4.0.6", 48 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 49 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 50 | "dev": true, 51 | "engines": { 52 | "node": ">= 4" 53 | } 54 | }, 55 | "node_modules/@humanwhocodes/config-array": { 56 | "version": "0.6.0", 57 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", 58 | "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==", 59 | "dev": true, 60 | "dependencies": { 61 | "@humanwhocodes/object-schema": "^1.2.0", 62 | "debug": "^4.1.1", 63 | "minimatch": "^3.0.4" 64 | }, 65 | "engines": { 66 | "node": ">=10.10.0" 67 | } 68 | }, 69 | "node_modules/@humanwhocodes/object-schema": { 70 | "version": "1.2.1", 71 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", 72 | "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", 73 | "dev": true 74 | }, 75 | "node_modules/@nodelib/fs.scandir": { 76 | "version": "2.1.5", 77 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 78 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 79 | "dev": true, 80 | "dependencies": { 81 | "@nodelib/fs.stat": "2.0.5", 82 | "run-parallel": "^1.1.9" 83 | }, 84 | "engines": { 85 | "node": ">= 8" 86 | } 87 | }, 88 | "node_modules/@nodelib/fs.stat": { 89 | "version": "2.0.5", 90 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 91 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 92 | "dev": true, 93 | "engines": { 94 | "node": ">= 8" 95 | } 96 | }, 97 | "node_modules/@nodelib/fs.walk": { 98 | "version": "1.2.8", 99 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 100 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 101 | "dev": true, 102 | "dependencies": { 103 | "@nodelib/fs.scandir": "2.1.5", 104 | "fastq": "^1.6.0" 105 | }, 106 | "engines": { 107 | "node": ">= 8" 108 | } 109 | }, 110 | "node_modules/@types/json-schema": { 111 | "version": "7.0.9", 112 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", 113 | "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", 114 | "dev": true 115 | }, 116 | "node_modules/@types/node": { 117 | "version": "16.11.43", 118 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.43.tgz", 119 | "integrity": "sha512-GqWykok+3uocgfAJM8imbozrqLnPyTrpFlrryURQlw1EesPUCx5XxTiucWDSFF9/NUEXDuD4bnvHm8xfVGWTpQ==", 120 | "dev": true 121 | }, 122 | "node_modules/@types/vscode": { 123 | "version": "1.74.0", 124 | "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.74.0.tgz", 125 | "integrity": "sha512-LyeCIU3jb9d38w0MXFwta9r0Jx23ugujkAxdwLTNCyspdZTKUc43t7ppPbCiPoQ/Ivd/pnDFZrb4hWd45wrsgA==", 126 | "dev": true 127 | }, 128 | "node_modules/@typescript-eslint/eslint-plugin": { 129 | "version": "5.3.0", 130 | "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.3.0.tgz", 131 | "integrity": "sha512-ARUEJHJrq85aaiCqez7SANeahDsJTD3AEua34EoQN9pHS6S5Bq9emcIaGGySt/4X2zSi+vF5hAH52sEen7IO7g==", 132 | "dev": true, 133 | "dependencies": { 134 | "@typescript-eslint/experimental-utils": "5.3.0", 135 | "@typescript-eslint/scope-manager": "5.3.0", 136 | "debug": "^4.3.2", 137 | "functional-red-black-tree": "^1.0.1", 138 | "ignore": "^5.1.8", 139 | "regexpp": "^3.2.0", 140 | "semver": "^7.3.5", 141 | "tsutils": "^3.21.0" 142 | }, 143 | "engines": { 144 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 145 | }, 146 | "funding": { 147 | "type": "opencollective", 148 | "url": "https://opencollective.com/typescript-eslint" 149 | }, 150 | "peerDependencies": { 151 | "@typescript-eslint/parser": "^5.0.0", 152 | "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" 153 | }, 154 | "peerDependenciesMeta": { 155 | "typescript": { 156 | "optional": true 157 | } 158 | } 159 | }, 160 | "node_modules/@typescript-eslint/experimental-utils": { 161 | "version": "5.3.0", 162 | "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.3.0.tgz", 163 | "integrity": "sha512-NFVxYTjKj69qB0FM+piah1x3G/63WB8vCBMnlnEHUsiLzXSTWb9FmFn36FD9Zb4APKBLY3xRArOGSMQkuzTF1w==", 164 | "dev": true, 165 | "dependencies": { 166 | "@types/json-schema": "^7.0.9", 167 | "@typescript-eslint/scope-manager": "5.3.0", 168 | "@typescript-eslint/types": "5.3.0", 169 | "@typescript-eslint/typescript-estree": "5.3.0", 170 | "eslint-scope": "^5.1.1", 171 | "eslint-utils": "^3.0.0" 172 | }, 173 | "engines": { 174 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 175 | }, 176 | "funding": { 177 | "type": "opencollective", 178 | "url": "https://opencollective.com/typescript-eslint" 179 | }, 180 | "peerDependencies": { 181 | "eslint": "*" 182 | } 183 | }, 184 | "node_modules/@typescript-eslint/parser": { 185 | "version": "5.3.0", 186 | "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.3.0.tgz", 187 | "integrity": "sha512-rKu/yAReip7ovx8UwOAszJVO5MgBquo8WjIQcp1gx4pYQCwYzag+I5nVNHO4MqyMkAo0gWt2gWUi+36gWAVKcw==", 188 | "dev": true, 189 | "dependencies": { 190 | "@typescript-eslint/scope-manager": "5.3.0", 191 | "@typescript-eslint/types": "5.3.0", 192 | "@typescript-eslint/typescript-estree": "5.3.0", 193 | "debug": "^4.3.2" 194 | }, 195 | "engines": { 196 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 197 | }, 198 | "funding": { 199 | "type": "opencollective", 200 | "url": "https://opencollective.com/typescript-eslint" 201 | }, 202 | "peerDependencies": { 203 | "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" 204 | }, 205 | "peerDependenciesMeta": { 206 | "typescript": { 207 | "optional": true 208 | } 209 | } 210 | }, 211 | "node_modules/@typescript-eslint/scope-manager": { 212 | "version": "5.3.0", 213 | "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.3.0.tgz", 214 | "integrity": "sha512-22Uic9oRlTsPppy5Tcwfj+QET5RWEnZ5414Prby465XxQrQFZ6nnm5KnXgnsAJefG4hEgMnaxTB3kNEyjdjj6A==", 215 | "dev": true, 216 | "dependencies": { 217 | "@typescript-eslint/types": "5.3.0", 218 | "@typescript-eslint/visitor-keys": "5.3.0" 219 | }, 220 | "engines": { 221 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 222 | }, 223 | "funding": { 224 | "type": "opencollective", 225 | "url": "https://opencollective.com/typescript-eslint" 226 | } 227 | }, 228 | "node_modules/@typescript-eslint/types": { 229 | "version": "5.3.0", 230 | "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.3.0.tgz", 231 | "integrity": "sha512-fce5pG41/w8O6ahQEhXmMV+xuh4+GayzqEogN24EK+vECA3I6pUwKuLi5QbXO721EMitpQne5VKXofPonYlAQg==", 232 | "dev": true, 233 | "engines": { 234 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 235 | }, 236 | "funding": { 237 | "type": "opencollective", 238 | "url": "https://opencollective.com/typescript-eslint" 239 | } 240 | }, 241 | "node_modules/@typescript-eslint/typescript-estree": { 242 | "version": "5.3.0", 243 | "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.3.0.tgz", 244 | "integrity": "sha512-FJ0nqcaUOpn/6Z4Jwbtf+o0valjBLkqc3MWkMvrhA2TvzFXtcclIM8F4MBEmYa2kgcI8EZeSAzwoSrIC8JYkug==", 245 | "dev": true, 246 | "dependencies": { 247 | "@typescript-eslint/types": "5.3.0", 248 | "@typescript-eslint/visitor-keys": "5.3.0", 249 | "debug": "^4.3.2", 250 | "globby": "^11.0.4", 251 | "is-glob": "^4.0.3", 252 | "semver": "^7.3.5", 253 | "tsutils": "^3.21.0" 254 | }, 255 | "engines": { 256 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 257 | }, 258 | "funding": { 259 | "type": "opencollective", 260 | "url": "https://opencollective.com/typescript-eslint" 261 | }, 262 | "peerDependenciesMeta": { 263 | "typescript": { 264 | "optional": true 265 | } 266 | } 267 | }, 268 | "node_modules/@typescript-eslint/visitor-keys": { 269 | "version": "5.3.0", 270 | "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.3.0.tgz", 271 | "integrity": "sha512-oVIAfIQuq0x2TFDNLVavUn548WL+7hdhxYn+9j3YdJJXB7mH9dAmZNJsPDa7Jc+B9WGqoiex7GUDbyMxV0a/aw==", 272 | "dev": true, 273 | "dependencies": { 274 | "@typescript-eslint/types": "5.3.0", 275 | "eslint-visitor-keys": "^3.0.0" 276 | }, 277 | "engines": { 278 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 279 | }, 280 | "funding": { 281 | "type": "opencollective", 282 | "url": "https://opencollective.com/typescript-eslint" 283 | } 284 | }, 285 | "node_modules/acorn": { 286 | "version": "8.5.0", 287 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", 288 | "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", 289 | "dev": true, 290 | "bin": { 291 | "acorn": "bin/acorn" 292 | }, 293 | "engines": { 294 | "node": ">=0.4.0" 295 | } 296 | }, 297 | "node_modules/acorn-jsx": { 298 | "version": "5.3.2", 299 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 300 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 301 | "dev": true, 302 | "peerDependencies": { 303 | "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" 304 | } 305 | }, 306 | "node_modules/ajv": { 307 | "version": "6.12.6", 308 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 309 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 310 | "dev": true, 311 | "dependencies": { 312 | "fast-deep-equal": "^3.1.1", 313 | "fast-json-stable-stringify": "^2.0.0", 314 | "json-schema-traverse": "^0.4.1", 315 | "uri-js": "^4.2.2" 316 | }, 317 | "funding": { 318 | "type": "github", 319 | "url": "https://github.com/sponsors/epoberezkin" 320 | } 321 | }, 322 | "node_modules/ansi-colors": { 323 | "version": "4.1.1", 324 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 325 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 326 | "dev": true, 327 | "engines": { 328 | "node": ">=6" 329 | } 330 | }, 331 | "node_modules/ansi-regex": { 332 | "version": "5.0.1", 333 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 334 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 335 | "dev": true, 336 | "engines": { 337 | "node": ">=8" 338 | } 339 | }, 340 | "node_modules/ansi-styles": { 341 | "version": "4.3.0", 342 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 343 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 344 | "dev": true, 345 | "dependencies": { 346 | "color-convert": "^2.0.1" 347 | }, 348 | "engines": { 349 | "node": ">=8" 350 | }, 351 | "funding": { 352 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 353 | } 354 | }, 355 | "node_modules/argparse": { 356 | "version": "2.0.1", 357 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 358 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 359 | "dev": true 360 | }, 361 | "node_modules/array-union": { 362 | "version": "2.1.0", 363 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", 364 | "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", 365 | "dev": true, 366 | "engines": { 367 | "node": ">=8" 368 | } 369 | }, 370 | "node_modules/balanced-match": { 371 | "version": "1.0.2", 372 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 373 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 374 | }, 375 | "node_modules/brace-expansion": { 376 | "version": "1.1.11", 377 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 378 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 379 | "dependencies": { 380 | "balanced-match": "^1.0.0", 381 | "concat-map": "0.0.1" 382 | } 383 | }, 384 | "node_modules/braces": { 385 | "version": "3.0.2", 386 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 387 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 388 | "dev": true, 389 | "dependencies": { 390 | "fill-range": "^7.0.1" 391 | }, 392 | "engines": { 393 | "node": ">=8" 394 | } 395 | }, 396 | "node_modules/callsites": { 397 | "version": "3.1.0", 398 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 399 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 400 | "dev": true, 401 | "engines": { 402 | "node": ">=6" 403 | } 404 | }, 405 | "node_modules/chalk": { 406 | "version": "4.1.2", 407 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 408 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 409 | "dev": true, 410 | "dependencies": { 411 | "ansi-styles": "^4.1.0", 412 | "supports-color": "^7.1.0" 413 | }, 414 | "engines": { 415 | "node": ">=10" 416 | }, 417 | "funding": { 418 | "url": "https://github.com/chalk/chalk?sponsor=1" 419 | } 420 | }, 421 | "node_modules/color-convert": { 422 | "version": "2.0.1", 423 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 424 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 425 | "dev": true, 426 | "dependencies": { 427 | "color-name": "~1.1.4" 428 | }, 429 | "engines": { 430 | "node": ">=7.0.0" 431 | } 432 | }, 433 | "node_modules/color-name": { 434 | "version": "1.1.4", 435 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 436 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 437 | "dev": true 438 | }, 439 | "node_modules/concat-map": { 440 | "version": "0.0.1", 441 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 442 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 443 | }, 444 | "node_modules/cross-spawn": { 445 | "version": "7.0.3", 446 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 447 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 448 | "dev": true, 449 | "dependencies": { 450 | "path-key": "^3.1.0", 451 | "shebang-command": "^2.0.0", 452 | "which": "^2.0.1" 453 | }, 454 | "engines": { 455 | "node": ">= 8" 456 | } 457 | }, 458 | "node_modules/debug": { 459 | "version": "4.3.2", 460 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", 461 | "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", 462 | "dev": true, 463 | "dependencies": { 464 | "ms": "2.1.2" 465 | }, 466 | "engines": { 467 | "node": ">=6.0" 468 | }, 469 | "peerDependenciesMeta": { 470 | "supports-color": { 471 | "optional": true 472 | } 473 | } 474 | }, 475 | "node_modules/deep-is": { 476 | "version": "0.1.4", 477 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 478 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", 479 | "dev": true 480 | }, 481 | "node_modules/dir-glob": { 482 | "version": "3.0.1", 483 | "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", 484 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", 485 | "dev": true, 486 | "dependencies": { 487 | "path-type": "^4.0.0" 488 | }, 489 | "engines": { 490 | "node": ">=8" 491 | } 492 | }, 493 | "node_modules/doctrine": { 494 | "version": "3.0.0", 495 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 496 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 497 | "dev": true, 498 | "dependencies": { 499 | "esutils": "^2.0.2" 500 | }, 501 | "engines": { 502 | "node": ">=6.0.0" 503 | } 504 | }, 505 | "node_modules/enquirer": { 506 | "version": "2.3.6", 507 | "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", 508 | "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", 509 | "dev": true, 510 | "dependencies": { 511 | "ansi-colors": "^4.1.1" 512 | }, 513 | "engines": { 514 | "node": ">=8.6" 515 | } 516 | }, 517 | "node_modules/escape-string-regexp": { 518 | "version": "4.0.0", 519 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 520 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 521 | "dev": true, 522 | "engines": { 523 | "node": ">=10" 524 | }, 525 | "funding": { 526 | "url": "https://github.com/sponsors/sindresorhus" 527 | } 528 | }, 529 | "node_modules/eslint": { 530 | "version": "8.2.0", 531 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.2.0.tgz", 532 | "integrity": "sha512-erw7XmM+CLxTOickrimJ1SiF55jiNlVSp2qqm0NuBWPtHYQCegD5ZMaW0c3i5ytPqL+SSLaCxdvQXFPLJn+ABw==", 533 | "dev": true, 534 | "dependencies": { 535 | "@eslint/eslintrc": "^1.0.4", 536 | "@humanwhocodes/config-array": "^0.6.0", 537 | "ajv": "^6.10.0", 538 | "chalk": "^4.0.0", 539 | "cross-spawn": "^7.0.2", 540 | "debug": "^4.3.2", 541 | "doctrine": "^3.0.0", 542 | "enquirer": "^2.3.5", 543 | "escape-string-regexp": "^4.0.0", 544 | "eslint-scope": "^6.0.0", 545 | "eslint-utils": "^3.0.0", 546 | "eslint-visitor-keys": "^3.0.0", 547 | "espree": "^9.0.0", 548 | "esquery": "^1.4.0", 549 | "esutils": "^2.0.2", 550 | "fast-deep-equal": "^3.1.3", 551 | "file-entry-cache": "^6.0.1", 552 | "functional-red-black-tree": "^1.0.1", 553 | "glob-parent": "^6.0.1", 554 | "globals": "^13.6.0", 555 | "ignore": "^4.0.6", 556 | "import-fresh": "^3.0.0", 557 | "imurmurhash": "^0.1.4", 558 | "is-glob": "^4.0.0", 559 | "js-yaml": "^4.1.0", 560 | "json-stable-stringify-without-jsonify": "^1.0.1", 561 | "levn": "^0.4.1", 562 | "lodash.merge": "^4.6.2", 563 | "minimatch": "^3.0.4", 564 | "natural-compare": "^1.4.0", 565 | "optionator": "^0.9.1", 566 | "progress": "^2.0.0", 567 | "regexpp": "^3.2.0", 568 | "semver": "^7.2.1", 569 | "strip-ansi": "^6.0.1", 570 | "strip-json-comments": "^3.1.0", 571 | "text-table": "^0.2.0", 572 | "v8-compile-cache": "^2.0.3" 573 | }, 574 | "bin": { 575 | "eslint": "bin/eslint.js" 576 | }, 577 | "engines": { 578 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 579 | }, 580 | "funding": { 581 | "url": "https://opencollective.com/eslint" 582 | } 583 | }, 584 | "node_modules/eslint-scope": { 585 | "version": "5.1.1", 586 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", 587 | "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", 588 | "dev": true, 589 | "dependencies": { 590 | "esrecurse": "^4.3.0", 591 | "estraverse": "^4.1.1" 592 | }, 593 | "engines": { 594 | "node": ">=8.0.0" 595 | } 596 | }, 597 | "node_modules/eslint-utils": { 598 | "version": "3.0.0", 599 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", 600 | "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", 601 | "dev": true, 602 | "dependencies": { 603 | "eslint-visitor-keys": "^2.0.0" 604 | }, 605 | "engines": { 606 | "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" 607 | }, 608 | "funding": { 609 | "url": "https://github.com/sponsors/mysticatea" 610 | }, 611 | "peerDependencies": { 612 | "eslint": ">=5" 613 | } 614 | }, 615 | "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { 616 | "version": "2.1.0", 617 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", 618 | "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", 619 | "dev": true, 620 | "engines": { 621 | "node": ">=10" 622 | } 623 | }, 624 | "node_modules/eslint-visitor-keys": { 625 | "version": "3.0.0", 626 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz", 627 | "integrity": "sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==", 628 | "dev": true, 629 | "engines": { 630 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 631 | } 632 | }, 633 | "node_modules/eslint/node_modules/eslint-scope": { 634 | "version": "6.0.0", 635 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-6.0.0.tgz", 636 | "integrity": "sha512-uRDL9MWmQCkaFus8RF5K9/L/2fn+80yoW3jkD53l4shjCh26fCtvJGasxjUqP5OT87SYTxCVA3BwTUzuELx9kA==", 637 | "dev": true, 638 | "dependencies": { 639 | "esrecurse": "^4.3.0", 640 | "estraverse": "^5.2.0" 641 | }, 642 | "engines": { 643 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 644 | } 645 | }, 646 | "node_modules/eslint/node_modules/estraverse": { 647 | "version": "5.3.0", 648 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 649 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 650 | "dev": true, 651 | "engines": { 652 | "node": ">=4.0" 653 | } 654 | }, 655 | "node_modules/eslint/node_modules/ignore": { 656 | "version": "4.0.6", 657 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 658 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 659 | "dev": true, 660 | "engines": { 661 | "node": ">= 4" 662 | } 663 | }, 664 | "node_modules/espree": { 665 | "version": "9.0.0", 666 | "resolved": "https://registry.npmjs.org/espree/-/espree-9.0.0.tgz", 667 | "integrity": "sha512-r5EQJcYZ2oaGbeR0jR0fFVijGOcwai07/690YRXLINuhmVeRY4UKSAsQPe/0BNuDgwP7Ophoc1PRsr2E3tkbdQ==", 668 | "dev": true, 669 | "dependencies": { 670 | "acorn": "^8.5.0", 671 | "acorn-jsx": "^5.3.1", 672 | "eslint-visitor-keys": "^3.0.0" 673 | }, 674 | "engines": { 675 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 676 | } 677 | }, 678 | "node_modules/esquery": { 679 | "version": "1.4.0", 680 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", 681 | "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", 682 | "dev": true, 683 | "dependencies": { 684 | "estraverse": "^5.1.0" 685 | }, 686 | "engines": { 687 | "node": ">=0.10" 688 | } 689 | }, 690 | "node_modules/esquery/node_modules/estraverse": { 691 | "version": "5.3.0", 692 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 693 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 694 | "dev": true, 695 | "engines": { 696 | "node": ">=4.0" 697 | } 698 | }, 699 | "node_modules/esrecurse": { 700 | "version": "4.3.0", 701 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 702 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 703 | "dev": true, 704 | "dependencies": { 705 | "estraverse": "^5.2.0" 706 | }, 707 | "engines": { 708 | "node": ">=4.0" 709 | } 710 | }, 711 | "node_modules/esrecurse/node_modules/estraverse": { 712 | "version": "5.3.0", 713 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 714 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 715 | "dev": true, 716 | "engines": { 717 | "node": ">=4.0" 718 | } 719 | }, 720 | "node_modules/estraverse": { 721 | "version": "4.3.0", 722 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 723 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 724 | "dev": true, 725 | "engines": { 726 | "node": ">=4.0" 727 | } 728 | }, 729 | "node_modules/esutils": { 730 | "version": "2.0.3", 731 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 732 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 733 | "dev": true, 734 | "engines": { 735 | "node": ">=0.10.0" 736 | } 737 | }, 738 | "node_modules/fast-deep-equal": { 739 | "version": "3.1.3", 740 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 741 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 742 | "dev": true 743 | }, 744 | "node_modules/fast-glob": { 745 | "version": "3.2.7", 746 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", 747 | "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", 748 | "dev": true, 749 | "dependencies": { 750 | "@nodelib/fs.stat": "^2.0.2", 751 | "@nodelib/fs.walk": "^1.2.3", 752 | "glob-parent": "^5.1.2", 753 | "merge2": "^1.3.0", 754 | "micromatch": "^4.0.4" 755 | }, 756 | "engines": { 757 | "node": ">=8" 758 | } 759 | }, 760 | "node_modules/fast-glob/node_modules/glob-parent": { 761 | "version": "5.1.2", 762 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 763 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 764 | "dev": true, 765 | "dependencies": { 766 | "is-glob": "^4.0.1" 767 | }, 768 | "engines": { 769 | "node": ">= 6" 770 | } 771 | }, 772 | "node_modules/fast-json-stable-stringify": { 773 | "version": "2.1.0", 774 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 775 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 776 | "dev": true 777 | }, 778 | "node_modules/fast-levenshtein": { 779 | "version": "2.0.6", 780 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 781 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 782 | "dev": true 783 | }, 784 | "node_modules/fastq": { 785 | "version": "1.13.0", 786 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", 787 | "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", 788 | "dev": true, 789 | "dependencies": { 790 | "reusify": "^1.0.4" 791 | } 792 | }, 793 | "node_modules/file-entry-cache": { 794 | "version": "6.0.1", 795 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", 796 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", 797 | "dev": true, 798 | "dependencies": { 799 | "flat-cache": "^3.0.4" 800 | }, 801 | "engines": { 802 | "node": "^10.12.0 || >=12.0.0" 803 | } 804 | }, 805 | "node_modules/fill-range": { 806 | "version": "7.0.1", 807 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 808 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 809 | "dev": true, 810 | "dependencies": { 811 | "to-regex-range": "^5.0.1" 812 | }, 813 | "engines": { 814 | "node": ">=8" 815 | } 816 | }, 817 | "node_modules/flat-cache": { 818 | "version": "3.0.4", 819 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", 820 | "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", 821 | "dev": true, 822 | "dependencies": { 823 | "flatted": "^3.1.0", 824 | "rimraf": "^3.0.2" 825 | }, 826 | "engines": { 827 | "node": "^10.12.0 || >=12.0.0" 828 | } 829 | }, 830 | "node_modules/flatted": { 831 | "version": "3.2.2", 832 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", 833 | "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", 834 | "dev": true 835 | }, 836 | "node_modules/fs.realpath": { 837 | "version": "1.0.0", 838 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 839 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 840 | "dev": true 841 | }, 842 | "node_modules/functional-red-black-tree": { 843 | "version": "1.0.1", 844 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 845 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 846 | "dev": true 847 | }, 848 | "node_modules/glob": { 849 | "version": "7.2.0", 850 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 851 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 852 | "dev": true, 853 | "dependencies": { 854 | "fs.realpath": "^1.0.0", 855 | "inflight": "^1.0.4", 856 | "inherits": "2", 857 | "minimatch": "^3.0.4", 858 | "once": "^1.3.0", 859 | "path-is-absolute": "^1.0.0" 860 | }, 861 | "engines": { 862 | "node": "*" 863 | }, 864 | "funding": { 865 | "url": "https://github.com/sponsors/isaacs" 866 | } 867 | }, 868 | "node_modules/glob-parent": { 869 | "version": "6.0.2", 870 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", 871 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 872 | "dev": true, 873 | "dependencies": { 874 | "is-glob": "^4.0.3" 875 | }, 876 | "engines": { 877 | "node": ">=10.13.0" 878 | } 879 | }, 880 | "node_modules/globals": { 881 | "version": "13.12.0", 882 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", 883 | "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", 884 | "dev": true, 885 | "dependencies": { 886 | "type-fest": "^0.20.2" 887 | }, 888 | "engines": { 889 | "node": ">=8" 890 | }, 891 | "funding": { 892 | "url": "https://github.com/sponsors/sindresorhus" 893 | } 894 | }, 895 | "node_modules/globby": { 896 | "version": "11.0.4", 897 | "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", 898 | "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", 899 | "dev": true, 900 | "dependencies": { 901 | "array-union": "^2.1.0", 902 | "dir-glob": "^3.0.1", 903 | "fast-glob": "^3.1.1", 904 | "ignore": "^5.1.4", 905 | "merge2": "^1.3.0", 906 | "slash": "^3.0.0" 907 | }, 908 | "engines": { 909 | "node": ">=10" 910 | }, 911 | "funding": { 912 | "url": "https://github.com/sponsors/sindresorhus" 913 | } 914 | }, 915 | "node_modules/has-flag": { 916 | "version": "4.0.0", 917 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 918 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 919 | "dev": true, 920 | "engines": { 921 | "node": ">=8" 922 | } 923 | }, 924 | "node_modules/ignore": { 925 | "version": "5.1.9", 926 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz", 927 | "integrity": "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==", 928 | "dev": true, 929 | "engines": { 930 | "node": ">= 4" 931 | } 932 | }, 933 | "node_modules/import-fresh": { 934 | "version": "3.3.0", 935 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 936 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 937 | "dev": true, 938 | "dependencies": { 939 | "parent-module": "^1.0.0", 940 | "resolve-from": "^4.0.0" 941 | }, 942 | "engines": { 943 | "node": ">=6" 944 | }, 945 | "funding": { 946 | "url": "https://github.com/sponsors/sindresorhus" 947 | } 948 | }, 949 | "node_modules/imurmurhash": { 950 | "version": "0.1.4", 951 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 952 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 953 | "dev": true, 954 | "engines": { 955 | "node": ">=0.8.19" 956 | } 957 | }, 958 | "node_modules/inflight": { 959 | "version": "1.0.6", 960 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 961 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 962 | "dev": true, 963 | "dependencies": { 964 | "once": "^1.3.0", 965 | "wrappy": "1" 966 | } 967 | }, 968 | "node_modules/inherits": { 969 | "version": "2.0.4", 970 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 971 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 972 | "dev": true 973 | }, 974 | "node_modules/is-extglob": { 975 | "version": "2.1.1", 976 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 977 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 978 | "dev": true, 979 | "engines": { 980 | "node": ">=0.10.0" 981 | } 982 | }, 983 | "node_modules/is-glob": { 984 | "version": "4.0.3", 985 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 986 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 987 | "dev": true, 988 | "dependencies": { 989 | "is-extglob": "^2.1.1" 990 | }, 991 | "engines": { 992 | "node": ">=0.10.0" 993 | } 994 | }, 995 | "node_modules/is-number": { 996 | "version": "7.0.0", 997 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 998 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 999 | "dev": true, 1000 | "engines": { 1001 | "node": ">=0.12.0" 1002 | } 1003 | }, 1004 | "node_modules/isexe": { 1005 | "version": "2.0.0", 1006 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1007 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 1008 | "dev": true 1009 | }, 1010 | "node_modules/js-yaml": { 1011 | "version": "4.1.0", 1012 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 1013 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 1014 | "dev": true, 1015 | "dependencies": { 1016 | "argparse": "^2.0.1" 1017 | }, 1018 | "bin": { 1019 | "js-yaml": "bin/js-yaml.js" 1020 | } 1021 | }, 1022 | "node_modules/json-schema-traverse": { 1023 | "version": "0.4.1", 1024 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1025 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1026 | "dev": true 1027 | }, 1028 | "node_modules/json-stable-stringify-without-jsonify": { 1029 | "version": "1.0.1", 1030 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 1031 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 1032 | "dev": true 1033 | }, 1034 | "node_modules/levn": { 1035 | "version": "0.4.1", 1036 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 1037 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 1038 | "dev": true, 1039 | "dependencies": { 1040 | "prelude-ls": "^1.2.1", 1041 | "type-check": "~0.4.0" 1042 | }, 1043 | "engines": { 1044 | "node": ">= 0.8.0" 1045 | } 1046 | }, 1047 | "node_modules/lodash.merge": { 1048 | "version": "4.6.2", 1049 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 1050 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 1051 | "dev": true 1052 | }, 1053 | "node_modules/lru-cache": { 1054 | "version": "6.0.0", 1055 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 1056 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 1057 | "dependencies": { 1058 | "yallist": "^4.0.0" 1059 | }, 1060 | "engines": { 1061 | "node": ">=10" 1062 | } 1063 | }, 1064 | "node_modules/merge2": { 1065 | "version": "1.4.1", 1066 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 1067 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 1068 | "dev": true, 1069 | "engines": { 1070 | "node": ">= 8" 1071 | } 1072 | }, 1073 | "node_modules/micromatch": { 1074 | "version": "4.0.4", 1075 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", 1076 | "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", 1077 | "dev": true, 1078 | "dependencies": { 1079 | "braces": "^3.0.1", 1080 | "picomatch": "^2.2.3" 1081 | }, 1082 | "engines": { 1083 | "node": ">=8.6" 1084 | } 1085 | }, 1086 | "node_modules/minimatch": { 1087 | "version": "3.1.2", 1088 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1089 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1090 | "dependencies": { 1091 | "brace-expansion": "^1.1.7" 1092 | }, 1093 | "engines": { 1094 | "node": "*" 1095 | } 1096 | }, 1097 | "node_modules/ms": { 1098 | "version": "2.1.2", 1099 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1100 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1101 | "dev": true 1102 | }, 1103 | "node_modules/natural-compare": { 1104 | "version": "1.4.0", 1105 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1106 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 1107 | "dev": true 1108 | }, 1109 | "node_modules/once": { 1110 | "version": "1.4.0", 1111 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1112 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1113 | "dev": true, 1114 | "dependencies": { 1115 | "wrappy": "1" 1116 | } 1117 | }, 1118 | "node_modules/optionator": { 1119 | "version": "0.9.1", 1120 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", 1121 | "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", 1122 | "dev": true, 1123 | "dependencies": { 1124 | "deep-is": "^0.1.3", 1125 | "fast-levenshtein": "^2.0.6", 1126 | "levn": "^0.4.1", 1127 | "prelude-ls": "^1.2.1", 1128 | "type-check": "^0.4.0", 1129 | "word-wrap": "^1.2.3" 1130 | }, 1131 | "engines": { 1132 | "node": ">= 0.8.0" 1133 | } 1134 | }, 1135 | "node_modules/parent-module": { 1136 | "version": "1.0.1", 1137 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 1138 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 1139 | "dev": true, 1140 | "dependencies": { 1141 | "callsites": "^3.0.0" 1142 | }, 1143 | "engines": { 1144 | "node": ">=6" 1145 | } 1146 | }, 1147 | "node_modules/path-is-absolute": { 1148 | "version": "1.0.1", 1149 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1150 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1151 | "dev": true, 1152 | "engines": { 1153 | "node": ">=0.10.0" 1154 | } 1155 | }, 1156 | "node_modules/path-key": { 1157 | "version": "3.1.1", 1158 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1159 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1160 | "dev": true, 1161 | "engines": { 1162 | "node": ">=8" 1163 | } 1164 | }, 1165 | "node_modules/path-type": { 1166 | "version": "4.0.0", 1167 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", 1168 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", 1169 | "dev": true, 1170 | "engines": { 1171 | "node": ">=8" 1172 | } 1173 | }, 1174 | "node_modules/picomatch": { 1175 | "version": "2.3.0", 1176 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", 1177 | "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", 1178 | "dev": true, 1179 | "engines": { 1180 | "node": ">=8.6" 1181 | }, 1182 | "funding": { 1183 | "url": "https://github.com/sponsors/jonschlinkert" 1184 | } 1185 | }, 1186 | "node_modules/prelude-ls": { 1187 | "version": "1.2.1", 1188 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 1189 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 1190 | "dev": true, 1191 | "engines": { 1192 | "node": ">= 0.8.0" 1193 | } 1194 | }, 1195 | "node_modules/progress": { 1196 | "version": "2.0.3", 1197 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 1198 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 1199 | "dev": true, 1200 | "engines": { 1201 | "node": ">=0.4.0" 1202 | } 1203 | }, 1204 | "node_modules/punycode": { 1205 | "version": "2.1.1", 1206 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1207 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 1208 | "dev": true, 1209 | "engines": { 1210 | "node": ">=6" 1211 | } 1212 | }, 1213 | "node_modules/queue-microtask": { 1214 | "version": "1.2.3", 1215 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 1216 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 1217 | "dev": true, 1218 | "funding": [ 1219 | { 1220 | "type": "github", 1221 | "url": "https://github.com/sponsors/feross" 1222 | }, 1223 | { 1224 | "type": "patreon", 1225 | "url": "https://www.patreon.com/feross" 1226 | }, 1227 | { 1228 | "type": "consulting", 1229 | "url": "https://feross.org/support" 1230 | } 1231 | ] 1232 | }, 1233 | "node_modules/regexpp": { 1234 | "version": "3.2.0", 1235 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", 1236 | "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", 1237 | "dev": true, 1238 | "engines": { 1239 | "node": ">=8" 1240 | }, 1241 | "funding": { 1242 | "url": "https://github.com/sponsors/mysticatea" 1243 | } 1244 | }, 1245 | "node_modules/resolve-from": { 1246 | "version": "4.0.0", 1247 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1248 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1249 | "dev": true, 1250 | "engines": { 1251 | "node": ">=4" 1252 | } 1253 | }, 1254 | "node_modules/reusify": { 1255 | "version": "1.0.4", 1256 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 1257 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 1258 | "dev": true, 1259 | "engines": { 1260 | "iojs": ">=1.0.0", 1261 | "node": ">=0.10.0" 1262 | } 1263 | }, 1264 | "node_modules/rimraf": { 1265 | "version": "3.0.2", 1266 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1267 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1268 | "dev": true, 1269 | "dependencies": { 1270 | "glob": "^7.1.3" 1271 | }, 1272 | "bin": { 1273 | "rimraf": "bin.js" 1274 | }, 1275 | "funding": { 1276 | "url": "https://github.com/sponsors/isaacs" 1277 | } 1278 | }, 1279 | "node_modules/run-parallel": { 1280 | "version": "1.2.0", 1281 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 1282 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 1283 | "dev": true, 1284 | "funding": [ 1285 | { 1286 | "type": "github", 1287 | "url": "https://github.com/sponsors/feross" 1288 | }, 1289 | { 1290 | "type": "patreon", 1291 | "url": "https://www.patreon.com/feross" 1292 | }, 1293 | { 1294 | "type": "consulting", 1295 | "url": "https://feross.org/support" 1296 | } 1297 | ], 1298 | "dependencies": { 1299 | "queue-microtask": "^1.2.2" 1300 | } 1301 | }, 1302 | "node_modules/semver": { 1303 | "version": "7.3.5", 1304 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", 1305 | "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", 1306 | "dependencies": { 1307 | "lru-cache": "^6.0.0" 1308 | }, 1309 | "bin": { 1310 | "semver": "bin/semver.js" 1311 | }, 1312 | "engines": { 1313 | "node": ">=10" 1314 | } 1315 | }, 1316 | "node_modules/shebang-command": { 1317 | "version": "2.0.0", 1318 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1319 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1320 | "dev": true, 1321 | "dependencies": { 1322 | "shebang-regex": "^3.0.0" 1323 | }, 1324 | "engines": { 1325 | "node": ">=8" 1326 | } 1327 | }, 1328 | "node_modules/shebang-regex": { 1329 | "version": "3.0.0", 1330 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1331 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1332 | "dev": true, 1333 | "engines": { 1334 | "node": ">=8" 1335 | } 1336 | }, 1337 | "node_modules/slash": { 1338 | "version": "3.0.0", 1339 | "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", 1340 | "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", 1341 | "dev": true, 1342 | "engines": { 1343 | "node": ">=8" 1344 | } 1345 | }, 1346 | "node_modules/strip-ansi": { 1347 | "version": "6.0.1", 1348 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1349 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1350 | "dev": true, 1351 | "dependencies": { 1352 | "ansi-regex": "^5.0.1" 1353 | }, 1354 | "engines": { 1355 | "node": ">=8" 1356 | } 1357 | }, 1358 | "node_modules/strip-json-comments": { 1359 | "version": "3.1.1", 1360 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 1361 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 1362 | "dev": true, 1363 | "engines": { 1364 | "node": ">=8" 1365 | }, 1366 | "funding": { 1367 | "url": "https://github.com/sponsors/sindresorhus" 1368 | } 1369 | }, 1370 | "node_modules/supports-color": { 1371 | "version": "7.2.0", 1372 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1373 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1374 | "dev": true, 1375 | "dependencies": { 1376 | "has-flag": "^4.0.0" 1377 | }, 1378 | "engines": { 1379 | "node": ">=8" 1380 | } 1381 | }, 1382 | "node_modules/text-table": { 1383 | "version": "0.2.0", 1384 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1385 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 1386 | "dev": true 1387 | }, 1388 | "node_modules/to-regex-range": { 1389 | "version": "5.0.1", 1390 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1391 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1392 | "dev": true, 1393 | "dependencies": { 1394 | "is-number": "^7.0.0" 1395 | }, 1396 | "engines": { 1397 | "node": ">=8.0" 1398 | } 1399 | }, 1400 | "node_modules/tslib": { 1401 | "version": "1.14.1", 1402 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", 1403 | "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", 1404 | "dev": true 1405 | }, 1406 | "node_modules/tsutils": { 1407 | "version": "3.21.0", 1408 | "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", 1409 | "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", 1410 | "dev": true, 1411 | "dependencies": { 1412 | "tslib": "^1.8.1" 1413 | }, 1414 | "engines": { 1415 | "node": ">= 6" 1416 | }, 1417 | "peerDependencies": { 1418 | "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" 1419 | } 1420 | }, 1421 | "node_modules/type-check": { 1422 | "version": "0.4.0", 1423 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 1424 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 1425 | "dev": true, 1426 | "dependencies": { 1427 | "prelude-ls": "^1.2.1" 1428 | }, 1429 | "engines": { 1430 | "node": ">= 0.8.0" 1431 | } 1432 | }, 1433 | "node_modules/type-fest": { 1434 | "version": "0.20.2", 1435 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", 1436 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", 1437 | "dev": true, 1438 | "engines": { 1439 | "node": ">=10" 1440 | }, 1441 | "funding": { 1442 | "url": "https://github.com/sponsors/sindresorhus" 1443 | } 1444 | }, 1445 | "node_modules/typescript": { 1446 | "version": "4.4.4", 1447 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", 1448 | "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", 1449 | "dev": true, 1450 | "bin": { 1451 | "tsc": "bin/tsc", 1452 | "tsserver": "bin/tsserver" 1453 | }, 1454 | "engines": { 1455 | "node": ">=4.2.0" 1456 | } 1457 | }, 1458 | "node_modules/uri-js": { 1459 | "version": "4.4.1", 1460 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 1461 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 1462 | "dev": true, 1463 | "dependencies": { 1464 | "punycode": "^2.1.0" 1465 | } 1466 | }, 1467 | "node_modules/v8-compile-cache": { 1468 | "version": "2.3.0", 1469 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", 1470 | "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", 1471 | "dev": true 1472 | }, 1473 | "node_modules/vscode-jsonrpc": { 1474 | "version": "8.0.2", 1475 | "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.2.tgz", 1476 | "integrity": "sha512-RY7HwI/ydoC1Wwg4gJ3y6LpU9FJRZAUnTYMXthqhFXXu77ErDd/xkREpGuk4MyYkk4a+XDWAMqe0S3KkelYQEQ==", 1477 | "engines": { 1478 | "node": ">=14.0.0" 1479 | } 1480 | }, 1481 | "node_modules/vscode-languageclient": { 1482 | "version": "8.0.2", 1483 | "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.0.2.tgz", 1484 | "integrity": "sha512-lHlthJtphG9gibGb/y72CKqQUxwPsMXijJVpHEC2bvbFqxmkj9LwQ3aGU9dwjBLqsX1S4KjShYppLvg1UJDF/Q==", 1485 | "dependencies": { 1486 | "minimatch": "^3.0.4", 1487 | "semver": "^7.3.5", 1488 | "vscode-languageserver-protocol": "3.17.2" 1489 | }, 1490 | "engines": { 1491 | "vscode": "^1.67.0" 1492 | } 1493 | }, 1494 | "node_modules/vscode-languageserver-protocol": { 1495 | "version": "3.17.2", 1496 | "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.2.tgz", 1497 | "integrity": "sha512-8kYisQ3z/SQ2kyjlNeQxbkkTNmVFoQCqkmGrzLH6A9ecPlgTbp3wDTnUNqaUxYr4vlAcloxx8zwy7G5WdguYNg==", 1498 | "dependencies": { 1499 | "vscode-jsonrpc": "8.0.2", 1500 | "vscode-languageserver-types": "3.17.2" 1501 | } 1502 | }, 1503 | "node_modules/vscode-languageserver-types": { 1504 | "version": "3.17.2", 1505 | "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz", 1506 | "integrity": "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==" 1507 | }, 1508 | "node_modules/which": { 1509 | "version": "2.0.2", 1510 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1511 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1512 | "dev": true, 1513 | "dependencies": { 1514 | "isexe": "^2.0.0" 1515 | }, 1516 | "bin": { 1517 | "node-which": "bin/node-which" 1518 | }, 1519 | "engines": { 1520 | "node": ">= 8" 1521 | } 1522 | }, 1523 | "node_modules/word-wrap": { 1524 | "version": "1.2.3", 1525 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 1526 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 1527 | "dev": true, 1528 | "engines": { 1529 | "node": ">=0.10.0" 1530 | } 1531 | }, 1532 | "node_modules/wrappy": { 1533 | "version": "1.0.2", 1534 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1535 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1536 | "dev": true 1537 | }, 1538 | "node_modules/yallist": { 1539 | "version": "4.0.0", 1540 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 1541 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 1542 | } 1543 | }, 1544 | "dependencies": { 1545 | "@eslint/eslintrc": { 1546 | "version": "1.0.4", 1547 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz", 1548 | "integrity": "sha512-h8Vx6MdxwWI2WM8/zREHMoqdgLNXEL4QX3MWSVMdyNJGvXVOs+6lp+m2hc3FnuMHDc4poxFNI20vCk0OmI4G0Q==", 1549 | "dev": true, 1550 | "requires": { 1551 | "ajv": "^6.12.4", 1552 | "debug": "^4.3.2", 1553 | "espree": "^9.0.0", 1554 | "globals": "^13.9.0", 1555 | "ignore": "^4.0.6", 1556 | "import-fresh": "^3.2.1", 1557 | "js-yaml": "^4.1.0", 1558 | "minimatch": "^3.0.4", 1559 | "strip-json-comments": "^3.1.1" 1560 | }, 1561 | "dependencies": { 1562 | "ignore": { 1563 | "version": "4.0.6", 1564 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 1565 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 1566 | "dev": true 1567 | } 1568 | } 1569 | }, 1570 | "@humanwhocodes/config-array": { 1571 | "version": "0.6.0", 1572 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", 1573 | "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==", 1574 | "dev": true, 1575 | "requires": { 1576 | "@humanwhocodes/object-schema": "^1.2.0", 1577 | "debug": "^4.1.1", 1578 | "minimatch": "^3.0.4" 1579 | } 1580 | }, 1581 | "@humanwhocodes/object-schema": { 1582 | "version": "1.2.1", 1583 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", 1584 | "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", 1585 | "dev": true 1586 | }, 1587 | "@nodelib/fs.scandir": { 1588 | "version": "2.1.5", 1589 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 1590 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 1591 | "dev": true, 1592 | "requires": { 1593 | "@nodelib/fs.stat": "2.0.5", 1594 | "run-parallel": "^1.1.9" 1595 | } 1596 | }, 1597 | "@nodelib/fs.stat": { 1598 | "version": "2.0.5", 1599 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 1600 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 1601 | "dev": true 1602 | }, 1603 | "@nodelib/fs.walk": { 1604 | "version": "1.2.8", 1605 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 1606 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 1607 | "dev": true, 1608 | "requires": { 1609 | "@nodelib/fs.scandir": "2.1.5", 1610 | "fastq": "^1.6.0" 1611 | } 1612 | }, 1613 | "@types/json-schema": { 1614 | "version": "7.0.9", 1615 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", 1616 | "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", 1617 | "dev": true 1618 | }, 1619 | "@types/node": { 1620 | "version": "16.11.43", 1621 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.43.tgz", 1622 | "integrity": "sha512-GqWykok+3uocgfAJM8imbozrqLnPyTrpFlrryURQlw1EesPUCx5XxTiucWDSFF9/NUEXDuD4bnvHm8xfVGWTpQ==", 1623 | "dev": true 1624 | }, 1625 | "@types/vscode": { 1626 | "version": "1.74.0", 1627 | "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.74.0.tgz", 1628 | "integrity": "sha512-LyeCIU3jb9d38w0MXFwta9r0Jx23ugujkAxdwLTNCyspdZTKUc43t7ppPbCiPoQ/Ivd/pnDFZrb4hWd45wrsgA==", 1629 | "dev": true 1630 | }, 1631 | "@typescript-eslint/eslint-plugin": { 1632 | "version": "5.3.0", 1633 | "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.3.0.tgz", 1634 | "integrity": "sha512-ARUEJHJrq85aaiCqez7SANeahDsJTD3AEua34EoQN9pHS6S5Bq9emcIaGGySt/4X2zSi+vF5hAH52sEen7IO7g==", 1635 | "dev": true, 1636 | "requires": { 1637 | "@typescript-eslint/experimental-utils": "5.3.0", 1638 | "@typescript-eslint/scope-manager": "5.3.0", 1639 | "debug": "^4.3.2", 1640 | "functional-red-black-tree": "^1.0.1", 1641 | "ignore": "^5.1.8", 1642 | "regexpp": "^3.2.0", 1643 | "semver": "^7.3.5", 1644 | "tsutils": "^3.21.0" 1645 | } 1646 | }, 1647 | "@typescript-eslint/experimental-utils": { 1648 | "version": "5.3.0", 1649 | "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.3.0.tgz", 1650 | "integrity": "sha512-NFVxYTjKj69qB0FM+piah1x3G/63WB8vCBMnlnEHUsiLzXSTWb9FmFn36FD9Zb4APKBLY3xRArOGSMQkuzTF1w==", 1651 | "dev": true, 1652 | "requires": { 1653 | "@types/json-schema": "^7.0.9", 1654 | "@typescript-eslint/scope-manager": "5.3.0", 1655 | "@typescript-eslint/types": "5.3.0", 1656 | "@typescript-eslint/typescript-estree": "5.3.0", 1657 | "eslint-scope": "^5.1.1", 1658 | "eslint-utils": "^3.0.0" 1659 | } 1660 | }, 1661 | "@typescript-eslint/parser": { 1662 | "version": "5.3.0", 1663 | "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.3.0.tgz", 1664 | "integrity": "sha512-rKu/yAReip7ovx8UwOAszJVO5MgBquo8WjIQcp1gx4pYQCwYzag+I5nVNHO4MqyMkAo0gWt2gWUi+36gWAVKcw==", 1665 | "dev": true, 1666 | "requires": { 1667 | "@typescript-eslint/scope-manager": "5.3.0", 1668 | "@typescript-eslint/types": "5.3.0", 1669 | "@typescript-eslint/typescript-estree": "5.3.0", 1670 | "debug": "^4.3.2" 1671 | } 1672 | }, 1673 | "@typescript-eslint/scope-manager": { 1674 | "version": "5.3.0", 1675 | "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.3.0.tgz", 1676 | "integrity": "sha512-22Uic9oRlTsPppy5Tcwfj+QET5RWEnZ5414Prby465XxQrQFZ6nnm5KnXgnsAJefG4hEgMnaxTB3kNEyjdjj6A==", 1677 | "dev": true, 1678 | "requires": { 1679 | "@typescript-eslint/types": "5.3.0", 1680 | "@typescript-eslint/visitor-keys": "5.3.0" 1681 | } 1682 | }, 1683 | "@typescript-eslint/types": { 1684 | "version": "5.3.0", 1685 | "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.3.0.tgz", 1686 | "integrity": "sha512-fce5pG41/w8O6ahQEhXmMV+xuh4+GayzqEogN24EK+vECA3I6pUwKuLi5QbXO721EMitpQne5VKXofPonYlAQg==", 1687 | "dev": true 1688 | }, 1689 | "@typescript-eslint/typescript-estree": { 1690 | "version": "5.3.0", 1691 | "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.3.0.tgz", 1692 | "integrity": "sha512-FJ0nqcaUOpn/6Z4Jwbtf+o0valjBLkqc3MWkMvrhA2TvzFXtcclIM8F4MBEmYa2kgcI8EZeSAzwoSrIC8JYkug==", 1693 | "dev": true, 1694 | "requires": { 1695 | "@typescript-eslint/types": "5.3.0", 1696 | "@typescript-eslint/visitor-keys": "5.3.0", 1697 | "debug": "^4.3.2", 1698 | "globby": "^11.0.4", 1699 | "is-glob": "^4.0.3", 1700 | "semver": "^7.3.5", 1701 | "tsutils": "^3.21.0" 1702 | } 1703 | }, 1704 | "@typescript-eslint/visitor-keys": { 1705 | "version": "5.3.0", 1706 | "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.3.0.tgz", 1707 | "integrity": "sha512-oVIAfIQuq0x2TFDNLVavUn548WL+7hdhxYn+9j3YdJJXB7mH9dAmZNJsPDa7Jc+B9WGqoiex7GUDbyMxV0a/aw==", 1708 | "dev": true, 1709 | "requires": { 1710 | "@typescript-eslint/types": "5.3.0", 1711 | "eslint-visitor-keys": "^3.0.0" 1712 | } 1713 | }, 1714 | "acorn": { 1715 | "version": "8.5.0", 1716 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", 1717 | "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", 1718 | "dev": true 1719 | }, 1720 | "acorn-jsx": { 1721 | "version": "5.3.2", 1722 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 1723 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 1724 | "dev": true, 1725 | "requires": {} 1726 | }, 1727 | "ajv": { 1728 | "version": "6.12.6", 1729 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 1730 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 1731 | "dev": true, 1732 | "requires": { 1733 | "fast-deep-equal": "^3.1.1", 1734 | "fast-json-stable-stringify": "^2.0.0", 1735 | "json-schema-traverse": "^0.4.1", 1736 | "uri-js": "^4.2.2" 1737 | } 1738 | }, 1739 | "ansi-colors": { 1740 | "version": "4.1.1", 1741 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 1742 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 1743 | "dev": true 1744 | }, 1745 | "ansi-regex": { 1746 | "version": "5.0.1", 1747 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1748 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1749 | "dev": true 1750 | }, 1751 | "ansi-styles": { 1752 | "version": "4.3.0", 1753 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1754 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1755 | "dev": true, 1756 | "requires": { 1757 | "color-convert": "^2.0.1" 1758 | } 1759 | }, 1760 | "argparse": { 1761 | "version": "2.0.1", 1762 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 1763 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 1764 | "dev": true 1765 | }, 1766 | "array-union": { 1767 | "version": "2.1.0", 1768 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", 1769 | "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", 1770 | "dev": true 1771 | }, 1772 | "balanced-match": { 1773 | "version": "1.0.2", 1774 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 1775 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 1776 | }, 1777 | "brace-expansion": { 1778 | "version": "1.1.11", 1779 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 1780 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 1781 | "requires": { 1782 | "balanced-match": "^1.0.0", 1783 | "concat-map": "0.0.1" 1784 | } 1785 | }, 1786 | "braces": { 1787 | "version": "3.0.2", 1788 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 1789 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 1790 | "dev": true, 1791 | "requires": { 1792 | "fill-range": "^7.0.1" 1793 | } 1794 | }, 1795 | "callsites": { 1796 | "version": "3.1.0", 1797 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 1798 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 1799 | "dev": true 1800 | }, 1801 | "chalk": { 1802 | "version": "4.1.2", 1803 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 1804 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 1805 | "dev": true, 1806 | "requires": { 1807 | "ansi-styles": "^4.1.0", 1808 | "supports-color": "^7.1.0" 1809 | } 1810 | }, 1811 | "color-convert": { 1812 | "version": "2.0.1", 1813 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1814 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1815 | "dev": true, 1816 | "requires": { 1817 | "color-name": "~1.1.4" 1818 | } 1819 | }, 1820 | "color-name": { 1821 | "version": "1.1.4", 1822 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1823 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1824 | "dev": true 1825 | }, 1826 | "concat-map": { 1827 | "version": "0.0.1", 1828 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 1829 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 1830 | }, 1831 | "cross-spawn": { 1832 | "version": "7.0.3", 1833 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 1834 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 1835 | "dev": true, 1836 | "requires": { 1837 | "path-key": "^3.1.0", 1838 | "shebang-command": "^2.0.0", 1839 | "which": "^2.0.1" 1840 | } 1841 | }, 1842 | "debug": { 1843 | "version": "4.3.2", 1844 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", 1845 | "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", 1846 | "dev": true, 1847 | "requires": { 1848 | "ms": "2.1.2" 1849 | } 1850 | }, 1851 | "deep-is": { 1852 | "version": "0.1.4", 1853 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 1854 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", 1855 | "dev": true 1856 | }, 1857 | "dir-glob": { 1858 | "version": "3.0.1", 1859 | "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", 1860 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", 1861 | "dev": true, 1862 | "requires": { 1863 | "path-type": "^4.0.0" 1864 | } 1865 | }, 1866 | "doctrine": { 1867 | "version": "3.0.0", 1868 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 1869 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 1870 | "dev": true, 1871 | "requires": { 1872 | "esutils": "^2.0.2" 1873 | } 1874 | }, 1875 | "enquirer": { 1876 | "version": "2.3.6", 1877 | "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", 1878 | "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", 1879 | "dev": true, 1880 | "requires": { 1881 | "ansi-colors": "^4.1.1" 1882 | } 1883 | }, 1884 | "escape-string-regexp": { 1885 | "version": "4.0.0", 1886 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 1887 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 1888 | "dev": true 1889 | }, 1890 | "eslint": { 1891 | "version": "8.2.0", 1892 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.2.0.tgz", 1893 | "integrity": "sha512-erw7XmM+CLxTOickrimJ1SiF55jiNlVSp2qqm0NuBWPtHYQCegD5ZMaW0c3i5ytPqL+SSLaCxdvQXFPLJn+ABw==", 1894 | "dev": true, 1895 | "requires": { 1896 | "@eslint/eslintrc": "^1.0.4", 1897 | "@humanwhocodes/config-array": "^0.6.0", 1898 | "ajv": "^6.10.0", 1899 | "chalk": "^4.0.0", 1900 | "cross-spawn": "^7.0.2", 1901 | "debug": "^4.3.2", 1902 | "doctrine": "^3.0.0", 1903 | "enquirer": "^2.3.5", 1904 | "escape-string-regexp": "^4.0.0", 1905 | "eslint-scope": "^6.0.0", 1906 | "eslint-utils": "^3.0.0", 1907 | "eslint-visitor-keys": "^3.0.0", 1908 | "espree": "^9.0.0", 1909 | "esquery": "^1.4.0", 1910 | "esutils": "^2.0.2", 1911 | "fast-deep-equal": "^3.1.3", 1912 | "file-entry-cache": "^6.0.1", 1913 | "functional-red-black-tree": "^1.0.1", 1914 | "glob-parent": "^6.0.1", 1915 | "globals": "^13.6.0", 1916 | "ignore": "^4.0.6", 1917 | "import-fresh": "^3.0.0", 1918 | "imurmurhash": "^0.1.4", 1919 | "is-glob": "^4.0.0", 1920 | "js-yaml": "^4.1.0", 1921 | "json-stable-stringify-without-jsonify": "^1.0.1", 1922 | "levn": "^0.4.1", 1923 | "lodash.merge": "^4.6.2", 1924 | "minimatch": "^3.0.4", 1925 | "natural-compare": "^1.4.0", 1926 | "optionator": "^0.9.1", 1927 | "progress": "^2.0.0", 1928 | "regexpp": "^3.2.0", 1929 | "semver": "^7.2.1", 1930 | "strip-ansi": "^6.0.1", 1931 | "strip-json-comments": "^3.1.0", 1932 | "text-table": "^0.2.0", 1933 | "v8-compile-cache": "^2.0.3" 1934 | }, 1935 | "dependencies": { 1936 | "eslint-scope": { 1937 | "version": "6.0.0", 1938 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-6.0.0.tgz", 1939 | "integrity": "sha512-uRDL9MWmQCkaFus8RF5K9/L/2fn+80yoW3jkD53l4shjCh26fCtvJGasxjUqP5OT87SYTxCVA3BwTUzuELx9kA==", 1940 | "dev": true, 1941 | "requires": { 1942 | "esrecurse": "^4.3.0", 1943 | "estraverse": "^5.2.0" 1944 | } 1945 | }, 1946 | "estraverse": { 1947 | "version": "5.3.0", 1948 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 1949 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 1950 | "dev": true 1951 | }, 1952 | "ignore": { 1953 | "version": "4.0.6", 1954 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 1955 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 1956 | "dev": true 1957 | } 1958 | } 1959 | }, 1960 | "eslint-scope": { 1961 | "version": "5.1.1", 1962 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", 1963 | "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", 1964 | "dev": true, 1965 | "requires": { 1966 | "esrecurse": "^4.3.0", 1967 | "estraverse": "^4.1.1" 1968 | } 1969 | }, 1970 | "eslint-utils": { 1971 | "version": "3.0.0", 1972 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", 1973 | "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", 1974 | "dev": true, 1975 | "requires": { 1976 | "eslint-visitor-keys": "^2.0.0" 1977 | }, 1978 | "dependencies": { 1979 | "eslint-visitor-keys": { 1980 | "version": "2.1.0", 1981 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", 1982 | "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", 1983 | "dev": true 1984 | } 1985 | } 1986 | }, 1987 | "eslint-visitor-keys": { 1988 | "version": "3.0.0", 1989 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz", 1990 | "integrity": "sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==", 1991 | "dev": true 1992 | }, 1993 | "espree": { 1994 | "version": "9.0.0", 1995 | "resolved": "https://registry.npmjs.org/espree/-/espree-9.0.0.tgz", 1996 | "integrity": "sha512-r5EQJcYZ2oaGbeR0jR0fFVijGOcwai07/690YRXLINuhmVeRY4UKSAsQPe/0BNuDgwP7Ophoc1PRsr2E3tkbdQ==", 1997 | "dev": true, 1998 | "requires": { 1999 | "acorn": "^8.5.0", 2000 | "acorn-jsx": "^5.3.1", 2001 | "eslint-visitor-keys": "^3.0.0" 2002 | } 2003 | }, 2004 | "esquery": { 2005 | "version": "1.4.0", 2006 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", 2007 | "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", 2008 | "dev": true, 2009 | "requires": { 2010 | "estraverse": "^5.1.0" 2011 | }, 2012 | "dependencies": { 2013 | "estraverse": { 2014 | "version": "5.3.0", 2015 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 2016 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 2017 | "dev": true 2018 | } 2019 | } 2020 | }, 2021 | "esrecurse": { 2022 | "version": "4.3.0", 2023 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 2024 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 2025 | "dev": true, 2026 | "requires": { 2027 | "estraverse": "^5.2.0" 2028 | }, 2029 | "dependencies": { 2030 | "estraverse": { 2031 | "version": "5.3.0", 2032 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 2033 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 2034 | "dev": true 2035 | } 2036 | } 2037 | }, 2038 | "estraverse": { 2039 | "version": "4.3.0", 2040 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 2041 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 2042 | "dev": true 2043 | }, 2044 | "esutils": { 2045 | "version": "2.0.3", 2046 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 2047 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 2048 | "dev": true 2049 | }, 2050 | "fast-deep-equal": { 2051 | "version": "3.1.3", 2052 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 2053 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 2054 | "dev": true 2055 | }, 2056 | "fast-glob": { 2057 | "version": "3.2.7", 2058 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", 2059 | "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", 2060 | "dev": true, 2061 | "requires": { 2062 | "@nodelib/fs.stat": "^2.0.2", 2063 | "@nodelib/fs.walk": "^1.2.3", 2064 | "glob-parent": "^5.1.2", 2065 | "merge2": "^1.3.0", 2066 | "micromatch": "^4.0.4" 2067 | }, 2068 | "dependencies": { 2069 | "glob-parent": { 2070 | "version": "5.1.2", 2071 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 2072 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 2073 | "dev": true, 2074 | "requires": { 2075 | "is-glob": "^4.0.1" 2076 | } 2077 | } 2078 | } 2079 | }, 2080 | "fast-json-stable-stringify": { 2081 | "version": "2.1.0", 2082 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 2083 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 2084 | "dev": true 2085 | }, 2086 | "fast-levenshtein": { 2087 | "version": "2.0.6", 2088 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 2089 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 2090 | "dev": true 2091 | }, 2092 | "fastq": { 2093 | "version": "1.13.0", 2094 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", 2095 | "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", 2096 | "dev": true, 2097 | "requires": { 2098 | "reusify": "^1.0.4" 2099 | } 2100 | }, 2101 | "file-entry-cache": { 2102 | "version": "6.0.1", 2103 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", 2104 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", 2105 | "dev": true, 2106 | "requires": { 2107 | "flat-cache": "^3.0.4" 2108 | } 2109 | }, 2110 | "fill-range": { 2111 | "version": "7.0.1", 2112 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 2113 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 2114 | "dev": true, 2115 | "requires": { 2116 | "to-regex-range": "^5.0.1" 2117 | } 2118 | }, 2119 | "flat-cache": { 2120 | "version": "3.0.4", 2121 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", 2122 | "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", 2123 | "dev": true, 2124 | "requires": { 2125 | "flatted": "^3.1.0", 2126 | "rimraf": "^3.0.2" 2127 | } 2128 | }, 2129 | "flatted": { 2130 | "version": "3.2.2", 2131 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", 2132 | "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", 2133 | "dev": true 2134 | }, 2135 | "fs.realpath": { 2136 | "version": "1.0.0", 2137 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 2138 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 2139 | "dev": true 2140 | }, 2141 | "functional-red-black-tree": { 2142 | "version": "1.0.1", 2143 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 2144 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 2145 | "dev": true 2146 | }, 2147 | "glob": { 2148 | "version": "7.2.0", 2149 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 2150 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 2151 | "dev": true, 2152 | "requires": { 2153 | "fs.realpath": "^1.0.0", 2154 | "inflight": "^1.0.4", 2155 | "inherits": "2", 2156 | "minimatch": "^3.0.4", 2157 | "once": "^1.3.0", 2158 | "path-is-absolute": "^1.0.0" 2159 | } 2160 | }, 2161 | "glob-parent": { 2162 | "version": "6.0.2", 2163 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", 2164 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 2165 | "dev": true, 2166 | "requires": { 2167 | "is-glob": "^4.0.3" 2168 | } 2169 | }, 2170 | "globals": { 2171 | "version": "13.12.0", 2172 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", 2173 | "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", 2174 | "dev": true, 2175 | "requires": { 2176 | "type-fest": "^0.20.2" 2177 | } 2178 | }, 2179 | "globby": { 2180 | "version": "11.0.4", 2181 | "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", 2182 | "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", 2183 | "dev": true, 2184 | "requires": { 2185 | "array-union": "^2.1.0", 2186 | "dir-glob": "^3.0.1", 2187 | "fast-glob": "^3.1.1", 2188 | "ignore": "^5.1.4", 2189 | "merge2": "^1.3.0", 2190 | "slash": "^3.0.0" 2191 | } 2192 | }, 2193 | "has-flag": { 2194 | "version": "4.0.0", 2195 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 2196 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 2197 | "dev": true 2198 | }, 2199 | "ignore": { 2200 | "version": "5.1.9", 2201 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz", 2202 | "integrity": "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==", 2203 | "dev": true 2204 | }, 2205 | "import-fresh": { 2206 | "version": "3.3.0", 2207 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 2208 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 2209 | "dev": true, 2210 | "requires": { 2211 | "parent-module": "^1.0.0", 2212 | "resolve-from": "^4.0.0" 2213 | } 2214 | }, 2215 | "imurmurhash": { 2216 | "version": "0.1.4", 2217 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 2218 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 2219 | "dev": true 2220 | }, 2221 | "inflight": { 2222 | "version": "1.0.6", 2223 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 2224 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 2225 | "dev": true, 2226 | "requires": { 2227 | "once": "^1.3.0", 2228 | "wrappy": "1" 2229 | } 2230 | }, 2231 | "inherits": { 2232 | "version": "2.0.4", 2233 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 2234 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 2235 | "dev": true 2236 | }, 2237 | "is-extglob": { 2238 | "version": "2.1.1", 2239 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 2240 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 2241 | "dev": true 2242 | }, 2243 | "is-glob": { 2244 | "version": "4.0.3", 2245 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 2246 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 2247 | "dev": true, 2248 | "requires": { 2249 | "is-extglob": "^2.1.1" 2250 | } 2251 | }, 2252 | "is-number": { 2253 | "version": "7.0.0", 2254 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 2255 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 2256 | "dev": true 2257 | }, 2258 | "isexe": { 2259 | "version": "2.0.0", 2260 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 2261 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 2262 | "dev": true 2263 | }, 2264 | "js-yaml": { 2265 | "version": "4.1.0", 2266 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 2267 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 2268 | "dev": true, 2269 | "requires": { 2270 | "argparse": "^2.0.1" 2271 | } 2272 | }, 2273 | "json-schema-traverse": { 2274 | "version": "0.4.1", 2275 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 2276 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 2277 | "dev": true 2278 | }, 2279 | "json-stable-stringify-without-jsonify": { 2280 | "version": "1.0.1", 2281 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 2282 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 2283 | "dev": true 2284 | }, 2285 | "levn": { 2286 | "version": "0.4.1", 2287 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 2288 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 2289 | "dev": true, 2290 | "requires": { 2291 | "prelude-ls": "^1.2.1", 2292 | "type-check": "~0.4.0" 2293 | } 2294 | }, 2295 | "lodash.merge": { 2296 | "version": "4.6.2", 2297 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 2298 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 2299 | "dev": true 2300 | }, 2301 | "lru-cache": { 2302 | "version": "6.0.0", 2303 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 2304 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 2305 | "requires": { 2306 | "yallist": "^4.0.0" 2307 | } 2308 | }, 2309 | "merge2": { 2310 | "version": "1.4.1", 2311 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 2312 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 2313 | "dev": true 2314 | }, 2315 | "micromatch": { 2316 | "version": "4.0.4", 2317 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", 2318 | "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", 2319 | "dev": true, 2320 | "requires": { 2321 | "braces": "^3.0.1", 2322 | "picomatch": "^2.2.3" 2323 | } 2324 | }, 2325 | "minimatch": { 2326 | "version": "3.1.2", 2327 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 2328 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 2329 | "requires": { 2330 | "brace-expansion": "^1.1.7" 2331 | } 2332 | }, 2333 | "ms": { 2334 | "version": "2.1.2", 2335 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 2336 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 2337 | "dev": true 2338 | }, 2339 | "natural-compare": { 2340 | "version": "1.4.0", 2341 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 2342 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 2343 | "dev": true 2344 | }, 2345 | "once": { 2346 | "version": "1.4.0", 2347 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 2348 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 2349 | "dev": true, 2350 | "requires": { 2351 | "wrappy": "1" 2352 | } 2353 | }, 2354 | "optionator": { 2355 | "version": "0.9.1", 2356 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", 2357 | "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", 2358 | "dev": true, 2359 | "requires": { 2360 | "deep-is": "^0.1.3", 2361 | "fast-levenshtein": "^2.0.6", 2362 | "levn": "^0.4.1", 2363 | "prelude-ls": "^1.2.1", 2364 | "type-check": "^0.4.0", 2365 | "word-wrap": "^1.2.3" 2366 | } 2367 | }, 2368 | "parent-module": { 2369 | "version": "1.0.1", 2370 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 2371 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 2372 | "dev": true, 2373 | "requires": { 2374 | "callsites": "^3.0.0" 2375 | } 2376 | }, 2377 | "path-is-absolute": { 2378 | "version": "1.0.1", 2379 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 2380 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 2381 | "dev": true 2382 | }, 2383 | "path-key": { 2384 | "version": "3.1.1", 2385 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 2386 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 2387 | "dev": true 2388 | }, 2389 | "path-type": { 2390 | "version": "4.0.0", 2391 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", 2392 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", 2393 | "dev": true 2394 | }, 2395 | "picomatch": { 2396 | "version": "2.3.0", 2397 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", 2398 | "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", 2399 | "dev": true 2400 | }, 2401 | "prelude-ls": { 2402 | "version": "1.2.1", 2403 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 2404 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 2405 | "dev": true 2406 | }, 2407 | "progress": { 2408 | "version": "2.0.3", 2409 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 2410 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 2411 | "dev": true 2412 | }, 2413 | "punycode": { 2414 | "version": "2.1.1", 2415 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 2416 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 2417 | "dev": true 2418 | }, 2419 | "queue-microtask": { 2420 | "version": "1.2.3", 2421 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 2422 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 2423 | "dev": true 2424 | }, 2425 | "regexpp": { 2426 | "version": "3.2.0", 2427 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", 2428 | "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", 2429 | "dev": true 2430 | }, 2431 | "resolve-from": { 2432 | "version": "4.0.0", 2433 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 2434 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 2435 | "dev": true 2436 | }, 2437 | "reusify": { 2438 | "version": "1.0.4", 2439 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 2440 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 2441 | "dev": true 2442 | }, 2443 | "rimraf": { 2444 | "version": "3.0.2", 2445 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 2446 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 2447 | "dev": true, 2448 | "requires": { 2449 | "glob": "^7.1.3" 2450 | } 2451 | }, 2452 | "run-parallel": { 2453 | "version": "1.2.0", 2454 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 2455 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 2456 | "dev": true, 2457 | "requires": { 2458 | "queue-microtask": "^1.2.2" 2459 | } 2460 | }, 2461 | "semver": { 2462 | "version": "7.3.5", 2463 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", 2464 | "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", 2465 | "requires": { 2466 | "lru-cache": "^6.0.0" 2467 | } 2468 | }, 2469 | "shebang-command": { 2470 | "version": "2.0.0", 2471 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 2472 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 2473 | "dev": true, 2474 | "requires": { 2475 | "shebang-regex": "^3.0.0" 2476 | } 2477 | }, 2478 | "shebang-regex": { 2479 | "version": "3.0.0", 2480 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 2481 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 2482 | "dev": true 2483 | }, 2484 | "slash": { 2485 | "version": "3.0.0", 2486 | "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", 2487 | "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", 2488 | "dev": true 2489 | }, 2490 | "strip-ansi": { 2491 | "version": "6.0.1", 2492 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2493 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2494 | "dev": true, 2495 | "requires": { 2496 | "ansi-regex": "^5.0.1" 2497 | } 2498 | }, 2499 | "strip-json-comments": { 2500 | "version": "3.1.1", 2501 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 2502 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 2503 | "dev": true 2504 | }, 2505 | "supports-color": { 2506 | "version": "7.2.0", 2507 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 2508 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 2509 | "dev": true, 2510 | "requires": { 2511 | "has-flag": "^4.0.0" 2512 | } 2513 | }, 2514 | "text-table": { 2515 | "version": "0.2.0", 2516 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 2517 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 2518 | "dev": true 2519 | }, 2520 | "to-regex-range": { 2521 | "version": "5.0.1", 2522 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2523 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2524 | "dev": true, 2525 | "requires": { 2526 | "is-number": "^7.0.0" 2527 | } 2528 | }, 2529 | "tslib": { 2530 | "version": "1.14.1", 2531 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", 2532 | "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", 2533 | "dev": true 2534 | }, 2535 | "tsutils": { 2536 | "version": "3.21.0", 2537 | "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", 2538 | "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", 2539 | "dev": true, 2540 | "requires": { 2541 | "tslib": "^1.8.1" 2542 | } 2543 | }, 2544 | "type-check": { 2545 | "version": "0.4.0", 2546 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 2547 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 2548 | "dev": true, 2549 | "requires": { 2550 | "prelude-ls": "^1.2.1" 2551 | } 2552 | }, 2553 | "type-fest": { 2554 | "version": "0.20.2", 2555 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", 2556 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", 2557 | "dev": true 2558 | }, 2559 | "typescript": { 2560 | "version": "4.4.4", 2561 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", 2562 | "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", 2563 | "dev": true 2564 | }, 2565 | "uri-js": { 2566 | "version": "4.4.1", 2567 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 2568 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 2569 | "dev": true, 2570 | "requires": { 2571 | "punycode": "^2.1.0" 2572 | } 2573 | }, 2574 | "v8-compile-cache": { 2575 | "version": "2.3.0", 2576 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", 2577 | "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", 2578 | "dev": true 2579 | }, 2580 | "vscode-jsonrpc": { 2581 | "version": "8.0.2", 2582 | "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.2.tgz", 2583 | "integrity": "sha512-RY7HwI/ydoC1Wwg4gJ3y6LpU9FJRZAUnTYMXthqhFXXu77ErDd/xkREpGuk4MyYkk4a+XDWAMqe0S3KkelYQEQ==" 2584 | }, 2585 | "vscode-languageclient": { 2586 | "version": "8.0.2", 2587 | "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.0.2.tgz", 2588 | "integrity": "sha512-lHlthJtphG9gibGb/y72CKqQUxwPsMXijJVpHEC2bvbFqxmkj9LwQ3aGU9dwjBLqsX1S4KjShYppLvg1UJDF/Q==", 2589 | "requires": { 2590 | "minimatch": "^3.0.4", 2591 | "semver": "^7.3.5", 2592 | "vscode-languageserver-protocol": "3.17.2" 2593 | } 2594 | }, 2595 | "vscode-languageserver-protocol": { 2596 | "version": "3.17.2", 2597 | "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.2.tgz", 2598 | "integrity": "sha512-8kYisQ3z/SQ2kyjlNeQxbkkTNmVFoQCqkmGrzLH6A9ecPlgTbp3wDTnUNqaUxYr4vlAcloxx8zwy7G5WdguYNg==", 2599 | "requires": { 2600 | "vscode-jsonrpc": "8.0.2", 2601 | "vscode-languageserver-types": "3.17.2" 2602 | } 2603 | }, 2604 | "vscode-languageserver-types": { 2605 | "version": "3.17.2", 2606 | "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz", 2607 | "integrity": "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==" 2608 | }, 2609 | "which": { 2610 | "version": "2.0.2", 2611 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2612 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2613 | "dev": true, 2614 | "requires": { 2615 | "isexe": "^2.0.0" 2616 | } 2617 | }, 2618 | "word-wrap": { 2619 | "version": "1.2.3", 2620 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 2621 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 2622 | "dev": true 2623 | }, 2624 | "wrappy": { 2625 | "version": "1.0.2", 2626 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2627 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 2628 | "dev": true 2629 | }, 2630 | "yallist": { 2631 | "version": "4.0.0", 2632 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 2633 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 2634 | } 2635 | } 2636 | } 2637 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spacy-extension", 3 | "displayName": "spaCy", 4 | "description": "spaCy extension that provides additional tooling and features for working with spaCy's config files", 5 | "author": "Explosion", 6 | "repository": "https://github.com/explosion/spacy-vscode", 7 | "license": "MIT", 8 | "version": "1.0.1", 9 | "icon": "icon.png", 10 | "galleryBanner": { 11 | "color": "#1e415e", 12 | "theme": "dark" 13 | }, 14 | "publisher": "Explosion", 15 | "homepage": "explosion.ai", 16 | "keywords": [ 17 | "python", 18 | "spacy", 19 | "prodigy", 20 | "explosion", 21 | "NLP", 22 | "ML" 23 | ], 24 | "engines": { 25 | "vscode": "^1.74.0" 26 | }, 27 | "categories": [ 28 | "Other", 29 | "Machine Learning" 30 | ], 31 | "extensionDependencies": [ 32 | "ms-python.python" 33 | ], 34 | "activationEvents": [ 35 | "workspaceContains:**/*.cfg" 36 | ], 37 | "contributes": { 38 | "commands": [], 39 | "configuration": { 40 | "title": "spaCy Server Configuration", 41 | "properties": { 42 | "spacy-extension.pythonInterpreter": { 43 | "scope": "resource", 44 | "type": "string", 45 | "default": "", 46 | "description": "Specify python interpreter to start the spaCy extension server. Make sure it contains all required modules." 47 | } 48 | } 49 | } 50 | }, 51 | "main": "./client/out/extension", 52 | "scripts": { 53 | "vscode:prepublish": "npm run compile", 54 | "compile": "tsc -b", 55 | "watch": "tsc -b -w", 56 | "lint": "eslint . --ext .ts" 57 | }, 58 | "devDependencies": { 59 | "@types/node": "16.11.43", 60 | "@types/vscode": "^1.74.0", 61 | "@typescript-eslint/eslint-plugin": "^5.3.0", 62 | "@typescript-eslint/parser": "^5.3.0", 63 | "eslint": "^8.2.0", 64 | "typescript": "^4.4.4" 65 | }, 66 | "dependencies": { 67 | "vscode-languageclient": "^8.0.2" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | spaCy > 3.4.0 2 | pygls == 1.0.0 -------------------------------------------------------------------------------- /server/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/explosion/spacy-vscode/9fa92737b967e85ef0d0c8019c3004c3e249c9f2/server/__init__.py -------------------------------------------------------------------------------- /server/__main__.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import logging 3 | from .server import spacy_server 4 | 5 | logging.basicConfig(filename="pygls.log", level=logging.DEBUG, filemode="w") 6 | 7 | 8 | def add_arguments(parser): 9 | parser.description = "spacy server" 10 | 11 | parser.add_argument("--tcp", action="store_true", help="Use TCP server") 12 | parser.add_argument("--ws", action="store_true", help="Use WebSocket server") 13 | parser.add_argument("--host", default="127.0.0.1", help="Bind to this address") 14 | parser.add_argument("--port", type=int, default=2087, help="Bind to this port") 15 | 16 | 17 | def main(): 18 | parser = argparse.ArgumentParser() 19 | add_arguments(parser) 20 | args = parser.parse_args() 21 | 22 | if args.tcp: 23 | spacy_server.start_tcp(args.host, args.port) 24 | elif args.ws: 25 | spacy_server.start_ws(args.host, args.port) 26 | else: 27 | spacy_server.start_io() 28 | 29 | 30 | if __name__ == "__main__": 31 | main() 32 | -------------------------------------------------------------------------------- /server/feature_hover.py: -------------------------------------------------------------------------------- 1 | """Script containing all logic for hover functionality""" 2 | 3 | from lsprotocol.types import ( 4 | Position, 5 | Range, 6 | Hover, 7 | TextDocumentPositionParams, 8 | MarkupContent, 9 | MarkupKind, 10 | Range, 11 | ) 12 | 13 | import re 14 | from typing import Optional 15 | from spacy import registry, schemas, glossary 16 | from .spacy_server import SpacyLanguageServer 17 | from .util import get_current_word, SpanInfo, format_docstrings 18 | from dataclasses import dataclass 19 | from catalogue import RegistryError # type:ignore[import] 20 | 21 | # TODO: glossary for now, to be replaced with glossary.CONFIG_DESCRIPTIONS from spacy 22 | CONFIG_DESCRIPTIONS = { 23 | "nlp": "Definition of the `Language` object, its tokenizer and processing pipeline component names.", 24 | "components": "Definitions of the pipeline components and their models. Pipeline components can be found in [nlp].", 25 | "paths": "Paths to data and other assets. Re-used across the config as variables, e.g. `${paths.train}`, and can be overridden by the CLI.", 26 | "system": "Settings related to system and hardware. Re-used across the config as variables, e.g. `${system.seed}`, and can be overridden by the CLI.", 27 | "training": "Settings and controls for the training and evaluation process.", 28 | "pretraining": "Optional settings and controls for the language model pretraining.", 29 | "initialize": "Data resources and arguments passed to components when `nlp.initialize` is called before training (but not at inference-time).", 30 | "corpora": "Readers for corpora like dev and train.", 31 | } 32 | 33 | 34 | def hover( 35 | server: SpacyLanguageServer, params: TextDocumentPositionParams 36 | ) -> Optional[Hover]: 37 | """ 38 | Implements the Hover functionality 39 | """ 40 | document = server.workspace.get_document(params.text_document.uri) 41 | 42 | if not document: 43 | return None 44 | 45 | # get the config as a dictinary 46 | config_dict = server.config 47 | 48 | line_n = params.position.line 49 | line_str = document.lines[line_n] 50 | current_span = get_current_word(line_str, params.position.character) 51 | 52 | hover_object = registry_resolver( 53 | line_str, current_span.span_string, current_span.start, current_span.end 54 | ) 55 | if hover_object is None: 56 | hover_object = section_resolver( 57 | line_str, current_span.span_string, current_span.start, current_span.end 58 | ) 59 | if hover_object is None and config_dict != None: 60 | hover_object = variable_resolver(line_str, config_dict) # type:ignore[arg-type] 61 | 62 | if hover_object is not None: 63 | return Hover( 64 | contents=MarkupContent( 65 | kind=MarkupKind.Markdown, value=hover_object.span_string 66 | ), 67 | range=Range( 68 | start=Position(line=line_n, character=hover_object.start), 69 | end=Position(line=line_n, character=hover_object.end + 1), 70 | ), 71 | ) 72 | else: 73 | return None 74 | 75 | 76 | def registry_resolver( 77 | line_str: str, current_word: str, w_start: int, w_end: int 78 | ) -> Optional[SpanInfo]: 79 | """ 80 | Check if currently hovered text is registered in the spaCy registry and return its description. 81 | 82 | ARGUMENTS: 83 | line_str (str): the current line as a string. 84 | current_word (str): the current word being hovered. 85 | w_start (int): The start index of the current_word. 86 | w_end (int): The end index of the current_word. 87 | """ 88 | 89 | registry_span = detect_registry_func(line_str, current_word, w_start, w_end) 90 | if registry_span: 91 | # the name of the function within the registry 92 | registry_func = registry_span.span_string 93 | r_start = registry_span.start 94 | r_end = registry_span.end 95 | # the name of the registry, e.x. "architectures" or "factory" 96 | registry_name = detect_registry_name(line_str, r_start) 97 | else: 98 | return None 99 | 100 | # hardcoded renaming for factories 101 | if registry_name == "factory": 102 | registry_name = "factories" 103 | 104 | try: 105 | # Retrieve data from registry 106 | registry_desc = registry.find(registry_name, registry_func) 107 | 108 | except RegistryError as e: 109 | return None 110 | 111 | # get the path to the file and line number of registered function 112 | registry_link = "" 113 | if registry_desc["file"]: # type:ignore[index] 114 | registry_path = registry_desc["file"] # type:ignore[index] 115 | line_no = registry_desc["line_no"] # type:ignore[index] 116 | registry_link = f"[Go to code](file://{registry_path}#L{line_no})" 117 | 118 | # find registry description or return no description 119 | registry_docstring = ( 120 | registry_desc.get("docstring") # type:ignore[attr-defined] 121 | or "Currently no description available" 122 | ) 123 | 124 | # Fix the formatting of docstrings for display in hover 125 | formatted_docstring = format_docstrings(registry_docstring) # type:ignore[arg-type] 126 | hover_display = ( 127 | f"### (*registry*) {registry_func}\n\n{registry_link}\n\n{formatted_docstring}" 128 | ) 129 | return SpanInfo(hover_display, r_start, r_end) 130 | 131 | 132 | def detect_registry_func( 133 | line: str, current_word: str, w_start: int, w_end: int 134 | ) -> Optional[SpanInfo]: 135 | """ 136 | Detect if a word indicates a registry name. 137 | 138 | ARGUMENTS: 139 | line (str): the current line as a string. 140 | current_word (str): the current word as a string. 141 | w_start (int): The start index of the current_word. 142 | w_end (int): The end index of the current_word. 143 | 144 | EXAMPLES: 145 | spacy.registry_name_.v1 146 | spacy-legacy.registry_name.v2 147 | compounding.v1 148 | textcat 149 | """ 150 | 151 | # Special Case for Factories 152 | # Because their registry_names can be "ner", "textcat" 153 | if "factory" in line: 154 | return SpanInfo(current_word, w_start, w_end) 155 | 156 | # match optional first segment (i.e. .), required second segment and version (i.e. ".v") 157 | registry_regex = r"([\w]*\.)?[\w]*\.v[\d]*" 158 | registry_match = re.search(registry_regex, line) 159 | 160 | if registry_match is None: 161 | return None 162 | 163 | full_registry_func = registry_match.group(0) 164 | if current_word in full_registry_func: 165 | # if actually hovering over part of the registry name, return values 166 | registry_func_start = registry_match.span()[0] 167 | registry_func_end = registry_match.span()[1] - 1 168 | return SpanInfo(full_registry_func, registry_func_start, registry_func_end) 169 | 170 | return None 171 | 172 | 173 | def detect_registry_name(line: str, registry_start: int) -> str: 174 | """ 175 | Detect type and return type and name of registry. 176 | 177 | ARGUMENTS: 178 | line (str): the current line as a string. 179 | registry_start (int): The start index of the current hover word. 180 | 181 | RETURN: 182 | full_registry_func (str): The full registry function as a string 183 | 184 | EXAMPLE: 185 | @architecture 186 | factory 187 | """ 188 | 189 | if registry_start <= 0: 190 | return "" 191 | 192 | for i in range(registry_start - 1, 0, -1): 193 | if re.match(r"\W", line[i]): 194 | continue 195 | else: 196 | type_span = get_current_word(line, i) 197 | return type_span.span_string 198 | return "" 199 | 200 | 201 | def section_resolver( 202 | line_str: str, current_word: str, w_start: int, w_end: int 203 | ) -> Optional[SpanInfo]: 204 | """ 205 | Check if current hovered text is a section title and then return it's description. 206 | 207 | ARGUMENTS: 208 | line_str (str): the current line as a string. 209 | current_word (str): the current word being hovered. 210 | w_start (int): The start index of the current_word. 211 | w_end (int): The end index of the current_word. 212 | 213 | EXAMPLES: 214 | [training] 215 | [training.batcher.size] 216 | """ 217 | 218 | config_schemas = { 219 | "nlp": schemas.ConfigSchemaNlp, 220 | "training": schemas.ConfigSchemaTraining, 221 | "pretraining": schemas.ConfigSchemaPretrain, 222 | "initialize": schemas.ConfigSchemaInit, 223 | } 224 | 225 | # match the section titles, always start with a bracket and more than 1 character 226 | if line_str[0] != "[" or len(current_word) <= 1: 227 | return None 228 | 229 | # break section into a list of components 230 | sections_list = line_str[1:-2].split(".") 231 | main_section = sections_list[0] 232 | sub_section = sections_list[1] if len(sections_list) > 1 else "" 233 | 234 | # if the current hover word is in the dictionary of descriptions 235 | if current_word in CONFIG_DESCRIPTIONS.keys(): 236 | hover_display = ( 237 | f"(*section*) **{current_word}**: {CONFIG_DESCRIPTIONS[current_word]}" 238 | ) 239 | return SpanInfo(hover_display, w_start, w_end) 240 | elif current_word == sub_section and main_section in config_schemas.keys(): 241 | # get field title from the config schema 242 | field_title = ( 243 | config_schemas[main_section] 244 | .__fields__[sub_section] # type:ignore[attr-defined] 245 | .field_info.title 246 | ) 247 | hover_display = ( 248 | f"(*section*) {main_section} -> **{sub_section}**: {field_title}" 249 | ) 250 | return SpanInfo(hover_display, w_start, w_end) 251 | else: 252 | return None 253 | 254 | 255 | def variable_resolver( 256 | line_str: str, 257 | config_dict: dict, 258 | ) -> Optional[SpanInfo]: 259 | """ 260 | Check if current hovered text is a variable and then return it's value. 261 | 262 | ARGUMENTS: 263 | line_str (str): the current line as a string. 264 | config_dict (dict): the config file as a dictionary 265 | 266 | EXAMPLES: 267 | ${system.seed} 268 | ${components.tok2vec.model.encode.width} 269 | """ 270 | 271 | # match the variables, always enclosed with ${} 272 | variable_regex = r"(?<=\$\{)[^][]*(?=})" 273 | variable_match = re.search(variable_regex, line_str) 274 | 275 | if variable_match is None: 276 | return None 277 | 278 | variable_list = variable_match.group(0).split(".") 279 | v_start = variable_match.span()[0] 280 | v_end = variable_match.span()[1] - 1 281 | 282 | # get value for final item in the variable from nested config dict 283 | for key in variable_list[:-1]: 284 | config_dict = config_dict.setdefault(key, {}) 285 | variable_value = config_dict[variable_list[-1]] 286 | 287 | hover_display = ( 288 | f"(*variable*) **{'.'.join(variable_list)}**: `{str(variable_value)}`" 289 | ) 290 | return SpanInfo(hover_display, v_start, v_end) 291 | -------------------------------------------------------------------------------- /server/feature_validation.py: -------------------------------------------------------------------------------- 1 | """Script containing all logic for validation functionality""" 2 | from lsprotocol.types import DidOpenTextDocumentParams 3 | 4 | from thinc.api import Config 5 | from typing import Optional 6 | from .spacy_server import SpacyLanguageServer 7 | 8 | 9 | def validate_config( 10 | server: SpacyLanguageServer, cfg: Optional[str] 11 | ) -> Optional[Config]: 12 | """Validate .cfg files and return their Config object""" 13 | try: 14 | config = Config().from_str(cfg) # type: ignore[arg-type] 15 | server.show_message_log("Validation Successful") 16 | return config 17 | except Exception as e: 18 | server.show_message_log("Validation Unsuccessful") 19 | server.show_message("Warning: Config not valid ") 20 | return None 21 | -------------------------------------------------------------------------------- /server/server.py: -------------------------------------------------------------------------------- 1 | from lsprotocol.types import ( 2 | TEXT_DOCUMENT_DID_OPEN, 3 | TEXT_DOCUMENT_DID_SAVE, 4 | TEXT_DOCUMENT_HOVER, 5 | DidOpenTextDocumentParams, 6 | DidSaveTextDocumentParams, 7 | Hover, 8 | TextDocumentPositionParams, 9 | ) 10 | 11 | from typing import Optional 12 | import spacy 13 | from .feature_hover import hover 14 | from .feature_validation import validate_config 15 | from .spacy_server import SpacyLanguageServer 16 | 17 | 18 | spacy_server = SpacyLanguageServer("pygls-spacy-server", "v0.1") 19 | 20 | 21 | @spacy_server.feature(TEXT_DOCUMENT_HOVER) 22 | def hover_feature( 23 | server: SpacyLanguageServer, params: TextDocumentPositionParams 24 | ) -> Optional[Hover]: 25 | """Implement Hover functionality""" 26 | 27 | if spacy_server.doc_uri != params.text_document.uri: 28 | document = server.workspace.get_document(params.text_document.uri) 29 | spacy_server.config = validate_config(server=server, cfg=document.source) 30 | if spacy_server.config: 31 | spacy_server.doc_uri = params.text_document.uri 32 | 33 | return hover(server, params) 34 | 35 | 36 | @spacy_server.feature(TEXT_DOCUMENT_DID_OPEN) 37 | async def did_open(server: SpacyLanguageServer, params: DidOpenTextDocumentParams): 38 | """Text document did open notification.""" 39 | spacy_server.config = validate_config(server=server, cfg=params.text_document.text) 40 | if spacy_server.config: 41 | spacy_server.doc_uri = params.text_document.uri 42 | server.show_message("spaCy Extension Active") 43 | 44 | 45 | @spacy_server.feature(TEXT_DOCUMENT_DID_SAVE) 46 | async def did_save(server: SpacyLanguageServer, params: DidSaveTextDocumentParams): 47 | """Text document did save notification.""" 48 | document = server.workspace.get_document(params.text_document.uri) 49 | spacy_server.config = validate_config(server=server, cfg=document.source) 50 | if spacy_server.config: 51 | spacy_server.doc_uri = params.text_document.uri 52 | -------------------------------------------------------------------------------- /server/spacy_server.py: -------------------------------------------------------------------------------- 1 | from pygls.server import LanguageServer 2 | 3 | from thinc.api import Config 4 | from typing import Optional 5 | 6 | 7 | class SpacyLanguageServer(LanguageServer): 8 | """ 9 | The language server is responsible for receiving and sending messages over the Language Server Protocol 10 | which is based on the Json RPC protocol. 11 | DOCS: https://pygls.readthedocs.io/en/latest/pages/advanced_usage.html#language-server 12 | """ 13 | 14 | def __init__(self, *args): 15 | super().__init__(*args) 16 | self.config: Optional[Config] = None 17 | self.doc_uri: str = None 18 | -------------------------------------------------------------------------------- /server/tests/__init__.py: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # Copyright(c) Open Law Library. All rights reserved. # 3 | # See ThirdPartyNotices.txt in the project root for additional notices. # 4 | # # 5 | # Licensed under the Apache License, Version 2.0 (the "License") # 6 | # you may not use this file except in compliance with the License. # 7 | # You may obtain a copy of the License at # 8 | # # 9 | # http: // www.apache.org/licenses/LICENSE-2.0 # 10 | # # 11 | # Unless required by applicable law or agreed to in writing, software # 12 | # distributed under the License is distributed on an "AS IS" BASIS, # 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 14 | # See the License for the specific language governing permissions and # 15 | # limitations under the License. # 16 | ############################################################################ 17 | -------------------------------------------------------------------------------- /server/tests/requirements.txt: -------------------------------------------------------------------------------- 1 | pytest==7.2.1 2 | mock 3 | types-mock 4 | mypy==1.0.1 5 | black==23.3.0 -------------------------------------------------------------------------------- /server/tests/test_features.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from mock import Mock 3 | from lsprotocol.types import ( 4 | TextDocumentIdentifier, 5 | TextDocumentPositionParams, 6 | Position, 7 | ) 8 | from pygls.workspace import Document, Workspace 9 | from thinc.api import Config 10 | from spacy import registry 11 | 12 | from ..server import hover_feature 13 | from ..feature_validation import validate_config 14 | from ..util import format_docstrings 15 | 16 | 17 | class FakeServer: 18 | """We don't need real server to unit test features.""" 19 | 20 | publish_diagnostics = None 21 | show_message = None 22 | show_message_log = None 23 | 24 | def __init__(self): 25 | self.workspace = Workspace("", None) 26 | self.config: Config = None 27 | 28 | 29 | fake_document_uri = "file://fake_config.cfg" 30 | fake_document_content = """ 31 | [paths] 32 | train = null 33 | dev = null 34 | vectors = null 35 | init_tok2vec = null 36 | 37 | [system] 38 | gpu_allocator = null 39 | seed = 0 40 | 41 | [nlp] 42 | lang = "id" 43 | pipeline = ["tok2vec","ner"] 44 | batch_size = 1000 45 | disabled = [] 46 | before_creation = null 47 | after_creation = null 48 | after_pipeline_creation = null 49 | tokenizer = {"@tokenizers":"spacy.Tokenizer.v1"} 50 | 51 | [components] 52 | 53 | [components.ner] 54 | factory = "ner" 55 | moves = null 56 | update_with_oracle_cut_size = 100 57 | 58 | [components.ner.model] 59 | @architectures = "spacy.TransitionBasedParser.v2" 60 | state_type = "ner" 61 | extra_state_tokens = false 62 | hidden_width = 64 63 | maxout_pieces = 2 64 | use_upper = true 65 | nO = null 66 | 67 | [components.ner.model.tok2vec] 68 | @architectures = "spacy.Tok2VecListener.v1" 69 | width = ${components.tok2vec.model.encode.width} 70 | upstream = "*" 71 | 72 | [components.tok2vec] 73 | factory = "tok2vec" 74 | 75 | [components.tok2vec.model] 76 | @architectures = "spacy.Tok2Vec.v2" 77 | 78 | [components.tok2vec.model.embed] 79 | @architectures = "spacy.MultiHashEmbed.v2" 80 | width = ${components.tok2vec.model.encode.width} 81 | attrs = ["NORM","PREFIX","SUFFIX","SHAPE"] 82 | rows = [5000,2500,2500,2500] 83 | include_static_vectors = false 84 | 85 | [components.tok2vec.model.encode] 86 | @architectures = "spacy.MaxoutWindowEncoder.v2" 87 | width = 96 88 | depth = 4 89 | window_size = 1 90 | maxout_pieces = 3 91 | 92 | [corpora] 93 | 94 | [corpora.dev] 95 | @readers = "spacy.Corpus.v1" 96 | path = ${paths.dev} 97 | max_length = 0 98 | gold_preproc = false 99 | limit = 0 100 | augmenter = null 101 | 102 | [corpora.train] 103 | @readers = "spacy.Corpus.v1" 104 | path = ${paths.train} 105 | max_length = 2000 106 | gold_preproc = false 107 | limit = 0 108 | augmenter = null 109 | 110 | [training] 111 | dev_corpus = "corpora.dev" 112 | train_corpus = "corpora.train" 113 | seed = ${system.seed} 114 | gpu_allocator = ${system.gpu_allocator} 115 | dropout = 0.1 116 | accumulate_gradient = 1 117 | patience = 1600 118 | max_epochs = 0 119 | max_steps = 20000 120 | eval_frequency = 200 121 | frozen_components = [] 122 | before_to_disk = null 123 | 124 | [training.batcher] 125 | @batchers = "spacy.batch_by_words.v1" 126 | discard_oversize = false 127 | tolerance = 0.2 128 | get_length = null 129 | 130 | [training.batcher.size] 131 | @schedules = "compounding.v1" 132 | start = 100 133 | stop = 1000 134 | compound = 1.001 135 | t = 0.0 136 | 137 | [training.logger] 138 | @loggers = "spacy.ConsoleLogger.v1" 139 | progress_bar = false 140 | 141 | [training.optimizer] 142 | @optimizers = "Adam.v1" 143 | beta1 = 0.9 144 | beta2 = 0.999 145 | L2_is_weight_decay = true 146 | L2 = 0.01 147 | grad_clip = 1.0 148 | use_averages = false 149 | eps = 0.00000001 150 | learn_rate = 0.001 151 | 152 | [training.score_weights] 153 | ents_per_type = null 154 | ents_f = 1.0 155 | ents_p = 0.0 156 | ents_r = 0.0 157 | 158 | [pretraining] 159 | 160 | [initialize] 161 | vectors = null 162 | init_tok2vec = ${paths.init_tok2vec} 163 | vocab_data = null 164 | lookups = null 165 | before_init = null 166 | after_init = null 167 | 168 | [initialize.components] 169 | 170 | [initialize.tokenizer] 171 | """ 172 | 173 | fake_document = Document(fake_document_uri, fake_document_content) 174 | 175 | fake_document_content_non_valid = """ 176 | [paths] 177 | train = null 178 | dev = null 179 | vectors = null 180 | init_tok2vec = null 181 | 182 | [system] 183 | gpu_allocator = null 184 | seed = 0 185 | 186 | [nlp] 187 | lang = "id" 188 | pipeline = ["tok2vec","ner"] 189 | batch_size = 1000 190 | disabled = [] 191 | before_creation = null 192 | after_creation = null 193 | after_pipeline_creation = null 194 | tokenizer = {"@tokenizers":"spacy.Tokenizer.v1"} 195 | 196 | [components] 197 | 198 | [components.ner] 199 | factory = "ner" 200 | moves = null 201 | update_with_oracle_cut_size = 100 202 | 203 | [components.ner.model] 204 | @architectures = "spacy.TransitionBasedParser.v2" 205 | state_typtokens = false 206 | hidden_width = 64 207 | maxout_pieces = 2 208 | use_upper = true 209 | nO = null 210 | 211 | [components.ner.model.tok2vec] 212 | @architectures = "spacy.Tok2VecListener.v1" 213 | width = ${components.tok2vec.model.encode.width} 214 | upstream = "*" 215 | 216 | [components.tok2vec] 217 | factory = "tok2vec" 218 | 219 | [components.tok2vec.model] 220 | @architectures = "spacy.Tok2Vec.v2" 221 | 222 | [components.tok2vec.model.embed] 223 | @architectures = "spacy.MultiHashEmbed.v2" 224 | width = ${components.tok2vec.model.encode.width} 225 | attrs = ["NORM","PREFIX","SUFFIX","SHAPE"] 226 | rows = [5000,2500,2500,2500] 227 | include_static_vectors = false 228 | 229 | [components.tok2vec.model.encode] 230 | @architectures = "spacy.MaxoutWindowEncoder.v2" 231 | width = 96 232 | depth = 4 233 | window_size = 1 234 | maxout_pieces = 3 235 | 236 | [corpora] 237 | 238 | [corpora.dev] 239 | @readers = "spacy.Corpus.v1" 240 | path = ${paths.dev} 241 | max_length = 0 242 | gold_preproc = false 243 | limit = 0 244 | augmenter = null 245 | 246 | [corpora.train] 247 | @readers = "spacy.Corpus.v1" 248 | path = ${paths.train} 249 | max_length = 2000 250 | gold_preproc = false 251 | limit = 0 252 | augmenter = null 253 | 254 | [tra] 255 | dev_corpus = "corpora.dev" 256 | train_corpus = "corpora.train" 257 | seed = ${system.seed} 258 | gpu_allocator = ${system.gpu_allocator} 259 | dropout = 0.1 260 | accumulate_gradient = 1 261 | patience = 1600 262 | max_epochs = 0 263 | max_steps = 20000 264 | eval_frequency = 200 265 | frozen_components = [] 266 | before_to_disk = null 267 | 268 | [training.batcher] 269 | @batchers = "spacy.batch_by_words.v1" 270 | discard_oversize = false 271 | tolerance = 0.2 272 | get_length = null 273 | 274 | [training.batch 275 | @schedules = "compounding.v1" 276 | start = 100 277 | stop = 1000 278 | compound = 1.001 279 | t = 0.0 280 | 281 | [training.logger] 282 | @loggers = "spacy.ConsoleLogger.v1" 283 | progress_ 284 | 285 | [training.optimizer] 286 | @optimizers = "Adam.v1" 287 | beta1 = 0.9 288 | beta2 = 0.999 289 | L2_is_weight_decay = true 290 | L2 = 0.01 291 | grad_clip = 1.0 292 | use_averages = false 293 | eps = 0.00000001 294 | learn_rate = 0.001 295 | 296 | [training.score_weights] 297 | ents_per_type = null 298 | ents 1.0 299 | ents_p = 0.0 300 | ents_r = 0.0 301 | 302 | [pretraining] 303 | 304 | [initialize] 305 | vectors = n 306 | init_tok2vec = ${paths.init_tok2vec} 307 | vocab_data = null 308 | lookups = null 309 | before_init = null 310 | after_init = null 311 | 312 | [initialize.compo 313 | 314 | [initialize.tokenizer] 315 | """ 316 | 317 | server = FakeServer() 318 | server.publish_diagnostics = Mock() # type:ignore[assignment] 319 | server.show_message = Mock() # type:ignore[assignment] 320 | server.show_message_log = Mock() # type:ignore[assignment] 321 | server.workspace.get_document = Mock(return_value=fake_document) 322 | 323 | 324 | def _reset_mocks(): 325 | server.publish_diagnostics.reset_mock() 326 | server.show_message.reset_mock() 327 | server.show_message_log.reset_mock() 328 | 329 | 330 | # Test Hover Resolve Registries 331 | @pytest.mark.parametrize( 332 | "line, character, registry_func", 333 | [ 334 | (19, 36, "spacy.Tokenizer.v1"), 335 | (24, 13, "ner"), 336 | (43, 14, "tok2vec"), 337 | (49, 32, "spacy.MultiHashEmbed.v2"), 338 | (56, 34, "spacy.MaxoutWindowEncoder.v2"), 339 | (73, 22, "spacy.Corpus.v1"), 340 | (95, 23, "spacy.batch_by_words.v1"), 341 | (101, 22, "compounding.v1"), 342 | ], 343 | ) 344 | def test_resolve_registries(line, character, registry_func): 345 | _reset_mocks() 346 | params = TextDocumentPositionParams( 347 | text_document=TextDocumentIdentifier(uri=fake_document.uri), 348 | position=Position(line=line, character=character), 349 | ) 350 | hover_obj = hover_feature(server, params) 351 | assert registry_func in hover_obj.contents.value 352 | 353 | 354 | # Test Hover Resolve Sections 355 | @pytest.mark.parametrize( 356 | "line, character, section_name", 357 | [ 358 | (72, 1, "corpora"), 359 | (80, 1, "training"), 360 | (94, 10, "batcher"), 361 | ], 362 | ) 363 | def test_resolve_sections(line, character, section_name): 364 | _reset_mocks() 365 | params = TextDocumentPositionParams( 366 | text_document=TextDocumentIdentifier(uri=fake_document.uri), 367 | position=Position(line=line, character=character), 368 | ) 369 | hover_obj = hover_feature(server, params) 370 | assert section_name in hover_obj.contents.value 371 | 372 | 373 | # Test formatting of docstrings 374 | @pytest.mark.parametrize( 375 | "registry_func, registry_name, docstring, formatted_docstring", 376 | [ 377 | ( 378 | "spacy.Tokenizer.v1", 379 | "tokenizers", 380 | "Registered function to create a tokenizer. Returns a factory that takes\nthe nlp object and returns a Tokenizer instance using the language detaults.", 381 | "Registered function to create a tokenizer. Returns a factory that takes\nthe nlp object and returns a Tokenizer instance using the language detaults.", 382 | ), 383 | ( 384 | "morphologizer", 385 | "factories", 386 | "make_morphologizer(nlp: Language, model: Model, name: str, overwrite: bool, extend: bool, scorer: Optional[Callable])", 387 | "\n#### Arguments:\n\n - nlp: Language\n\n - model: Model\n\n - name: str\n\n - overwrite: bool\n\n - extend: bool\n\n - scorer: Optional[Callable]", 388 | ), 389 | ( 390 | "tok2vec", 391 | "factories", 392 | "Currently no description available", 393 | "Currently no description available", 394 | ), 395 | ( 396 | "spacy.MultiHashEmbed.v2", 397 | "architectures", 398 | "Construct an embedding layer that separately embeds a number of lexical\nattributes using hash embedding, concatenates the results, and passes it\nthrough a feed-forward subnetwork to build a mixed representation.\n\nThe features used can be configured with the 'attrs' argument. The suggested\nattributes are NORM, PREFIX, SUFFIX and SHAPE. This lets the model take into\naccount some subword information, without constructing a fully character-based\nrepresentation. If pretrained vectors are available, they can be included in\nthe representation as well, with the vectors table kept static\n(i.e. it's not updated).\n\nThe `width` parameter specifies the output width of the layer and the widths\nof all embedding tables. If static vectors are included, a learned linear\nlayer is used to map the vectors to the specified width before concatenating\nit with the other embedding outputs. A single Maxout layer is then used to\nreduce the concatenated vectors to the final width.\n\nThe `rows` parameter controls the number of rows used by the `HashEmbed`\ntables. The HashEmbed layer needs surprisingly few rows, due to its use of\nthe hashing trick. Generally between 2000 and 10000 rows is sufficient,\neven for very large vocabularies. A number of rows must be specified for each\ntable, so the `rows` list must be of the same length as the `attrs` parameter.\n\nwidth (int): The output width. Also used as the width of the embedding tables.\n Recommended values are between 64 and 300.\nattrs (list of attr IDs): The token attributes to embed. A separate\n embedding table will be constructed for each attribute.\nrows (List[int]): The number of rows in the embedding tables. Must have the\n same length as attrs.\ninclude_static_vectors (bool): Whether to also use static word vectors.\n Requires a vectors table to be loaded in the Doc objects' vocab.", 399 | "Construct an embedding layer that separately embeds a number of lexical\nattributes using hash embedding, concatenates the results, and passes it\nthrough a feed-forward subnetwork to build a mixed representation.\n\nThe features used can be configured with the 'attrs' argument. The suggested\nattributes are NORM, PREFIX, SUFFIX and SHAPE. This lets the model take into\naccount some subword information, without constructing a fully character-based\nrepresentation. If pretrained vectors are available, they can be included in\nthe representation as well, with the vectors table kept static\n(i.e. it's not updated).\n\nThe `width` parameter specifies the output width of the layer and the widths\nof all embedding tables. If static vectors are included, a learned linear\nlayer is used to map the vectors to the specified width before concatenating\nit with the other embedding outputs. A single Maxout layer is then used to\nreduce the concatenated vectors to the final width.\n\nThe `rows` parameter controls the number of rows used by the `HashEmbed`\ntables. The HashEmbed layer needs surprisingly few rows, due to its use of\nthe hashing trick. Generally between 2000 and 10000 rows is sufficient,\neven for very large vocabularies. A number of rows must be specified for each\ntable, so the `rows` list must be of the same length as the `attrs` parameter.\n#### Arguments:\n\n - width (int): The output width. Also used as the width of the embedding tables. Recommended values are between 64 and 300.\n\n - attrs (list of attr IDs): The token attributes to embed. A separate embedding table will be constructed for each attribute.\n\n - rows (List[int]): The number of rows in the embedding tables. Must have the same length as attrs.\n\n - include_static_vectors (bool): Whether to also use static word vectors. Requires a vectors table to be loaded in the Doc objects' vocab.", 400 | ), 401 | ], 402 | ) 403 | def test_hover_formatting(registry_func, registry_name, docstring, formatted_docstring): 404 | _reset_mocks() 405 | 406 | registry_desc = registry.find(registry_name, registry_func) 407 | 408 | registry_docstring = ( 409 | registry_desc.get("docstring") or "Currently no description available" 410 | ) 411 | assert registry_docstring == docstring 412 | 413 | registry_formatted_docstring = format_docstrings(registry_docstring) 414 | assert registry_formatted_docstring == formatted_docstring 415 | 416 | 417 | # Test validation of configs 418 | @pytest.mark.parametrize( 419 | "cfg, valid", 420 | [(fake_document_content, True), (fake_document_content_non_valid, False)], 421 | ) 422 | def test_validation(cfg, valid): 423 | _reset_mocks() 424 | config = validate_config(server, cfg) 425 | if config: 426 | _valid = True 427 | else: 428 | _valid = False 429 | assert _valid == valid 430 | -------------------------------------------------------------------------------- /server/util.py: -------------------------------------------------------------------------------- 1 | """Script for utility functions that can be used across the other implementations""" 2 | 3 | import re 4 | from dataclasses import dataclass 5 | 6 | 7 | @dataclass 8 | class SpanInfo: 9 | span_string: str # The span text, can have markdown elements 10 | start: int # Start index of the string 11 | end: int # End index of the string 12 | 13 | 14 | def get_current_word(line: str, start_pos: int) -> SpanInfo: 15 | """ 16 | Returns the a span string seperated by non-word characters 17 | 18 | EXAMPLE OUTPUT: 19 | ('architectures', 1, 13) 20 | ('spacy', 18, 22) 21 | """ 22 | 23 | # Verify index lies within boundaries 24 | if start_pos < 0 or start_pos >= len(line): 25 | return SpanInfo("", 0, 0) 26 | 27 | end_i = start_pos 28 | start_i = start_pos 29 | 30 | for i in range(start_pos, len(line), 1): 31 | if re.match(r"\W", line[i]): 32 | break 33 | else: 34 | end_i = i 35 | 36 | for i in range(start_pos, -1, -1): 37 | if re.match(r"\W", line[i]): 38 | break 39 | else: 40 | start_i = i 41 | 42 | return SpanInfo(line[start_i : end_i + 1], start_i, end_i) 43 | 44 | 45 | def format_docstrings(docstring: str): 46 | """ 47 | Formats the docstring into compatible Markdown for hover display 48 | """ 49 | docstring_split = docstring.split("\n\n") 50 | 51 | has_func = False 52 | has_args = False 53 | has_format = False 54 | 55 | # test docstring for formatting features 56 | if docstring_split[0].count("make_") == 1: 57 | has_func = True 58 | if docstring_split[-1].count(":") > 1 and docstring_split[-1].count("make_") != 1: 59 | has_args = True 60 | if "\n " in docstring: 61 | has_format = True 62 | 63 | # if no re-formatting features, return the docstring as is 64 | if not has_func and not has_args and not has_format: 65 | return docstring 66 | 67 | # if the string has a make function and not argument descriptions, 68 | # just return the arguments and other additional info if present 69 | if has_func: 70 | if not has_args: 71 | registry_arguments = docstring_split[0] 72 | registry_arguments = "\n\n - ".join( 73 | registry_arguments.split("(")[1][:-1].split(",") 74 | ) 75 | # remove first paragraph from docstring 76 | registry_info = "\n\n".join(docstring_split[1:]) or "" 77 | # remove the make function if it has arguments 78 | docstring_split = docstring_split[1:] 79 | 80 | # if docstring has formatting issues (has_format = True) and has an argument list 81 | if has_format and has_args: 82 | # create the arguments list from the last paragraph, 83 | # remove unnessesary \n and replace others with paragraph breaking \n\n and bullet points 84 | registry_arguments = ( 85 | docstring_split[-1][:-2] 86 | .replace("\n ", "") 87 | .replace("\n ", "\n\n - ") 88 | ) 89 | # reformat all other paragraphs 90 | # remove unnessesary \n and replace others with paragraph breaking \n\n 91 | registry_info = ( 92 | "\n\n".join(docstring_split[:-1]).replace("\n ", "").replace("\n", "\n\n") 93 | ) 94 | elif has_args: 95 | # create the arguments list from the last paragraph, 96 | # remove unnessesary \n and replace others with paragraph breaking \n\n and bullet points 97 | registry_arguments = ( 98 | docstring_split[-1].replace("\n ", "").replace("\n", "\n\n - ") 99 | ) 100 | # remove last paragraph from info 101 | registry_info = "\n\n".join(docstring_split[:-1]) 102 | 103 | if registry_arguments: 104 | formatted_docstring = ( 105 | f"{registry_info}\n#### Arguments:\n\n - {registry_arguments}" 106 | ) 107 | return formatted_docstring 108 | elif has_func: 109 | # if make function name is present with no arguments, return no description 110 | return "Currently no description available" 111 | else: 112 | return docstring 113 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true, 4 | "resolveJsonModule": true, 5 | "module": "commonjs", 6 | "target": "es2019", 7 | "lib": ["ES2019"], 8 | "rootDir": "client/src", 9 | "outDir": "client/out", 10 | "sourceMap": true 11 | }, 12 | "include": ["client/src"], 13 | "exclude": ["node_modules"] 14 | } 15 | --------------------------------------------------------------------------------