├── .nvmrc ├── .github ├── FUNDING.yml └── workflows │ └── codeql-analysis.yml ├── src ├── lib │ ├── const.ts │ ├── logger.ts │ ├── types │ │ ├── collection.ts │ │ ├── node.ts │ │ └── vscode.ts │ ├── commands │ │ ├── extension-command.ts │ │ ├── clear-history.ts │ │ ├── run-input.ts │ │ ├── run-quick.ts │ │ └── run.ts │ ├── errors │ │ └── command.ts │ ├── resolve-os-kind.ts │ ├── history-store.ts │ ├── error-message-formatter.ts │ ├── shell-settings-resolver.ts │ ├── adapters │ │ ├── workspace.ts │ │ └── editor.ts │ ├── shell-command-exec-context.ts │ ├── command-wrap.ts │ ├── process-runner.ts │ ├── command-reader.ts │ ├── app-integrator.ts │ ├── shell-command-service.ts │ └── app-integrator-factory.ts ├── test │ ├── tslint.json │ ├── lib │ │ ├── commands │ │ │ ├── clear-history.test.ts │ │ │ ├── run-input.test.ts │ │ │ └── run-quick.test.ts │ │ ├── error-message-formatter.test.ts │ │ ├── history-store.test.ts │ │ ├── adapters │ │ │ ├── workspace.test.ts │ │ │ └── editor.test.ts │ │ ├── command-wrap.test.ts │ │ ├── shell-command-exec-context.test.ts │ │ ├── command-reader.test.ts │ │ ├── shell-settings-resolver.test.ts │ │ └── shell-command-service.test.ts │ ├── index.ts │ └── helper.ts └── extension.ts ├── .gitignore ├── images ├── edit-with-shell.png └── animations │ ├── public.gif │ ├── insert-command-output.gif │ └── edit-and-run-command-history.gif ├── .mocharc.json ├── tag-release.sh ├── .nycrc ├── .editorconfig ├── .vscodeignore ├── tslint.json ├── tsconfig.json ├── .codeclimate.yml ├── .vscode └── launch.json ├── .travis.yml ├── LICENSE.txt ├── CHANGELOG.md ├── README.md ├── package.json └── yarn.lock /.nvmrc: -------------------------------------------------------------------------------- 1 | v12.14.1 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: ryu1kn 2 | -------------------------------------------------------------------------------- /src/lib/const.ts: -------------------------------------------------------------------------------- 1 | 2 | export const EXTENSION_NAME = 'editWithShell'; 3 | -------------------------------------------------------------------------------- /src/lib/logger.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface Logger { 3 | error(...args: any[]): void; 4 | } 5 | -------------------------------------------------------------------------------- /src/lib/types/collection.ts: -------------------------------------------------------------------------------- 1 | 2 | export type ObjectMap = { 3 | [p: string]: T; 4 | }; 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /.nyc_output 3 | /coverage 4 | /node_modules 5 | yarn-*.log 6 | /out 7 | *.vsix 8 | __* 9 | -------------------------------------------------------------------------------- /images/edit-with-shell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu1kn/vscode-edit-with-shell/HEAD/images/edit-with-shell.png -------------------------------------------------------------------------------- /.mocharc.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": ["ts-node/register"], 3 | "recursive": true, 4 | "spec": "src/test/**/*.ts" 5 | } 6 | -------------------------------------------------------------------------------- /images/animations/public.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu1kn/vscode-edit-with-shell/HEAD/images/animations/public.gif -------------------------------------------------------------------------------- /src/test/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tslint.json", 3 | "rules": { 4 | "no-unused-expression": false 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /images/animations/insert-command-output.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu1kn/vscode-edit-with-shell/HEAD/images/animations/insert-command-output.gif -------------------------------------------------------------------------------- /src/lib/types/node.ts: -------------------------------------------------------------------------------- 1 | import {ObjectMap} from './collection'; 2 | 3 | export interface EnvVarWrap { 4 | env: ObjectMap; 5 | } 6 | -------------------------------------------------------------------------------- /images/animations/edit-and-run-command-history.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu1kn/vscode-edit-with-shell/HEAD/images/animations/edit-and-run-command-history.gif -------------------------------------------------------------------------------- /src/lib/commands/extension-command.ts: -------------------------------------------------------------------------------- 1 | import {Editor} from '../adapters/editor'; 2 | 3 | export interface ExtensionCommand { 4 | execute(editor?: Editor): Promise; 5 | } 6 | -------------------------------------------------------------------------------- /tag-release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | RELEASE_VER="$(node -p 'require("./package.json").version')" 6 | 7 | GIT_TAG_NAME="v$RELEASE_VER" 8 | git tag -a "$GIT_TAG_NAME" -m "$GIT_TAG_NAME" 9 | git push origin "$GIT_TAG_NAME" 10 | -------------------------------------------------------------------------------- /.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "extension": [ 3 | ".ts" 4 | ], 5 | "exclude": [ 6 | "coverage", 7 | "src/test", 8 | "**/*.d.ts" 9 | ], 10 | "all": true, 11 | "reporter": [ 12 | "lcov", 13 | "text-summary" 14 | ], 15 | "report-dir": "./coverage" 16 | } 17 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | end_of_line = lf 7 | insert_final_newline = true 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | 11 | [*.js] 12 | indent_size = 4 13 | 14 | [*.{json,html,css,less,sass}] 15 | indent_size = 2 16 | -------------------------------------------------------------------------------- /src/lib/errors/command.ts: -------------------------------------------------------------------------------- 1 | 2 | export class CommandExecutionError extends Error { 3 | constructor(message: string, 4 | public readonly code: number, 5 | public readonly command: string, 6 | public readonly errorOutput: string) { 7 | super(message); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/lib/resolve-os-kind.ts: -------------------------------------------------------------------------------- 1 | import {ObjectMap} from './types/collection'; 2 | 3 | const OS_KIND = { 4 | darwin: 'osx', 5 | linux: 'linux', 6 | win32: 'windows' 7 | } as ObjectMap; 8 | const DEFAULT_OS_KIND = OS_KIND.linux; 9 | 10 | export default (platform: string) => OS_KIND[platform] || DEFAULT_OS_KIND; 11 | -------------------------------------------------------------------------------- /src/extension.ts: -------------------------------------------------------------------------------- 1 | import {AppIntegratorFactory} from './lib/app-integrator-factory'; 2 | import {ExecutionContextLike} from './lib/types/vscode'; 3 | 4 | exports.activate = (context: ExecutionContextLike) => { 5 | const appIntegrator = new AppIntegratorFactory().create(); 6 | appIntegrator.integrate(context); 7 | }; 8 | 9 | exports.deactivate = () => {}; 10 | -------------------------------------------------------------------------------- /src/lib/commands/clear-history.ts: -------------------------------------------------------------------------------- 1 | import {HistoryStore} from '../history-store'; 2 | import {ExtensionCommand} from './extension-command'; 3 | 4 | export class ClearHistoryCommand implements ExtensionCommand { 5 | constructor(private readonly historyStore: HistoryStore) {} 6 | 7 | async execute() { 8 | this.historyStore.clear(); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .codeclimate.yml 2 | .editorconfig 3 | .gitignore 4 | .idea/**/* 5 | .nvmrc 6 | .nyc_output/**/* 7 | .nycrc 8 | .travis.yml 9 | .vscode/**/* 10 | __* 11 | __*/**/* 12 | *.vsix 13 | .mocharc.json 14 | coverage/**/* 15 | images/animations/**/* 16 | yarn.lock 17 | yarn-*.log 18 | tag-release.sh 19 | src/**/* 20 | out/test/**/* 21 | out/**/*.map 22 | tsconfig.json 23 | tslint.json 24 | -------------------------------------------------------------------------------- /src/lib/types/vscode.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface ExecutionContextLike { 3 | subscriptions: any[]; 4 | } 5 | 6 | export interface PositionLike { 7 | line: number; 8 | character: number; 9 | } 10 | 11 | export interface RangeLike { 12 | start: PositionLike; 13 | end: PositionLike; 14 | } 15 | 16 | export type ShowErrorMessage = (message: string) => Thenable; 17 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-string-throw": true, 4 | "no-unused-expression": true, 5 | "no-duplicate-variable": true, 6 | "curly": [true, "ignore-same-line"], 7 | "class-name": true, 8 | "semicolon": [ 9 | true, 10 | "always" 11 | ], 12 | "quotemark": [true, "single", "avoid-escape"], 13 | "triple-equals": true 14 | }, 15 | "defaultSeverity": "error" 16 | } 17 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "outDir": "out", 6 | "lib": [ 7 | "es6", 8 | "es2017" 9 | ], 10 | "sourceMap": true, 11 | "rootDir": "src", 12 | "strict": true, 13 | "noUnusedLocals": true, 14 | "noFallthroughCasesInSwitch": true, 15 | "noUnusedParameters": true, 16 | "noImplicitReturns": true 17 | }, 18 | "exclude": [ 19 | "node_modules", 20 | ".vscode-test" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /src/test/lib/commands/clear-history.test.ts: -------------------------------------------------------------------------------- 1 | import {ClearHistoryCommand} from '../../../lib/commands/clear-history'; 2 | import {HistoryStore} from '../../../lib/history-store'; 3 | import {mockMethods, verify} from '../../helper'; 4 | 5 | describe('ClearHistoryCommand', () => { 6 | const historyStore = mockMethods(['clear']); 7 | const command = new ClearHistoryCommand(historyStore); 8 | 9 | it('clears command history', async () => { 10 | await command.execute(); 11 | 12 | verify(historyStore.clear(), {times: 1}); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | plugins: 3 | tslint: 4 | enabled: true 5 | config: tslint.json 6 | fixme: 7 | enabled: true 8 | checks: 9 | argument-count: 10 | enabled: true 11 | complex-logic: 12 | enabled: true 13 | file-lines: 14 | enabled: true 15 | method-complexity: 16 | enabled: true 17 | method-count: 18 | enabled: true 19 | method-lines: 20 | enabled: true 21 | nested-control-flow: 22 | enabled: true 23 | return-statements: 24 | enabled: true 25 | similar-code: 26 | enabled: false 27 | identical-code: 28 | enabled: true 29 | -------------------------------------------------------------------------------- /src/lib/history-store.ts: -------------------------------------------------------------------------------- 1 | 2 | export class HistoryStore { 3 | private history: string[]; 4 | 5 | constructor() { 6 | this.history = []; 7 | } 8 | 9 | getAll() { 10 | return this.history; 11 | } 12 | 13 | clear() { 14 | this.history = []; 15 | } 16 | 17 | add(command: string) { 18 | const history = this.history; 19 | const index = history.indexOf(command); 20 | if (index === -1) { 21 | this.history = [...history, command]; 22 | return; 23 | } 24 | this.history = [...history.slice(0, index), ...history.slice(index + 1), command]; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "extensionHost", 9 | "request": "launch", 10 | "name": "Launch Extension", 11 | "runtimeExecutable": "${execPath}", 12 | "args": [ 13 | "--extensionDevelopmentPath=${workspaceFolder}" 14 | ] 15 | }, 16 | { 17 | "type": "node", 18 | "request": "launch", 19 | "name": "Launch Program", 20 | "program": "${workspaceFolder}/extension" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /src/lib/error-message-formatter.ts: -------------------------------------------------------------------------------- 1 | 2 | const REPLACE_PAIRS = [ 3 | ['\n', '\\n'], 4 | ['*', '\\*'], 5 | ['_', '\\_'], 6 | ['[', '\\['], 7 | [']', '\\]'] 8 | ]; 9 | 10 | export class ErrorMessageFormatter { 11 | 12 | format(message: string) { 13 | const trimmedMessage = (message || '').trim(); 14 | return this.escapeText(trimmedMessage); 15 | } 16 | 17 | private escapeText(string: string) { 18 | return REPLACE_PAIRS.reduce( 19 | (s, pair) => replaceAll(s, pair[0], pair[1]), 20 | string 21 | ); 22 | } 23 | 24 | } 25 | 26 | function replaceAll(string: string, fromStr: string, toStr: string) { 27 | return string.split(fromStr).join(toStr); 28 | } 29 | -------------------------------------------------------------------------------- /src/lib/shell-settings-resolver.ts: -------------------------------------------------------------------------------- 1 | import {EXTENSION_NAME} from './const'; 2 | import resolveOsKind from './resolve-os-kind'; 3 | import {Workspace} from './adapters/workspace'; 4 | 5 | export class ShellSettingsResolver { 6 | constructor(private readonly workspaceAdapter: Workspace, 7 | private readonly platform: string) {} 8 | 9 | shellProgramme(): string { 10 | return this.workspaceAdapter.getConfig(`${EXTENSION_NAME}.shell.${this.osKind}`); 11 | } 12 | 13 | shellArgs(): string[] { 14 | return this.workspaceAdapter.getConfig(`${EXTENSION_NAME}.shellArgs.${this.osKind}`); 15 | } 16 | 17 | private get osKind() { 18 | return resolveOsKind(this.platform); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/lib/commands/run-input.ts: -------------------------------------------------------------------------------- 1 | import {ShellCommandService} from '../shell-command-service'; 2 | import {CommandReader} from '../command-reader'; 3 | import {HistoryStore} from '../history-store'; 4 | import {Workspace} from '../adapters/workspace'; 5 | import {RunCommand} from './run'; 6 | 7 | export class RunInputCommand extends RunCommand { 8 | constructor(shellCommandService: ShellCommandService, 9 | private readonly commandReader: CommandReader, 10 | historyStore: HistoryStore, 11 | workspaceAdapter: Workspace) { 12 | super(shellCommandService, historyStore, workspaceAdapter); 13 | } 14 | 15 | protected getCommandText(): Promise { 16 | return this.commandReader.read(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/lib/adapters/workspace.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | 3 | const CONFIG_PATH_DELIMITER = '.'; 4 | 5 | export class Workspace { 6 | constructor(private readonly vsWorkspace: typeof vscode.workspace) {} 7 | 8 | getConfig(configPath: string): T { 9 | const {basePath, leafName} = this.parseConfigPath(configPath); 10 | return this.vsWorkspace.getConfiguration(basePath).get(leafName) as T; 11 | } 12 | 13 | private parseConfigPath(configPath: string) { 14 | const configPathParts = configPath.split(CONFIG_PATH_DELIMITER); 15 | return { 16 | basePath: configPathParts.slice(0, -1).join(CONFIG_PATH_DELIMITER), 17 | leafName: configPathParts.slice(-1)[0] 18 | }; 19 | } 20 | 21 | get rootPath() { 22 | return this.vsWorkspace.rootPath; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/test/index.ts: -------------------------------------------------------------------------------- 1 | // 2 | // PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING 3 | // 4 | // This file is providing the test runner to use when running extension tests. 5 | // By default the test runner in use is Mocha based. 6 | // 7 | // You can provide your own test runner if you want to override it by exporting 8 | // a function run(testRoot: string, clb: (error:Error) => void) that the extension 9 | // host can call to run the tests. The test runner is expected to use console.log 10 | // to report the results back to the caller. When the tests are finished, return 11 | // a possible error to the callback or null if none. 12 | 13 | var testRunner = require('vscode/lib/testrunner'); 14 | 15 | // You can directly control Mocha options by uncommenting the following lines 16 | // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info 17 | testRunner.configure({ 18 | useColors: true // Colored output from test results 19 | }); 20 | 21 | module.exports = testRunner; 22 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "12.14.1" 4 | addons: 5 | code_climate: 6 | repo_token: 7 | secure: "EXHuvB3ZvlJBW1YhvW0AocSfIKmcT8Y4dh1YCDX6XOMEvLyYo3NyXebM3pJlkWwqIU8vDXc2Crg4Yd1bMErf62esCo2oxQXZWr6th95kbbnhQjvIG84ITia7VXYHNrZa16g/z+1ogFcPPJOwbiPTaDgnMwhlezd3Q0ip8bwM3cRWOCy+MK7DUUEQI6UWTQ9856ail+rWgkIK/jKnDFtavuXFfdWx8UXS9n0q6nnKO3UaOFysC2X+udyNIwBvg/L0J3BddPIy3MsSTFH5nabV5DWOzsx2F7UgCpAqD5kaQmzWUiPBc+mpM+xhwu6WUO2JE1jwD4lokepjiXZkHIdt/JQDFQpAIFQ1WAOZVdXHhmoo6cUNgn7xVFb6JxhE+nK0cnNfF/lRr7dB+c07jUe2QR0KwPl31DkK61DYyuj3WmoleEWlddiG2UvG3LFLoxmca1/7+XfQoMPeNZx6bmziD2C39DUV4C9PMPv4Hz9ByIr0rd9WalYv7y19HMiCrSbZh0CTrSIL3AuSd+qh3WfYv75wJJ4ZmEnA+qlnPIDQ7CQP4/6sHcOAkGhcRPeJOzBijKI9pGjAFnbPZXkGpfdQCyxrJyCzcmeFRJckpuKoxX9GuHXuShfw8Ibl++mbMKMNYGxYeddzzEoK1kMIaDF0CTaZK0HUVYuNtev9ptBrWlw=" 8 | install: 9 | - yarn install 10 | script: 11 | - yarn run lint 12 | - yarn run coverage # coverage also runs unit tests internally 13 | after_script: 14 | - codeclimate-test-reporter < coverage/lcov.info 15 | notifications: 16 | email: 17 | on_success: change 18 | on_failure: always 19 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Ryuichi Inagaki 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 | -------------------------------------------------------------------------------- /src/lib/commands/run-quick.ts: -------------------------------------------------------------------------------- 1 | import {EXTENSION_NAME} from '../const'; 2 | import {ShellCommandService} from '../shell-command-service'; 3 | import {HistoryStore} from '../history-store'; 4 | import {Workspace} from '../adapters/workspace'; 5 | import {RunCommand} from './run'; 6 | 7 | interface FavoriteCommand { 8 | id: string; 9 | command: string; 10 | } 11 | 12 | export class RunQuickCommand extends RunCommand { 13 | constructor(shellCommandService: ShellCommandService, 14 | historyStore: HistoryStore, 15 | private readonly workspace: Workspace, 16 | private readonly commandNumber: number) { 17 | super(shellCommandService, historyStore, workspace); 18 | } 19 | 20 | protected getCommandText(): Promise { 21 | const commandId = this.workspace.getConfig(`${EXTENSION_NAME}.quickCommand${this.commandNumber}`); 22 | const favoriteCommands = this.workspace.getConfig(`${EXTENSION_NAME}.favoriteCommands`); 23 | const command = favoriteCommands.find(c => c.id === commandId); 24 | return Promise.resolve(command && command.command); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/lib/shell-command-exec-context.ts: -------------------------------------------------------------------------------- 1 | import {EXTENSION_NAME} from './const'; 2 | import {Workspace} from './adapters/workspace'; 3 | import {EnvVarWrap} from './types/node'; 4 | import {dirname} from 'path'; 5 | 6 | enum CurrentDirectoryKind { 7 | CURRENT_FILE = 'currentFile', 8 | WORKSPACE_ROOT = 'workspaceRoot' 9 | } 10 | 11 | export class ShellCommandExecContext { 12 | constructor(private readonly workspaceAdapter: Workspace, 13 | private readonly process: EnvVarWrap) {} 14 | 15 | get env() { 16 | return this.process.env; 17 | } 18 | 19 | getCwd(filePath?: string) { 20 | const configPath = `${EXTENSION_NAME}.currentDirectoryKind`; 21 | const currentDirectoryKind = this.workspaceAdapter.getConfig(configPath); 22 | switch (currentDirectoryKind) { 23 | case CurrentDirectoryKind.CURRENT_FILE: 24 | return filePath ? dirname(filePath) : this.env.HOME; 25 | 26 | case CurrentDirectoryKind.WORKSPACE_ROOT: 27 | return this.workspaceAdapter.rootPath || this.env.HOME; 28 | 29 | default: 30 | throw new Error(`Unknown currentDirectoryKind: ${currentDirectoryKind}`); 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/lib/command-wrap.ts: -------------------------------------------------------------------------------- 1 | import {ShowErrorMessage} from './types/vscode'; 2 | import {Logger} from './logger'; 3 | import {WrapEditor} from './adapters/editor'; 4 | import {TextEditor as VsTextEditor} from 'vscode'; 5 | import {CommandExecutionError} from './errors/command'; 6 | import {ErrorMessageFormatter} from './error-message-formatter'; 7 | import {ExtensionCommand} from './commands/extension-command'; 8 | 9 | export class CommandWrap { 10 | private readonly errorMessageFormatter: ErrorMessageFormatter; 11 | 12 | constructor(private readonly command: ExtensionCommand, 13 | private readonly wrapEditor: WrapEditor, 14 | private readonly showErrorMessage: ShowErrorMessage, 15 | private readonly logger: Logger) { 16 | this.errorMessageFormatter = new ErrorMessageFormatter(); 17 | } 18 | 19 | async execute(editor?: VsTextEditor) { 20 | try { 21 | await this.command.execute(editor && this.wrapEditor(editor)); 22 | } catch (e) { 23 | this.handleError(e); 24 | } 25 | } 26 | 27 | async handleError(e: Error | CommandExecutionError) { 28 | this.logger.error(e.stack); 29 | 30 | const sourceMessage = e instanceof CommandExecutionError ? e.errorOutput : e.message; 31 | const errorMessage = this.errorMessageFormatter.format(sourceMessage); 32 | await this.showErrorMessage(errorMessage); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/lib/error-message-formatter.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import {ErrorMessageFormatter} from '../../lib/error-message-formatter'; 3 | 4 | describe('ErrorMessageFormatter', () => { 5 | 6 | const formatter = new ErrorMessageFormatter(); 7 | 8 | it('pass through normal text', () => { 9 | const formattedText = formatter.format('normal text'); 10 | assert.deepStrictEqual(formattedText, 'normal text'); 11 | }); 12 | 13 | it('escape newline characters to show all lines in one line', () => { 14 | const formattedText = formatter.format('MESSAGE\nCONTAINS\nNEWLINES\n'); 15 | assert.deepStrictEqual(formattedText, 'MESSAGE\\nCONTAINS\\nNEWLINES'); 16 | }); 17 | 18 | it('escape `*` character', () => { 19 | const formattedText = formatter.format('**bold**'); 20 | assert.deepStrictEqual(formattedText, '\\*\\*bold\\*\\*'); 21 | }); 22 | 23 | it('escape `_` character', () => { 24 | const formattedText = formatter.format('__italic__'); 25 | assert.deepStrictEqual(formattedText, '\\_\\_italic\\_\\_'); 26 | }); 27 | 28 | it('escape `[` character', () => { 29 | const formattedText = formatter.format('[['); 30 | assert.deepStrictEqual(formattedText, '\\[\\['); 31 | }); 32 | 33 | it('escape `]` character', () => { 34 | const formattedText = formatter.format(']]'); 35 | assert.deepStrictEqual(formattedText, '\\]\\]'); 36 | }); 37 | 38 | }); 39 | -------------------------------------------------------------------------------- /src/test/helper.ts: -------------------------------------------------------------------------------- 1 | import * as td from 'testdouble'; 2 | import * as assert from 'assert'; 3 | import {ObjectMap} from '../lib/types/collection'; 4 | 5 | export function mock(c: new (...args: any[]) => T): T { 6 | return new (td.constructor(c)); 7 | } 8 | 9 | export function mockType(params?: any): T { 10 | return Object.assign({} as T, params); 11 | } 12 | 13 | export function mockMethods(methods: string[], params?: any): T { 14 | return Object.assign(td.object(methods) as T, params); 15 | } 16 | 17 | export function mockFunction() { 18 | return td.function(); 19 | } 20 | 21 | export const verify = td.verify; 22 | export const when = td.when; 23 | export const contains = td.matchers.contains; 24 | export const any = td.matchers.anything; 25 | 26 | export function wrapVerify(invokeCallback: (...args: any[]) => void, expectedCalls: any[][] | ObjectMap) { 27 | const captors = [td.matchers.captor(), td.matchers.captor(), td.matchers.captor()]; 28 | 29 | invokeCallback(...captors.map(captor => captor.capture)); 30 | 31 | const toIndex = (key: string) => parseInt(key.replace('call', ''), 10); 32 | 33 | Object.entries(expectedCalls).forEach(([key, value]) => { 34 | const callIndex = toIndex(key); 35 | (value as any[]).forEach((expectedArg, argIndex) => { 36 | const failureMessage = `Check argument ${argIndex} of call ${callIndex}`; 37 | assert.deepStrictEqual(captors[argIndex].values![callIndex], expectedArg, failureMessage); 38 | }); 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /src/lib/process-runner.ts: -------------------------------------------------------------------------------- 1 | import {ChildProcess} from 'child_process'; 2 | import {CommandExecutionError} from './errors/command'; 3 | 4 | export class ProcessRunner { 5 | 6 | run(command: ChildProcess, inputString: string): Promise { 7 | let stdoutString = ''; 8 | let stderrString = ''; 9 | 10 | command.stdin?.write(inputString); 11 | command.stdin?.end(); 12 | 13 | command.stdout?.on('data', data => { 14 | stdoutString += data.toString(); 15 | }); 16 | command.stderr?.on('data', data => { 17 | stderrString += data.toString(); 18 | }); 19 | 20 | return new Promise((resolve, reject) => { 21 | command.on('error', err => { 22 | reject(err); 23 | }); 24 | command.on('close', code => { 25 | if (code !== 0) { 26 | // @ts-ignore `spawnargs` is not declared on ChildProcess class. Private property? 27 | const commandString = command.spawnargs.slice(-1)[0]; 28 | reject( 29 | new CommandExecutionError(`Command failed: ${commandString}\n${stderrString}`, 30 | code, 31 | commandString, 32 | stderrString.trim() 33 | ) 34 | ); 35 | } else { 36 | resolve(stdoutString); 37 | } 38 | }); 39 | }); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/lib/command-reader.ts: -------------------------------------------------------------------------------- 1 | import {HistoryStore} from './history-store'; 2 | import * as vscode from 'vscode'; 3 | 4 | export class CommandReader { 5 | constructor(private readonly historyStore: HistoryStore, 6 | private readonly vsWindow: typeof vscode.window) {} 7 | 8 | async read() { 9 | const history = this.historyStore.getAll(); 10 | if (history.length === 0) { 11 | return this.vsWindow.showInputBox({ 12 | placeHolder: 'Enter a command', 13 | prompt: 'No history available yet' 14 | }); 15 | } 16 | 17 | const pickedCommand = await this.letUserToPickCommand(history); 18 | return this.letUserToModifyCommand(pickedCommand); 19 | } 20 | 21 | private letUserToPickCommand(history: string[]): Thenable { 22 | const options = {placeHolder: 'Select a command to reuse or Cancel (Esc) to write a new command'}; 23 | return this.vsWindow.showQuickPick(history.reverse(), options); 24 | } 25 | 26 | private letUserToModifyCommand(pickedCommand?: string) { 27 | const options = this.getInputBoxOption(pickedCommand); 28 | return this.vsWindow.showInputBox(options); 29 | } 30 | 31 | private getInputBoxOption(pickedCommand?: string) { 32 | if (!pickedCommand) { 33 | return {placeHolder: 'Enter a command'}; 34 | } 35 | return { 36 | placeHolder: 'Enter a command', 37 | prompt: 'Edit the command if necessary', 38 | value: pickedCommand 39 | }; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/test/lib/history-store.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import {HistoryStore} from '../../lib/history-store'; 3 | 4 | describe('HistoryStore', () => { 5 | 6 | it('retrieves all recorded commands', () => { 7 | const historyStore = new HistoryStore(); 8 | historyStore.add('COMMAND_1'); 9 | historyStore.add('COMMAND_2'); 10 | assert.deepStrictEqual(historyStore.getAll(), ['COMMAND_1', 'COMMAND_2']); 11 | }); 12 | 13 | it('does not record the same command twice', () => { 14 | const historyStore = new HistoryStore(); 15 | historyStore.add('COMMAND_1'); 16 | historyStore.add('COMMAND_1'); 17 | assert.deepStrictEqual(historyStore.getAll(), ['COMMAND_1']); 18 | }); 19 | 20 | it('returns the last used command at the end', () => { 21 | const historyStore = new HistoryStore(); 22 | historyStore.add('COMMAND_1'); 23 | historyStore.add('COMMAND_2'); 24 | historyStore.add('COMMAND_1'); 25 | assert.deepStrictEqual(historyStore.getAll(), ['COMMAND_2', 'COMMAND_1']); 26 | }); 27 | 28 | it('returns an empty list if no commands are recorded yet', () => { 29 | const historyStore = new HistoryStore(); 30 | assert.deepStrictEqual(historyStore.getAll(), []); 31 | }); 32 | 33 | it('clears all history', () => { 34 | const historyStore = new HistoryStore(); 35 | historyStore.add('COMMAND_1'); 36 | historyStore.add('COMMAND_2'); 37 | historyStore.clear(); 38 | assert.deepStrictEqual(historyStore.getAll(), []); 39 | }); 40 | 41 | }); 42 | -------------------------------------------------------------------------------- /src/test/lib/adapters/workspace.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import {mockType} from '../../helper'; 3 | 4 | import {Workspace as WorkspaceAdapter} from '../../../lib/adapters/workspace'; 5 | import * as vscode from 'vscode'; 6 | import {ObjectMap} from '../../../lib/types/collection'; 7 | 8 | describe('WorkspaceAdapter', () => { 9 | 10 | const workspaceAdapter = new WorkspaceAdapter(fakeVscodeWorkspace()); 11 | 12 | it('gets config value of specified 2 level path', () => { 13 | assert.deepStrictEqual(workspaceAdapter.getConfig('A.B'), 'VALUE1'); 14 | }); 15 | 16 | it('gets config value of specified 4 level path', () => { 17 | assert.deepStrictEqual(workspaceAdapter.getConfig('C.D.E.F'), 'VALUE2'); 18 | }); 19 | 20 | it('returns the project root path', () => { 21 | assert.deepStrictEqual(workspaceAdapter.rootPath, 'PROJECT_ROOT_PATH'); 22 | }); 23 | 24 | function fakeVscodeWorkspace() { 25 | const config = { 26 | 'A.B': 'VALUE1', 27 | 'C.D.E.F': 'VALUE2' 28 | } as ObjectMap; 29 | return mockType({ 30 | getConfiguration: (oneAbove: any) => { 31 | switch (oneAbove) { 32 | case 'A': 33 | return {get: (name: string) => config[`A.${name}`]}; 34 | case 'C.D.E': 35 | return {get: (name: string) => config[`C.D.E.${name}`]}; 36 | default: 37 | return {get: () => {}}; 38 | } 39 | }, 40 | rootPath: 'PROJECT_ROOT_PATH' 41 | }); 42 | } 43 | 44 | }); 45 | -------------------------------------------------------------------------------- /src/test/lib/command-wrap.test.ts: -------------------------------------------------------------------------------- 1 | import {contains, mock, mockFunction, mockMethods, mockType, verify, when} from '../helper'; 2 | import {Editor, WrapEditor} from '../../lib/adapters/editor'; 3 | import {Logger} from '../../lib/logger'; 4 | import {ShowErrorMessage} from '../../lib/types/vscode'; 5 | import * as vscode from 'vscode'; 6 | import {CommandWrap} from '../../lib/command-wrap'; 7 | import {ExtensionCommand} from '../../lib/commands/extension-command'; 8 | 9 | describe('CommandWrap', () => { 10 | let logger: Logger; 11 | let showErrorMessage: ShowErrorMessage; 12 | let command: ExtensionCommand; 13 | let commandWrap: CommandWrap; 14 | 15 | const rowGoodEditor = mockType({id: 'good'}); 16 | const rowBadEditor = mockType({id: 'bad'}); 17 | 18 | const goodEditor = mock(Editor); 19 | const badEditor = mock(Editor); 20 | 21 | const wrapEditor = mockFunction() as WrapEditor; 22 | when(wrapEditor(rowGoodEditor)).thenReturn(goodEditor); 23 | when(wrapEditor(rowBadEditor)).thenReturn(badEditor); 24 | 25 | beforeEach(() => { 26 | logger = mockMethods(['error']); 27 | showErrorMessage = mockFunction() as ShowErrorMessage; 28 | 29 | command = mockMethods(['execute']); 30 | when(command.execute(badEditor)).thenThrow(new Error('UNEXPECTED_ERROR')); 31 | 32 | commandWrap = new CommandWrap(command, wrapEditor, showErrorMessage, logger); 33 | }); 34 | 35 | it('invokes wrapped command with wrapped editor', async () => { 36 | await commandWrap.execute(rowGoodEditor); 37 | 38 | verify(command.execute(goodEditor)); 39 | }); 40 | 41 | it('reports an error', async () => { 42 | await commandWrap.execute(rowBadEditor); 43 | 44 | verify(showErrorMessage(contains('UNEXPECTED\\_ERROR'))); 45 | verify(logger.error(contains('Error: UNEXPECTED_ERROR'))); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /src/lib/app-integrator.ts: -------------------------------------------------------------------------------- 1 | import {EXTENSION_NAME} from './const'; 2 | import {ExecutionContextLike} from './types/vscode'; 3 | import {CommandWrap} from './command-wrap'; 4 | 5 | interface CommandHandlerInfo { 6 | id: string; 7 | command: CommandWrap; 8 | } 9 | 10 | export class AppIntegrator { 11 | constructor(private readonly runCommand: CommandWrap, 12 | private readonly clearHistoryCommand: CommandWrap, 13 | private readonly createQuickCommand: (n: number) => CommandWrap, 14 | private readonly vscode: any) {} 15 | 16 | integrate(context: ExecutionContextLike) { 17 | this.registerCommands(context); 18 | this.registerTextEditorCommands(context); 19 | } 20 | 21 | private registerCommands(context: ExecutionContextLike) { 22 | const disposable = this.vscode.commands.registerCommand( 23 | `${EXTENSION_NAME}.clearCommandHistory`, 24 | this.clearHistoryCommand.execute, 25 | this.clearHistoryCommand 26 | ); 27 | context.subscriptions.push(disposable); 28 | } 29 | 30 | private registerTextEditorCommands(context: ExecutionContextLike): void { 31 | this.textEditorCommands.forEach(command => { 32 | const disposable = this.vscode.commands.registerTextEditorCommand( 33 | command.id, 34 | command.command.execute, 35 | command.command 36 | ); 37 | context.subscriptions.push(disposable); 38 | }); 39 | } 40 | 41 | private get textEditorCommands(): CommandHandlerInfo[] { 42 | return [ 43 | { 44 | id: `${EXTENSION_NAME}.runCommand`, 45 | command: this.runCommand 46 | }, 47 | ...[1, 2, 3, 4, 5].map(n => ({ 48 | id: `${EXTENSION_NAME}.runQuickCommand${n}`, 49 | command: this.createQuickCommand(n) 50 | })) 51 | ]; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/lib/shell-command-service.ts: -------------------------------------------------------------------------------- 1 | import {ProcessRunner} from './process-runner'; 2 | import {ShellCommandExecContext} from './shell-command-exec-context'; 3 | import {ShellSettingsResolver} from './shell-settings-resolver'; 4 | import {ChildProcess, SpawnOptions} from 'child_process'; 5 | import {Workspace} from './adapters/workspace'; 6 | import Process = NodeJS.Process; 7 | 8 | export interface SpawnWrapper { 9 | spawn: (command: string, args?: ReadonlyArray, options?: SpawnOptions) => ChildProcess; 10 | } 11 | 12 | export interface CommandParams { 13 | command: string; 14 | input: string; 15 | filePath?: string; 16 | } 17 | 18 | export class ShellCommandService { 19 | private readonly shellCommandExecContext: ShellCommandExecContext; 20 | private readonly shellSettingsResolver: ShellSettingsResolver; 21 | 22 | constructor(private readonly processRunner: ProcessRunner, 23 | workspace: Workspace, 24 | process: Process, 25 | private readonly childProcess: SpawnWrapper) { 26 | this.shellCommandExecContext = new ShellCommandExecContext(workspace, {env: process.env}); 27 | this.shellSettingsResolver = new ShellSettingsResolver(workspace, process.platform); 28 | } 29 | 30 | runCommand(params: CommandParams): Promise { 31 | const options = this.getOptions(params); 32 | const shell = this.shellSettingsResolver.shellProgramme(); 33 | const shellArgs = this.shellSettingsResolver.shellArgs(); 34 | const command = this.childProcess.spawn(shell, [...shellArgs, params.command], options); 35 | return this.processRunner.run(command, params.input); 36 | } 37 | 38 | private getOptions(params: CommandParams) { 39 | return { 40 | cwd: this.shellCommandExecContext.getCwd(params.filePath), 41 | env: { 42 | ...this.shellCommandExecContext.env, 43 | ES_SELECTED: params.input 44 | } 45 | }; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/lib/adapters/editor.ts: -------------------------------------------------------------------------------- 1 | import {Position, Range, TextEditor as VsTextEditor} from 'vscode'; 2 | 3 | export type WrapEditor = (editor: VsTextEditor, lf?: LocationFactory) => Editor; 4 | 5 | export interface LocationFactory { 6 | createPosition(line: number, character: number): Position; 7 | createRange(start: Position, end: Position): Range; 8 | } 9 | 10 | export class Editor { 11 | constructor(private readonly vsEditor: VsTextEditor, 12 | private readonly locationFactory: LocationFactory) {} 13 | 14 | get selectedTexts(): string[] { 15 | const editor = this.vsEditor; 16 | return editor.selections 17 | .map(selection => editor.document.getText(selection)); 18 | } 19 | 20 | get entireText(): string { 21 | return this.vsEditor.document.getText(); 22 | } 23 | 24 | get isTextSelected(): boolean { 25 | return this.selectedTexts.length > 1 || this.selectedTexts[0] !== ''; 26 | } 27 | 28 | get filePath(): string | undefined { 29 | const uri = this.vsEditor.document.uri; 30 | return uri.scheme === 'file' ? uri.fsPath : undefined; 31 | } 32 | 33 | replaceSelectedTextsWith(texts: string[]) { 34 | const editor = this.vsEditor; 35 | return editor.edit(editBuilder => { 36 | editor.selections.forEach((selection, index) => { 37 | editBuilder.replace(selection, texts[index]); 38 | }); 39 | }); 40 | } 41 | 42 | replaceEntireTextWith(text: string) { 43 | const editor = this.vsEditor; 44 | const document = editor.document; 45 | const lineCount = document.lineCount; 46 | const lastLine = document.lineAt(lineCount - 1); 47 | const entireRange = this.locationFactory.createRange( 48 | this.locationFactory.createPosition(0, 0), 49 | lastLine.range.end 50 | ); 51 | return editor.edit(editBuilder => { 52 | editBuilder.replace(entireRange, text); 53 | }); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/test/lib/shell-command-exec-context.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import {mockMethods, mockType, when} from '../helper'; 3 | 4 | import {ShellCommandExecContext} from '../../lib/shell-command-exec-context'; 5 | import {Workspace} from '../../lib/adapters/workspace'; 6 | 7 | describe('ShellCommandExecContext', () => { 8 | 9 | it('has environment variables', () => { 10 | const workspace = mockType(); 11 | const execContext = new ShellCommandExecContext(workspace, {env: {VAR: '..'}}); 12 | assert.deepStrictEqual(execContext.env, {VAR: '..'}); 13 | }); 14 | 15 | it('returns the directory of the current file if currentDirectoryKind is set to "currentFile"', () => { 16 | const execContext = new ShellCommandExecContext(fakeWorkspaceAdapter('currentFile'), {env: {}}); 17 | assert.deepStrictEqual(execContext.getCwd('DIR/FILE'), 'DIR'); 18 | }); 19 | 20 | it('returns user\'s home directory if currentDirectoryKind is set to "currentFile" but not available', () => { 21 | const execContext = new ShellCommandExecContext(fakeWorkspaceAdapter('currentFile'), {env: {HOME: 'USER_HOME_DIR'}}); 22 | assert.deepStrictEqual(execContext.getCwd(), 'USER_HOME_DIR'); 23 | }); 24 | 25 | it('returns project root directory if currentDirectoryKind is set to "workspaceRoot"', () => { 26 | const execContext = new ShellCommandExecContext(fakeWorkspaceAdapter('workspaceRoot', 'PROJECT_ROOT_PATH'), {env: {}}); 27 | assert.deepStrictEqual(execContext.getCwd(), 'PROJECT_ROOT_PATH'); 28 | }); 29 | 30 | it('returns user\'s home directory if currentDirectoryKind is set to "workspaceRoot" but not available', () => { 31 | const execContext = new ShellCommandExecContext(fakeWorkspaceAdapter('workspaceRoot'), {env: {HOME: 'USER_HOME_DIR'}}); 32 | assert.deepStrictEqual(execContext.getCwd(), 'USER_HOME_DIR'); 33 | }); 34 | 35 | function fakeWorkspaceAdapter(currentDirectoryKind: string, rootPath?: string) { 36 | const workspace = mockMethods(['getConfig'], {rootPath}); 37 | when(workspace.getConfig('editWithShell.currentDirectoryKind')).thenReturn(currentDirectoryKind); 38 | return workspace; 39 | } 40 | 41 | }); 42 | -------------------------------------------------------------------------------- /src/lib/commands/run.ts: -------------------------------------------------------------------------------- 1 | import {EXTENSION_NAME} from '../const'; 2 | import {ShellCommandService} from '../shell-command-service'; 3 | import {HistoryStore} from '../history-store'; 4 | import {Workspace} from '../adapters/workspace'; 5 | import {Editor} from '../adapters/editor'; 6 | import {ExtensionCommand} from './extension-command'; 7 | 8 | export abstract class RunCommand implements ExtensionCommand { 9 | constructor(private readonly shellCommandService: ShellCommandService, 10 | private readonly historyStore: HistoryStore, 11 | private readonly workspaceAdapter: Workspace) {} 12 | 13 | protected abstract getCommandText(): Promise; 14 | 15 | async execute(wrappedEditor: Editor) { 16 | const command = await this.getCommandText(); 17 | if (!command) return; 18 | 19 | this.historyStore.add(command); 20 | 21 | if (this.shouldPassEntireText(wrappedEditor)) { 22 | await this.processEntireText(command, wrappedEditor); 23 | } else { 24 | await this.processSelectedTexts(command, wrappedEditor); 25 | } 26 | } 27 | 28 | private async processSelectedTexts(command: string, wrappedEditor: Editor): Promise { 29 | const filePath = wrappedEditor.filePath; 30 | const promiseOfCommandOutputs = wrappedEditor.selectedTexts 31 | .map(input => this.shellCommandService.runCommand({command, input, filePath})); 32 | const commandOutputs = await Promise.all(promiseOfCommandOutputs); 33 | await wrappedEditor.replaceSelectedTextsWith(commandOutputs); 34 | } 35 | 36 | private async processEntireText(command: string, wrappedEditor: Editor): Promise { 37 | const commandOutput = await this.shellCommandService.runCommand({ 38 | command, 39 | input: wrappedEditor.entireText, 40 | filePath: wrappedEditor.filePath 41 | }); 42 | await wrappedEditor.replaceEntireTextWith(commandOutput); 43 | } 44 | 45 | private shouldPassEntireText(wrappedEditor: Editor): boolean { 46 | const processEntireText = this.workspaceAdapter.getConfig(`${EXTENSION_NAME}.processEntireTextIfNoneSelected`); 47 | return !wrappedEditor.isTextSelected && processEntireText; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to "Edit with Shell Command" extension will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 6 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). 7 | 8 | ## [1.3.0] - 2021-05-26 9 | ### Added 10 | - Made a selected text also available as an environment variable, `ES_SELECTED`. 11 | [#18](https://github.com/ryu1kn/vscode-edit-with-shell/issues/18) 12 | 13 | ## [1.2.0] - 2019-01-17 14 | ### Added 15 | - Support multi cursors. [#11](https://github.com/ryu1kn/vscode-edit-with-shell/issues/11) 16 | 17 | ## [1.1.0] - 2018-12-26 18 | ### Added 19 | - Introduced **Quick Command**. You can quickly run a pre-registered shell command with a keyboard shortcut. [#7](https://github.com/ryu1kn/vscode-edit-with-shell/issues/7) 20 | 21 | ## [1.0.1] - 2018-09-12 22 | ### Fixed 23 | - Fixed the problem that entire text is passed to a command when `editWithShell.processEntireTextIfNoneSelected` is set to `true`. 24 | [#6](https://github.com/ryu1kn/vscode-edit-with-shell/issues/6) 25 | 26 | ## [1.0.0] - 2018-05-12 27 | ### Added 28 | - Introduced a configuration to pass the entire text to the shell command if no text is selected. [#5](https://github.com/ryu1kn/vscode-edit-with-shell/issues/5) 29 | 30 | ## [0.4.0] - 2018-04-02 31 | ### Added 32 | - Introduced a command to clear command history. [#4](https://github.com/ryu1kn/vscode-edit-with-shell/issues/4) 33 | 34 | ## [0.3.0] - 2018-02-13 35 | ### Added 36 | - Support non-default shells. `bash` on Windows is now possible. [#1](https://github.com/ryu1kn/vscode-edit-with-shell/issues/1) 37 | 38 | ## [0.2.2] - 2018-02-09 39 | ### Fixed 40 | - Fixed the problem that error messages were not shown on shell command failure if they contain certain character sequences. [#2](https://github.com/ryu1kn/vscode-edit-with-shell/issues/2) 41 | 42 | ## [0.2.1] - 2017-09-14 43 | ### Fixed 44 | - Fixed the link to the gif animation 45 | 46 | ## [0.2.0] - 2016-12-07 47 | ### Added 48 | - Introduced a configuration for choosing the current directory of shell command execution 49 | 50 | ## [0.1.0] - 2016-12-04 51 | ### Added 52 | - Support command history. Edit and reuse past commands 53 | 54 | ## [0.0.1] - 2016-09-29 55 | ### Added 56 | - Initial release of the extension 57 | -------------------------------------------------------------------------------- /src/test/lib/command-reader.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import {any, mockMethods, mockType, verify, when} from '../helper'; 3 | 4 | import {CommandReader} from '../../lib/command-reader'; 5 | import * as vscode from 'vscode'; 6 | import {HistoryStore} from '../../lib/history-store'; 7 | 8 | describe('CommandReader', () => { 9 | 10 | it('allows user to pick and modify a past command. Commands shown last one first', async () => { 11 | const historyStore = mockType({getAll: () => ['COMMAND_1', 'COMMAND_2']}); 12 | const vscodeWindow = mockMethods(['showInputBox', 'showQuickPick']); 13 | when(vscodeWindow.showQuickPick( 14 | ['COMMAND_2', 'COMMAND_1'], 15 | {placeHolder: 'Select a command to reuse or Cancel (Esc) to write a new command'} 16 | )).thenResolve('COMMAND_1'); 17 | when(vscodeWindow.showInputBox({ 18 | placeHolder: 'Enter a command', 19 | prompt: 'Edit the command if necessary', 20 | value: 'COMMAND_1' 21 | })).thenResolve('COMMAND_FINAL'); 22 | const reader = new CommandReader(historyStore, vscodeWindow); 23 | const command = await reader.read(); 24 | 25 | assert.deepStrictEqual(command, 'COMMAND_FINAL'); 26 | }); 27 | 28 | it('shows inputBox right away if there is no commands recorded in the history', async () => { 29 | const vscodeWindow = mockMethods(['showInputBox', 'showQuickPick']); 30 | when(vscodeWindow.showInputBox({ 31 | placeHolder: 'Enter a command', 32 | prompt: 'No history available yet' 33 | })).thenResolve('COMMAND'); 34 | const historyStore = mockType({getAll: () => []}); 35 | const reader = new CommandReader(historyStore, vscodeWindow); 36 | const command = await reader.read(); 37 | 38 | assert.deepStrictEqual(command, 'COMMAND'); 39 | verify(vscodeWindow.showQuickPick(any()), {times: 0, ignoreExtraArgs: true}); 40 | }); 41 | 42 | it('shows inputBox if history command picker is dismissed', async () => { 43 | const vscodeWindow = mockMethods(['showInputBox'], { 44 | showQuickPick: () => Promise.resolve() 45 | }); 46 | when(vscodeWindow.showInputBox({placeHolder: 'Enter a command'})).thenResolve('COMMAND'); 47 | 48 | const historyStore = mockType({getAll: () => ['COMMAND_1', 'COMMAND_2']}); 49 | const reader = new CommandReader(historyStore, vscodeWindow); 50 | const command = await reader.read(); 51 | 52 | assert.deepStrictEqual(command, 'COMMAND'); 53 | }); 54 | 55 | }); 56 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '45 16 * * 5' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 37 | # Learn more: 38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v2 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v1 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see below) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v1 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v1 72 | -------------------------------------------------------------------------------- /src/lib/app-integrator-factory.ts: -------------------------------------------------------------------------------- 1 | import {AppIntegrator} from './app-integrator'; 2 | import {Editor} from './adapters/editor'; 3 | import {ShellCommandService} from './shell-command-service'; 4 | import {CommandReader} from './command-reader'; 5 | import {HistoryStore} from './history-store'; 6 | import {ProcessRunner} from './process-runner'; 7 | import {RunInputCommand} from './commands/run-input'; 8 | import {ClearHistoryCommand} from './commands/clear-history'; 9 | import {Workspace as WorkspaceAdapter} from './adapters/workspace'; 10 | import * as vscode from 'vscode'; 11 | import {Position, Range, TextEditor as VsTextEditor} from 'vscode'; 12 | import {ExtensionCommand} from './commands/extension-command'; 13 | import {CommandWrap} from './command-wrap'; 14 | import {RunQuickCommand} from './commands/run-quick'; 15 | 16 | const childProcess = require('child_process'); 17 | 18 | export class AppIntegratorFactory { 19 | private readonly cache: { 20 | workspaceAdapter?: WorkspaceAdapter; 21 | historyStore?: HistoryStore; 22 | }; 23 | 24 | constructor() { 25 | this.cache = Object.create(null); 26 | } 27 | 28 | create() { 29 | return new AppIntegrator(this.runCommand, this.clearHistoryCommand, this.createQuickCommand, vscode); 30 | } 31 | 32 | private get runCommand() { 33 | return this.wrapCommand(new RunInputCommand( 34 | this.shellCommandService, 35 | new CommandReader(this.historyStore, vscode.window), 36 | this.historyStore, 37 | this.workspaceAdapter 38 | )); 39 | } 40 | 41 | private get createQuickCommand() { 42 | return (commandNumber: number) => this.wrapCommand(new RunQuickCommand( 43 | this.shellCommandService, 44 | this.historyStore, 45 | this.workspaceAdapter, 46 | commandNumber 47 | )); 48 | } 49 | 50 | private get clearHistoryCommand() { 51 | return this.wrapCommand(new ClearHistoryCommand(this.historyStore)); 52 | } 53 | 54 | private wrapCommand(command: ExtensionCommand) { 55 | return new CommandWrap( 56 | command, 57 | (editor: VsTextEditor) => new Editor(editor, this.locationFactory), 58 | (message: string) => vscode.window.showErrorMessage(message), 59 | console 60 | ); 61 | } 62 | 63 | private get historyStore() { 64 | this.cache.historyStore = this.cache.historyStore || new HistoryStore(); 65 | return this.cache.historyStore; 66 | } 67 | 68 | private get shellCommandService() { 69 | return new ShellCommandService( 70 | new ProcessRunner(), 71 | this.workspaceAdapter, 72 | process, 73 | childProcess 74 | ); 75 | } 76 | 77 | private get locationFactory() { 78 | return { 79 | createPosition: (line: number, character: number) => new Position(line, character), 80 | createRange: (p1: Position, p2: Position) => new Range(p1, p2) 81 | }; 82 | } 83 | 84 | private get workspaceAdapter() { 85 | this.cache.workspaceAdapter = this.cache.workspaceAdapter || 86 | new WorkspaceAdapter(vscode.workspace); 87 | return this.cache.workspaceAdapter; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/test/lib/shell-settings-resolver.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import {mock, when} from '../helper'; 3 | 4 | import {ShellSettingsResolver} from '../../lib/shell-settings-resolver'; 5 | import {Workspace} from '../../lib/adapters/workspace'; 6 | 7 | describe('ShellSettingsResolver', () => { 8 | 9 | const workspaceAdapter = mock(Workspace); 10 | when(workspaceAdapter.getConfig('editWithShell.shell.linux')).thenReturn('linux_SHELL_PATH'); 11 | when(workspaceAdapter.getConfig('editWithShell.shell.osx')).thenReturn('osx_SHELL_PATH'); 12 | when(workspaceAdapter.getConfig('editWithShell.shell.windows')).thenReturn('windows_SHELL_PATH'); 13 | when(workspaceAdapter.getConfig('editWithShell.shellArgs.linux')).thenReturn(['LINUX_SHELL_ARGS']); 14 | when(workspaceAdapter.getConfig('editWithShell.shellArgs.osx')).thenReturn(['MACOS_SHELL_ARGS']); 15 | when(workspaceAdapter.getConfig('editWithShell.shellArgs.windows')).thenReturn(['WINDOWS_SHELL_ARGS']); 16 | 17 | it('it returns Linux shell args user specified in their config when run on Linux', () => { 18 | const shellArgsRetriever = createShellSettingsResolver('linux'); 19 | assert.deepStrictEqual(shellArgsRetriever.shellArgs(), ['LINUX_SHELL_ARGS']); 20 | }); 21 | 22 | it('it returns macOS shell args user specified in their config when run on macOS', () => { 23 | const shellArgsRetriever = createShellSettingsResolver('darwin'); 24 | assert.deepStrictEqual(shellArgsRetriever.shellArgs(), ['MACOS_SHELL_ARGS']); 25 | }); 26 | 27 | it('it returns Windows shell args user specified in their config when run on Windows', () => { 28 | const shellArgsRetriever = createShellSettingsResolver('win32'); 29 | assert.deepStrictEqual(shellArgsRetriever.shellArgs(), ['WINDOWS_SHELL_ARGS']); 30 | }); 31 | 32 | it('it returns Linux shell args user specified in their config when run on other OSs', () => { 33 | const shellArgsRetriever = createShellSettingsResolver('unknown_platform'); 34 | assert.deepStrictEqual(shellArgsRetriever.shellArgs(), ['LINUX_SHELL_ARGS']); 35 | }); 36 | 37 | it('it returns Linux shell path user specified in their config when run on Linux', () => { 38 | const shellProgrammeResolver = createShellSettingsResolver('linux'); 39 | assert.deepStrictEqual(shellProgrammeResolver.shellProgramme(), 'linux_SHELL_PATH'); 40 | }); 41 | 42 | it('it returns macOS shell path user specified in their config when run on macOS', () => { 43 | const shellProgrammeResolver = createShellSettingsResolver('darwin'); 44 | assert.deepStrictEqual(shellProgrammeResolver.shellProgramme(), 'osx_SHELL_PATH'); 45 | }); 46 | 47 | it('it returns Windows shell path user specified in their config when run on Windows', () => { 48 | const shellProgrammeResolver = createShellSettingsResolver('win32'); 49 | assert.deepStrictEqual(shellProgrammeResolver.shellProgramme(), 'windows_SHELL_PATH'); 50 | }); 51 | 52 | it('it returns Linux shell path user specified in their config when run on other OSs', () => { 53 | const shellProgrammeResolver = createShellSettingsResolver('unknown_platform'); 54 | assert.deepStrictEqual(shellProgrammeResolver.shellProgramme(), 'linux_SHELL_PATH'); 55 | }); 56 | 57 | function createShellSettingsResolver(platform: string) { 58 | return new ShellSettingsResolver(workspaceAdapter, platform); 59 | } 60 | }); 61 | -------------------------------------------------------------------------------- /src/test/lib/adapters/editor.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import {mockMethods, mockType, verify} from '../../helper'; 3 | 4 | import {Editor} from '../../../lib/adapters/editor'; 5 | import * as vscode from 'vscode'; 6 | import {Position, Range} from 'vscode'; 7 | 8 | describe('Editor', () => { 9 | 10 | const locationFactory = {createPosition, createRange}; 11 | 12 | it('holds a selected text', () => { 13 | const vsEditor = fakeEditor({selectedTexts: ['SELECTED_TEXT']}); 14 | const editor = new Editor(vsEditor, locationFactory); 15 | assert.deepStrictEqual(editor.selectedTexts, ['SELECTED_TEXT']); 16 | }); 17 | 18 | it('holds the entire text', () => { 19 | const vsEditor = fakeEditor({}); 20 | const editor = new Editor(vsEditor, locationFactory); 21 | assert.deepStrictEqual(editor.entireText, 'FOO\n\nBAR'); 22 | }); 23 | 24 | it('holds a file path', () => { 25 | const vsEditor = fakeEditor({uriScheme: 'file'}); 26 | const editor = new Editor(vsEditor, locationFactory); 27 | assert.deepStrictEqual(editor.filePath, 'FILE_PATH'); 28 | }); 29 | 30 | it('does not hold a file path if editor content has never been saved', () => { 31 | const vsEditor = fakeEditor({}); 32 | const editor = new Editor(vsEditor, locationFactory); 33 | assert.strictEqual(typeof editor.filePath, 'undefined'); 34 | }); 35 | 36 | it('replaces the selected text with given text', async () => { 37 | const editBuilder = mockMethods(['replace']); 38 | const vsEditor = fakeEditor({selectedTexts: ['SELECTED_TEXT'], editBuilder}); 39 | const editor = new Editor(vsEditor, locationFactory); 40 | 41 | await editor.replaceSelectedTextsWith(['NEW_TEXT']); 42 | 43 | verify(editBuilder.replace(vsEditor.selections[0], 'NEW_TEXT')); 44 | }); 45 | 46 | it('replaces the entire text with the command output', async () => { 47 | const editBuilder = mockMethods(['replace']); 48 | const vsEditor = fakeEditor({editBuilder}); 49 | const locationFactory = {createPosition, createRange}; 50 | const editor = new Editor(vsEditor, locationFactory); 51 | 52 | await editor.replaceEntireTextWith('NEW_TEXT'); 53 | 54 | verify(editBuilder.replace(createRange(createPosition(0, 0), createPosition(2, 24)), 'NEW_TEXT')); 55 | }); 56 | 57 | function fakeEditor(params: any) { 58 | const selectedTexts = params.selectedTexts || []; 59 | const entireText = `FOO\n${selectedTexts[0] || ''}\nBAR`; 60 | const uriScheme = params.uriScheme; 61 | return mockType({ 62 | selections: selectedTexts.map((text: string) => ({ 63 | text, 64 | isEmpty: !text 65 | })), 66 | document: { 67 | getText: () => selectedTexts[0] || entireText, 68 | uri: { 69 | scheme: uriScheme || 'untitled', 70 | fsPath: 'FILE_PATH' 71 | }, 72 | lineCount: entireText.split('\n').length, 73 | lineAt: (lineIndex: number) => ({ 74 | range: createRange(createPosition(lineIndex, 0), createPosition(lineIndex, 24)) 75 | }) 76 | }, 77 | edit: function (callback: any) { 78 | callback(params.editBuilder || {replace: () => {}}); 79 | return Promise.resolve(true); 80 | } 81 | }); 82 | } 83 | 84 | function createPosition(line: number, column: number) { 85 | return mockType({line, column}); 86 | } 87 | 88 | function createRange(position1: Position, position2: Position) { 89 | return mockType({ 90 | start: position1, 91 | end: position2 92 | }); 93 | } 94 | 95 | }); 96 | -------------------------------------------------------------------------------- /src/test/lib/shell-command-service.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import {any, contains, mock, mockMethods, mockType, when} from '../helper'; 3 | import {ShellCommandService, SpawnWrapper} from '../../lib/shell-command-service'; 4 | import {ProcessRunner} from '../../lib/process-runner'; 5 | import {ChildProcess} from 'child_process'; 6 | import {Workspace} from '../../lib/adapters/workspace'; 7 | import {EXTENSION_NAME} from '../../lib/const'; 8 | import Process = NodeJS.Process; 9 | 10 | describe('ShellCommandService', () => { 11 | 12 | let childProcess: SpawnWrapper; 13 | let processRunner: ProcessRunner; 14 | let service: ShellCommandService; 15 | const currentPath = 'CURRENT_DIR/CURRENT_FILE'; 16 | const platform = 'linux'; 17 | 18 | beforeEach(() => { 19 | const process = mockType(); 20 | 21 | childProcess = mockMethods(['spawn']); 22 | when(childProcess.spawn('SHELL_PATH', ['SHELL_ARG', 'COMMAND_STRING'], any())).thenReturn(process); 23 | when(childProcess.spawn('SHELL_PATH', ['SHELL_ARG', 'COMMAND_TEST_WITH_ENVVARS'], contains({env: {SOME_ENV_VAR: '...'}}))).thenReturn(process); 24 | when(childProcess.spawn('SHELL_PATH', ['SHELL_ARG', 'COMMAND_TEST_WITH_EXPOSE_INPUT_AS_ENVVAR'], contains({env: {ES_SELECTED: 'SELECTED_TEXT'}}))).thenReturn(process); 25 | when(childProcess.spawn('SHELL_PATH', ['SHELL_ARG', 'COMMAND_TEST_WITH_EXEC_DIR'], contains({cwd: 'CURRENT_DIR'}))).thenReturn(process); 26 | 27 | processRunner = mock(ProcessRunner); 28 | when(processRunner.run(process, '')).thenResolve('COMMAND_OUTPUT'); 29 | when(processRunner.run(process, 'SELECTED_TEXT')).thenResolve('COMMAND_OUTPUT_TEST_WITH_INPUT'); 30 | when(processRunner.run(process, 'CAUSE_ERROR_INPUT')).thenReject(new Error('UNEXPECTED_ERROR')); 31 | 32 | const workspace = mock(Workspace); 33 | when(workspace.getConfig(`${EXTENSION_NAME}.shell.${platform}`)).thenReturn('SHELL_PATH'); 34 | when(workspace.getConfig(`${EXTENSION_NAME}.shellArgs.${platform}`)).thenReturn(['SHELL_ARG']); 35 | when(workspace.getConfig(`${EXTENSION_NAME}.currentDirectoryKind`)).thenReturn('currentFile'); 36 | 37 | service = new ShellCommandService( 38 | processRunner, 39 | workspace, 40 | mockType({ 41 | platform, 42 | env: {SOME_ENV_VAR: '...'} 43 | }), 44 | childProcess, 45 | ); 46 | }); 47 | 48 | it('runs a given command on shell', async () => { 49 | const params = {command: 'COMMAND_STRING', input: ''}; 50 | const output = await service.runCommand(params); 51 | 52 | assert.deepStrictEqual(output, 'COMMAND_OUTPUT'); 53 | }); 54 | 55 | it('passes selected text in the editor to the command', async () => { 56 | const params = { 57 | command: 'COMMAND_STRING', 58 | input: 'SELECTED_TEXT' 59 | }; 60 | const output = await service.runCommand(params); 61 | 62 | assert.deepStrictEqual(output, 'COMMAND_OUTPUT_TEST_WITH_INPUT'); 63 | }); 64 | 65 | it('inherits environment variables on executing a command', async () => { 66 | const params = {command: 'COMMAND_TEST_WITH_ENVVARS', input: ''}; 67 | const output = await service.runCommand(params); 68 | 69 | assert.deepStrictEqual(output, 'COMMAND_OUTPUT'); 70 | }); 71 | 72 | it('also exposes a selected text as an environment variable', async () => { 73 | const params = { 74 | command: 'COMMAND_TEST_WITH_EXPOSE_INPUT_AS_ENVVAR', 75 | input: 'SELECTED_TEXT' 76 | }; 77 | const output = await service.runCommand(params); 78 | 79 | assert.deepStrictEqual(output, 'COMMAND_OUTPUT_TEST_WITH_INPUT'); 80 | }); 81 | 82 | it('executes a command on a specific directory', async () => { 83 | const params = { 84 | command: 'COMMAND_TEST_WITH_EXEC_DIR', 85 | input: '', 86 | filePath: currentPath 87 | }; 88 | const output = await service.runCommand(params); 89 | 90 | assert.deepStrictEqual(output, 'COMMAND_OUTPUT'); 91 | }); 92 | 93 | it('throws an error if command failed', async () => { 94 | const params = { 95 | command: 'COMMAND_STRING', 96 | input: 'CAUSE_ERROR_INPUT' 97 | }; 98 | 99 | try { 100 | await service.runCommand(params); 101 | throw new Error('Should not have been called'); 102 | } catch (e) { 103 | assert.deepStrictEqual(e.message, 'UNEXPECTED_ERROR'); 104 | } 105 | }); 106 | }); 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/ryu1kn/vscode-edit-with-shell.svg?branch=master)](https://travis-ci.org/ryu1kn/vscode-edit-with-shell) [![Code Climate](https://codeclimate.com/github/ryu1kn/vscode-edit-with-shell/badges/gpa.svg)](https://codeclimate.com/github/ryu1kn/vscode-edit-with-shell) 2 | 3 | # Edit with Shell Command 4 | 5 | Leverage your favourite shell commands to edit text. 6 | 7 | ## Features 8 | 9 | * Edit the selected text by piping it through shell commands. 10 | The same text is also available as an environment variable, `ES_SELECTED`. 11 | * Insert the output of shell commands at the cursor position. 12 | * Records command history: you can edit and reuse past commands. 13 | * Use the shell you like. For example, if you have Bash on Windows, you can specify Bash as your shell for this extension. 14 | * Register up to 5 quick commands that can be invoked by keyboard shortcuts. 15 | * Support multi cursors. 16 | 17 | ![Edit with Shell Command](https://raw.githubusercontent.com/ryu1kn/vscode-edit-with-shell/master/images/animations/public.gif) 18 | 19 | ![Insert command output](https://raw.githubusercontent.com/ryu1kn/vscode-edit-with-shell/master/images/animations/insert-command-output.gif) 20 | 21 | ![Edit and reuse past commands](https://raw.githubusercontent.com/ryu1kn/vscode-edit-with-shell/master/images/animations/edit-and-run-command-history.gif) 22 | 23 | ## Request Features or Report Bugs 24 | 25 | Feature requests and bug reports are very welcome: https://github.com/ryu1kn/vscode-edit-with-shell/issues 26 | 27 | A couple of requests from me when you raise an github issue. 28 | 29 | * **Requesting a feature:** Please try to provide the context of why you want the feature. Such as, in what situation the feature could help you and how, or how the lack of the feature is causing an inconvenience to you. I can't think of introducing it until I understand how it helps you 🙂 30 | * **Reporting a bug:** Please include environment information (OS name/version, the editor version). Also consider providing screenshots (or even videos) where appropriate. They are often very very helpful! 31 | 32 | ## Commands 33 | 34 | * `EditWithShell: Run command` (**Command ID:** `editWithShell.runCommand`) 35 | 36 | Show command history and let you select, modify & run a command 37 | 38 | * `EditWithShell: Clear Command History` (**Command ID:** `editWithShell.clearCommandHistory`) 39 | 40 | Clear command history 41 | 42 | * `EditWithShell: Run quick command 1` (**Command ID:** `editWithShell.runQuickCommand1`) 43 | 44 | Run quick command 1. **You have quick commands up to 5**, i.e. `editWithShell.runQuickCommand5` 45 | 46 | ## Configurations 47 | 48 | * `editWithShell.currentDirectoryKind` (default: `"currentFile"`) 49 | 50 | Current directory for shell commands. If the target directory is not available, HOME directory will be used. Possible values: `currentFile` or `workspaceRoot` 51 | 52 | * `editWithShell.processEntireTextIfNoneSelected` (default: `false`) 53 | 54 | Pipe the entire text to the shell command if no text is selected 55 | 56 | * `editWithShell.favoriteCommands` (default: `[]`) 57 | 58 | List of commands that can be activated by quick commands. Each element must have a command ID and command. e.g: 59 | 60 | ``` 61 | "editWithShell.favoriteCommands": [ 62 | { 63 | "id": "extract-email-and-sort-on-address-book", 64 | "command": "cut -d, -f3 | sort" 65 | }, 66 | { 67 | "id": "insert-melbourne-time", 68 | "command": "TZ=Australia/Melbourne date '+%Y-%m-%dT%H:%M:%S'" 69 | }, 70 | ... 71 | ] 72 | ``` 73 | 74 | * `editWithShell.quickCommand1` (default: `""`) 75 | 76 | ID of a favorite command triggered with quick command 1. e.g. `"insert-melbourne-time"` of `favoriteCommands` config value example. 77 | 78 | **You have quick commands up to 5**, i.e. `editWithShell.quickCommand5`. 79 | 80 | * `editWithShell.shell.linux` (default: `"/bin/sh"`) 81 | 82 | The path of the shell that this extension uses on Linux 83 | 84 | * `editWithShell.shellArgs.linux` (default: `["-c"]`) 85 | 86 | Arguments to the shell to be used on Linux 87 | 88 | * `editWithShell.shell.osx` (default: `"/bin/sh"`) 89 | 90 | The path of the shell that this extension uses on macOS 91 | 92 | * `editWithShell.shellArgs.osx` (default: `["-c"]`) 93 | 94 | Arguments to the shell to be used on macOS 95 | 96 | * `editWithShell.shell.windows` (default: `"cmd.exe"`) 97 | 98 | The path of the shell that this extension uses on Windows 99 | 100 | * For PowerShell, you may set this to `"pwsh"` 101 | * For Bash on WSL (Windows Subsystem for Linux), you may set this to `"wsl"` 102 | 103 | * `editWithShell.shellArgs.windows` (default: `["/d", "/s", "/c"]`) 104 | 105 | Arguments to the shell to be used on Winows 106 | 107 | * For PowerShell, you may set this to `["-NoLogo", "-NoProfile", "-Command"]` 108 | * For Bash on WSL (Windows Subsystem for Linux), you may set this to `["bash", "-c"]` 109 | 110 | ## Keyboard Shortcuts 111 | 112 | You can quickly open a command input box by registering the extension command to your keyboard shortcut settings. For example: 113 | 114 | ``` 115 | { "key": "ctrl+r ctrl+r", "command": "editWithShell.runCommand", 116 | "when": "editorTextFocus && !editorReadonly" }, 117 | { "key": "ctrl+r ctrl+1", "command": "editWithShell.runQuickCommand1", 118 | "when": "editorTextFocus && !editorReadonly" }, 119 | ``` 120 | 121 | ## Changelog 122 | 123 | * https://github.com/ryu1kn/vscode-edit-with-shell/blob/master/CHANGELOG.md 124 | -------------------------------------------------------------------------------- /src/test/lib/commands/run-input.test.ts: -------------------------------------------------------------------------------- 1 | import {RunInputCommand} from '../../../lib/commands/run-input'; 2 | import {Workspace} from '../../../lib/adapters/workspace'; 3 | import {Editor} from '../../../lib/adapters/editor'; 4 | import {ShellCommandService} from '../../../lib/shell-command-service'; 5 | import {HistoryStore} from '../../../lib/history-store'; 6 | import {any, mock, mockMethods, mockType, verify, when} from '../../helper'; 7 | import {CommandReader} from '../../../lib/command-reader'; 8 | 9 | describe('RunInputCommand', () => { 10 | 11 | describe('When command is specified and "processEntireTextIfNoneSelected" is set to "false"', () => { 12 | const commandReader = mockType({read: () => Promise.resolve('COMMAND_STRING')}); 13 | const workspaceAdapter = mockType({ 14 | getConfig: (key: string) => key === 'editWithShell.processEntireTextIfNoneSelected' && false 15 | }); 16 | 17 | let shellCommandService: ShellCommandService; 18 | let historyStore: HistoryStore; 19 | let command: RunInputCommand; 20 | 21 | beforeEach(() => { 22 | shellCommandService = mock(ShellCommandService); 23 | when(shellCommandService.runCommand({ 24 | command: 'COMMAND_STRING', 25 | input: 'SELECTED_TEXT', 26 | filePath: 'FILE_NAME' 27 | })).thenResolve('COMMAND_OUTPUT_1'); 28 | when(shellCommandService.runCommand({ 29 | command: 'COMMAND_STRING', 30 | input: '', 31 | filePath: 'FILE_NAME' 32 | })).thenResolve('COMMAND_OUTPUT_2'); 33 | 34 | historyStore = mock(HistoryStore); 35 | command = new RunInputCommand(shellCommandService, commandReader, historyStore, workspaceAdapter); 36 | }); 37 | 38 | it('runs command with selected text and add commands to the history', async () => { 39 | const editor = mockMethods(['replaceSelectedTextsWith'], { 40 | isTextSelected: true, 41 | selectedTexts: ['SELECTED_TEXT'], 42 | entireText: 'ENTIRE_TEXT', 43 | filePath: 'FILE_NAME' 44 | }); 45 | 46 | await command.execute(editor); 47 | 48 | verify(editor.replaceSelectedTextsWith(['COMMAND_OUTPUT_1'])); 49 | verify(historyStore.add('COMMAND_STRING')); 50 | }); 51 | 52 | it('runs command with no input text', async () => { 53 | const editor = mockMethods(['replaceSelectedTextsWith'], { 54 | isTextSelected: false, 55 | selectedTexts: [''], 56 | entireText: 'ENTIRE_TEXT', 57 | filePath: 'FILE_NAME' 58 | }); 59 | 60 | await command.execute(editor); 61 | 62 | verify(editor.replaceSelectedTextsWith(['COMMAND_OUTPUT_2'])); 63 | }); 64 | }); 65 | 66 | describe('When command is specified and "processEntireTextIfNoneSelected" is set to "true"', () => { 67 | const commandReader = mockType({read: () => Promise.resolve('COMMAND_STRING')}); 68 | const workspaceAdapter = mockType({ 69 | getConfig: (key: string) => key === 'editWithShell.processEntireTextIfNoneSelected' 70 | }); 71 | 72 | let shellCommandService: ShellCommandService; 73 | let historyStore: HistoryStore; 74 | let command: RunInputCommand; 75 | 76 | beforeEach(() => { 77 | shellCommandService = mock(ShellCommandService); 78 | when(shellCommandService.runCommand({ 79 | command: 'COMMAND_STRING', 80 | input: 'SELECTED_TEXT', 81 | filePath: 'FILE_NAME' 82 | })).thenResolve('COMMAND_OUTPUT_1'); 83 | when(shellCommandService.runCommand({ 84 | command: 'COMMAND_STRING', 85 | input: 'ENTIRE_TEXT', 86 | filePath: 'FILE_NAME' 87 | })).thenResolve('COMMAND_OUTPUT_2'); 88 | 89 | historyStore = mock(HistoryStore); 90 | command = new RunInputCommand(shellCommandService, commandReader, historyStore, workspaceAdapter); 91 | }); 92 | 93 | it('runs command with selected text', async () => { 94 | const editor = mockMethods(['replaceSelectedTextsWith'], { 95 | isTextSelected: true, 96 | selectedTexts: ['SELECTED_TEXT'], 97 | entireText: 'ENTIRE_TEXT', 98 | filePath: 'FILE_NAME' 99 | }); 100 | 101 | await command.execute(editor); 102 | 103 | verify(editor.replaceSelectedTextsWith(['COMMAND_OUTPUT_1'])); 104 | }); 105 | 106 | it('runs command with entire text', async () => { 107 | const editor = mockMethods(['replaceEntireTextWith'], { 108 | isTextSelected: false, 109 | selectedTexts: [''], 110 | entireText: 'ENTIRE_TEXT', 111 | filePath: 'FILE_NAME' 112 | }); 113 | 114 | await command.execute(editor); 115 | 116 | verify(editor.replaceEntireTextWith('COMMAND_OUTPUT_2')); 117 | }); 118 | }); 119 | 120 | describe('When command is NOT specified', () => { 121 | 122 | it('does not try to run a command', async () => { 123 | const historyStore = mock(HistoryStore); 124 | const shellCommandService = mock(ShellCommandService); 125 | const editor = mock(Editor); 126 | const command = new RunInputCommand( 127 | shellCommandService, 128 | mockType({read: () => Promise.resolve()}), 129 | historyStore, 130 | mockType() 131 | ); 132 | 133 | await command.execute(editor); 134 | 135 | verify(editor.replaceSelectedTextsWith(any()), {times: 0}); 136 | verify(shellCommandService.runCommand(any()), {times: 0}); 137 | verify(historyStore.add(any()), {times: 0}); 138 | }); 139 | }); 140 | }); 141 | -------------------------------------------------------------------------------- /src/test/lib/commands/run-quick.test.ts: -------------------------------------------------------------------------------- 1 | import {RunQuickCommand} from '../../../lib/commands/run-quick'; 2 | import {Workspace} from '../../../lib/adapters/workspace'; 3 | import {Editor} from '../../../lib/adapters/editor'; 4 | import {ShellCommandService} from '../../../lib/shell-command-service'; 5 | import {HistoryStore} from '../../../lib/history-store'; 6 | import {any, mock, mockMethods, verify, when} from '../../helper'; 7 | 8 | describe('RunQuickCommand', () => { 9 | 10 | describe('When command is specified and "processEntireTextIfNoneSelected" is set to "false"', () => { 11 | const workspaceAdapter = mockMethods(['getConfig']); 12 | when(workspaceAdapter.getConfig('editWithShell.processEntireTextIfNoneSelected')).thenReturn(false); 13 | when(workspaceAdapter.getConfig('editWithShell.quickCommand1')).thenReturn('favourite-command-1'); 14 | when(workspaceAdapter.getConfig('editWithShell.favoriteCommands')).thenReturn([ 15 | {id: 'favourite-command-1', command: 'COMMAND_STRING'} 16 | ]); 17 | 18 | let shellCommandService: ShellCommandService; 19 | let historyStore: HistoryStore; 20 | let command: RunQuickCommand; 21 | 22 | beforeEach(() => { 23 | shellCommandService = mock(ShellCommandService); 24 | when(shellCommandService.runCommand({ 25 | command: 'COMMAND_STRING', 26 | input: 'SELECTED_TEXT', 27 | filePath: 'FILE_NAME' 28 | })).thenResolve('COMMAND_OUTPUT_1'); 29 | when(shellCommandService.runCommand({ 30 | command: 'COMMAND_STRING', 31 | input: '', 32 | filePath: 'FILE_NAME' 33 | })).thenResolve('COMMAND_OUTPUT_2'); 34 | 35 | historyStore = mock(HistoryStore); 36 | command = new RunQuickCommand(shellCommandService, historyStore, workspaceAdapter, 1); 37 | }); 38 | 39 | it('runs command with selected text and add commands to the history', async () => { 40 | const editor = mockMethods(['replaceSelectedTextsWith'], { 41 | isTextSelected: true, 42 | selectedTexts: ['SELECTED_TEXT'], 43 | entireText: 'ENTIRE_TEXT', 44 | filePath: 'FILE_NAME' 45 | }); 46 | 47 | await command.execute(editor); 48 | 49 | verify(editor.replaceSelectedTextsWith(['COMMAND_OUTPUT_1'])); 50 | verify(historyStore.add('COMMAND_STRING')); 51 | }); 52 | 53 | it('runs command with no input text', async () => { 54 | const editor = mockMethods(['replaceSelectedTextsWith'], { 55 | isTextSelected: false, 56 | selectedTexts: [''], 57 | entireText: 'ENTIRE_TEXT', 58 | filePath: 'FILE_NAME' 59 | }); 60 | 61 | await command.execute(editor); 62 | 63 | verify(editor.replaceSelectedTextsWith(['COMMAND_OUTPUT_2'])); 64 | }); 65 | }); 66 | 67 | describe('When command is specified and "processEntireTextIfNoneSelected" is set to "true"', () => { 68 | const workspaceAdapter = mockMethods(['getConfig']); 69 | when(workspaceAdapter.getConfig('editWithShell.processEntireTextIfNoneSelected')).thenReturn(true); 70 | when(workspaceAdapter.getConfig('editWithShell.quickCommand1')).thenReturn('favourite-command-1'); 71 | when(workspaceAdapter.getConfig('editWithShell.favoriteCommands')).thenReturn([ 72 | {id: 'favourite-command-1', command: 'COMMAND_STRING'} 73 | ]); 74 | 75 | let shellCommandService: ShellCommandService; 76 | let historyStore: HistoryStore; 77 | let command: RunQuickCommand; 78 | 79 | beforeEach(() => { 80 | shellCommandService = mock(ShellCommandService); 81 | when(shellCommandService.runCommand({ 82 | command: 'COMMAND_STRING', 83 | input: 'SELECTED_TEXT', 84 | filePath: 'FILE_NAME' 85 | })).thenResolve('COMMAND_OUTPUT_1'); 86 | when(shellCommandService.runCommand({ 87 | command: 'COMMAND_STRING', 88 | input: 'ENTIRE_TEXT', 89 | filePath: 'FILE_NAME' 90 | })).thenResolve('COMMAND_OUTPUT_2'); 91 | 92 | historyStore = mock(HistoryStore); 93 | command = new RunQuickCommand(shellCommandService, historyStore, workspaceAdapter, 1); 94 | }); 95 | 96 | it('runs command with selected text', async () => { 97 | const editor = mockMethods(['replaceSelectedTextsWith'], { 98 | isTextSelected: true, 99 | selectedTexts: ['SELECTED_TEXT'], 100 | entireText: 'ENTIRE_TEXT', 101 | filePath: 'FILE_NAME' 102 | }); 103 | 104 | await command.execute(editor); 105 | 106 | verify(editor.replaceSelectedTextsWith(['COMMAND_OUTPUT_1'])); 107 | }); 108 | 109 | it('runs command with entire text', async () => { 110 | const editor = mockMethods(['replaceEntireTextWith'], { 111 | isTextSelected: false, 112 | selectedTexts: [''], 113 | entireText: 'ENTIRE_TEXT', 114 | filePath: 'FILE_NAME' 115 | }); 116 | 117 | await command.execute(editor); 118 | 119 | verify(editor.replaceEntireTextWith('COMMAND_OUTPUT_2')); 120 | }); 121 | }); 122 | 123 | describe('When command is NOT specified', () => { 124 | const workspaceAdapter = mockMethods(['getConfig']); 125 | when(workspaceAdapter.getConfig('editWithShell.quickCommand1')).thenReturn(''); 126 | when(workspaceAdapter.getConfig('editWithShell.favoriteCommands')).thenReturn([]); 127 | 128 | it('does not try to run a command', async () => { 129 | const historyStore = mock(HistoryStore); 130 | const shellCommandService = mock(ShellCommandService); 131 | const editor = mock(Editor); 132 | const command = new RunQuickCommand(shellCommandService, historyStore, workspaceAdapter, 1); 133 | 134 | await command.execute(editor); 135 | 136 | verify(editor.replaceSelectedTextsWith(any()), {times: 0}); 137 | verify(shellCommandService.runCommand(any()), {times: 0}); 138 | verify(historyStore.add(any()), {times: 0}); 139 | }); 140 | }); 141 | }); 142 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "edit-with-shell", 3 | "displayName": "Edit with Shell Command", 4 | "description": "Leverage your favourite shell commands to edit text", 5 | "version": "1.3.0", 6 | "publisher": "ryu1kn", 7 | "license": "SEE LICENSE IN LICENSE.txt", 8 | "icon": "images/edit-with-shell.png", 9 | "bugs": { 10 | "url": "https://github.com/ryu1kn/vscode-edit-with-shell/issues" 11 | }, 12 | "homepage": "https://github.com/ryu1kn/vscode-edit-with-shell/blob/master/README.md", 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/ryu1kn/vscode-edit-with-shell.git" 16 | }, 17 | "engines": { 18 | "vscode": "^1.26.0" 19 | }, 20 | "categories": [ 21 | "Other" 22 | ], 23 | "keywords": [ 24 | "shell", 25 | "command", 26 | "filter" 27 | ], 28 | "activationEvents": [ 29 | "onCommand:editWithShell.clearCommandHistory", 30 | "onCommand:editWithShell.runCommand", 31 | "onCommand:editWithShell.runQuickCommand1", 32 | "onCommand:editWithShell.runQuickCommand2", 33 | "onCommand:editWithShell.runQuickCommand3", 34 | "onCommand:editWithShell.runQuickCommand4", 35 | "onCommand:editWithShell.runQuickCommand5" 36 | ], 37 | "main": "./out/extension", 38 | "contributes": { 39 | "commands": [ 40 | { 41 | "command": "editWithShell.clearCommandHistory", 42 | "title": "Clear command history", 43 | "category": "EditWithShell" 44 | }, 45 | { 46 | "command": "editWithShell.runCommand", 47 | "title": "Run command", 48 | "category": "EditWithShell" 49 | }, 50 | { 51 | "command": "editWithShell.runQuickCommand1", 52 | "title": "Run quick command 1", 53 | "category": "EditWithShell" 54 | }, 55 | { 56 | "command": "editWithShell.runQuickCommand2", 57 | "title": "Run quick command 2", 58 | "category": "EditWithShell" 59 | }, 60 | { 61 | "command": "editWithShell.runQuickCommand3", 62 | "title": "Run quick command 3", 63 | "category": "EditWithShell" 64 | }, 65 | { 66 | "command": "editWithShell.runQuickCommand4", 67 | "title": "Run quick command 4", 68 | "category": "EditWithShell" 69 | }, 70 | { 71 | "command": "editWithShell.runQuickCommand5", 72 | "title": "Run quick command 5", 73 | "category": "EditWithShell" 74 | } 75 | ], 76 | "configuration": { 77 | "type": "object", 78 | "title": "Edit with Shell Command configurations", 79 | "properties": { 80 | "editWithShell.currentDirectoryKind": { 81 | "description": "Current directory for shell commands", 82 | "type": "string", 83 | "enum": [ 84 | "currentFile", 85 | "workspaceRoot" 86 | ], 87 | "default": "currentFile" 88 | }, 89 | "editWithShell.quickCommand1": { 90 | "description": "ID of a favorite command triggered by quick command 1", 91 | "type": "string" 92 | }, 93 | "editWithShell.quickCommand2": { 94 | "description": "ID of a favorite command triggered by quick command 2", 95 | "type": "string" 96 | }, 97 | "editWithShell.quickCommand3": { 98 | "description": "ID of a favorite command triggered by quick command 3", 99 | "type": "string" 100 | }, 101 | "editWithShell.quickCommand4": { 102 | "description": "ID of a favorite command triggered by quick command 4", 103 | "type": "string" 104 | }, 105 | "editWithShell.quickCommand5": { 106 | "description": "ID of a favorite command triggered by quick command 5", 107 | "type": "string" 108 | }, 109 | "editWithShell.favoriteCommands": { 110 | "description": "Commands that can be activated by quick commands", 111 | "type": "array", 112 | "items": { 113 | "type": "object", 114 | "properties": { 115 | "id": { 116 | "type": "string" 117 | }, 118 | "command": { 119 | "type": "string" 120 | } 121 | }, 122 | "required": [ 123 | "id", 124 | "command" 125 | ] 126 | }, 127 | "default": [] 128 | }, 129 | "editWithShell.processEntireTextIfNoneSelected": { 130 | "description": "Pipe the entire text to the shell command if no text is selected", 131 | "type": "boolean", 132 | "default": false 133 | }, 134 | "editWithShell.shell.linux": { 135 | "description": "The path of the shell that this extension uses on Linux", 136 | "type": "string", 137 | "default": "/bin/sh" 138 | }, 139 | "editWithShell.shellArgs.linux": { 140 | "description": "Arguments to the shell to be used on Linux", 141 | "type": "array", 142 | "items": { 143 | "type": "string" 144 | }, 145 | "default": [ 146 | "-c" 147 | ] 148 | }, 149 | "editWithShell.shell.osx": { 150 | "description": "The path of the shell that this extension uses on OS X", 151 | "type": "string", 152 | "default": "/bin/sh" 153 | }, 154 | "editWithShell.shellArgs.osx": { 155 | "description": "Arguments to the shell to be used on OS X", 156 | "type": "array", 157 | "items": { 158 | "type": "string" 159 | }, 160 | "default": [ 161 | "-c" 162 | ] 163 | }, 164 | "editWithShell.shell.windows": { 165 | "description": "The path of the shell that this extension uses on Windows", 166 | "type": "string", 167 | "default": "cmd.exe" 168 | }, 169 | "editWithShell.shellArgs.windows": { 170 | "description": "Arguments to the shell to be used on Windows", 171 | "type": "array", 172 | "items": { 173 | "type": "string" 174 | }, 175 | "default": [ 176 | "/d", 177 | "/s", 178 | "/c" 179 | ] 180 | } 181 | } 182 | } 183 | }, 184 | "scripts": { 185 | "postinstall": "node ./node_modules/vscode/bin/install", 186 | "coverage": "nyc mocha", 187 | "lint": "tslint -p .", 188 | "test": "mocha", 189 | "test-mode": "mocha --watch", 190 | "compile": "tsc -p ./", 191 | "watch": "tsc -watch -p ./", 192 | "prep": "yarn run lint && yarn run compile && yarn test", 193 | "vscode:prepublish": "yarn run compile", 194 | "vscode:postpublish": "./tag-release.sh" 195 | }, 196 | "devDependencies": { 197 | "@types/mocha": "^8.0.4", 198 | "@types/node": "^12.14.1", 199 | "mocha": "^8.2.1", 200 | "nyc": "^15.1.0", 201 | "testdouble": "^3.13.1", 202 | "ts-node": "^9.0.0", 203 | "tslint": "^6.1.3", 204 | "typescript": "^4.1.2", 205 | "vscode": "^1.1.37" 206 | }, 207 | "resolutions": { 208 | "**/minimist": "^1.2.5" 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/code-frame@^7.0.0": 6 | version "7.0.0" 7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" 8 | dependencies: 9 | "@babel/highlight" "^7.0.0" 10 | 11 | "@babel/code-frame@^7.5.5": 12 | version "7.5.5" 13 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" 14 | integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== 15 | dependencies: 16 | "@babel/highlight" "^7.0.0" 17 | 18 | "@babel/core@^7.7.5": 19 | version "7.7.7" 20 | resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.7.tgz#ee155d2e12300bcc0cff6a8ad46f2af5063803e9" 21 | integrity sha512-jlSjuj/7z138NLZALxVgrx13AOtqip42ATZP7+kYl53GvDV6+4dCek1mVUo8z8c8Xnw/mx2q3d9HWh3griuesQ== 22 | dependencies: 23 | "@babel/code-frame" "^7.5.5" 24 | "@babel/generator" "^7.7.7" 25 | "@babel/helpers" "^7.7.4" 26 | "@babel/parser" "^7.7.7" 27 | "@babel/template" "^7.7.4" 28 | "@babel/traverse" "^7.7.4" 29 | "@babel/types" "^7.7.4" 30 | convert-source-map "^1.7.0" 31 | debug "^4.1.0" 32 | json5 "^2.1.0" 33 | lodash "^4.17.13" 34 | resolve "^1.3.2" 35 | semver "^5.4.1" 36 | source-map "^0.5.0" 37 | 38 | "@babel/generator@^7.7.4", "@babel/generator@^7.7.7": 39 | version "7.7.7" 40 | resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.7.tgz#859ac733c44c74148e1a72980a64ec84b85f4f45" 41 | integrity sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ== 42 | dependencies: 43 | "@babel/types" "^7.7.4" 44 | jsesc "^2.5.1" 45 | lodash "^4.17.13" 46 | source-map "^0.5.0" 47 | 48 | "@babel/helper-function-name@^7.7.4": 49 | version "7.7.4" 50 | resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e" 51 | integrity sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ== 52 | dependencies: 53 | "@babel/helper-get-function-arity" "^7.7.4" 54 | "@babel/template" "^7.7.4" 55 | "@babel/types" "^7.7.4" 56 | 57 | "@babel/helper-get-function-arity@^7.7.4": 58 | version "7.7.4" 59 | resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0" 60 | integrity sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA== 61 | dependencies: 62 | "@babel/types" "^7.7.4" 63 | 64 | "@babel/helper-split-export-declaration@^7.7.4": 65 | version "7.7.4" 66 | resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8" 67 | integrity sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug== 68 | dependencies: 69 | "@babel/types" "^7.7.4" 70 | 71 | "@babel/helpers@^7.7.4": 72 | version "7.7.4" 73 | resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.4.tgz#62c215b9e6c712dadc15a9a0dcab76c92a940302" 74 | integrity sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg== 75 | dependencies: 76 | "@babel/template" "^7.7.4" 77 | "@babel/traverse" "^7.7.4" 78 | "@babel/types" "^7.7.4" 79 | 80 | "@babel/highlight@^7.0.0": 81 | version "7.0.0" 82 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" 83 | dependencies: 84 | chalk "^2.0.0" 85 | esutils "^2.0.2" 86 | js-tokens "^4.0.0" 87 | 88 | "@babel/parser@^7.7.4", "@babel/parser@^7.7.5", "@babel/parser@^7.7.7": 89 | version "7.7.7" 90 | resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.7.tgz#1b886595419cf92d811316d5b715a53ff38b4937" 91 | integrity sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw== 92 | 93 | "@babel/template@^7.7.4": 94 | version "7.7.4" 95 | resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b" 96 | integrity sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw== 97 | dependencies: 98 | "@babel/code-frame" "^7.0.0" 99 | "@babel/parser" "^7.7.4" 100 | "@babel/types" "^7.7.4" 101 | 102 | "@babel/traverse@^7.7.4": 103 | version "7.7.4" 104 | resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558" 105 | integrity sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw== 106 | dependencies: 107 | "@babel/code-frame" "^7.5.5" 108 | "@babel/generator" "^7.7.4" 109 | "@babel/helper-function-name" "^7.7.4" 110 | "@babel/helper-split-export-declaration" "^7.7.4" 111 | "@babel/parser" "^7.7.4" 112 | "@babel/types" "^7.7.4" 113 | debug "^4.1.0" 114 | globals "^11.1.0" 115 | lodash "^4.17.13" 116 | 117 | "@babel/types@^7.7.4": 118 | version "7.7.4" 119 | resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193" 120 | integrity sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA== 121 | dependencies: 122 | esutils "^2.0.2" 123 | lodash "^4.17.13" 124 | to-fast-properties "^2.0.0" 125 | 126 | "@istanbuljs/load-nyc-config@^1.0.0": 127 | version "1.0.0" 128 | resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz#10602de5570baea82f8afbfa2630b24e7a8cfe5b" 129 | integrity sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg== 130 | dependencies: 131 | camelcase "^5.3.1" 132 | find-up "^4.1.0" 133 | js-yaml "^3.13.1" 134 | resolve-from "^5.0.0" 135 | 136 | "@istanbuljs/schema@^0.1.2": 137 | version "0.1.2" 138 | resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" 139 | integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== 140 | 141 | "@tootallnate/once@1": 142 | version "1.1.2" 143 | resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" 144 | integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== 145 | 146 | "@types/color-name@^1.1.1": 147 | version "1.1.1" 148 | resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" 149 | integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== 150 | 151 | "@types/mocha@^8.0.4": 152 | version "8.0.4" 153 | resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.0.4.tgz#b840c2dce46bacf286e237bfb59a29e843399148" 154 | integrity sha512-M4BwiTJjHmLq6kjON7ZoI2JMlBvpY3BYSdiP6s/qCT3jb1s9/DeJF0JELpAxiVSIxXDzfNKe+r7yedMIoLbknQ== 155 | 156 | "@types/node@^12.14.1": 157 | version "12.19.7" 158 | resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.7.tgz#cf8b6ac088dd9182ac9a1d765f787a8d12490c04" 159 | integrity sha512-zvjOU1g4CpPilbTDUATnZCUb/6lARMRAqzT7ILwl1P3YvU2leEcZ2+fw9+Jrw/paXB1CgQyXTrN4hWDtqT9O2A== 160 | 161 | "@ungap/promise-all-settled@1.1.2": 162 | version "1.1.2" 163 | resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" 164 | integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== 165 | 166 | agent-base@4, agent-base@^4.3.0: 167 | version "4.3.0" 168 | resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" 169 | integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== 170 | dependencies: 171 | es6-promisify "^5.0.0" 172 | 173 | agent-base@6: 174 | version "6.0.2" 175 | resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" 176 | integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== 177 | dependencies: 178 | debug "4" 179 | 180 | aggregate-error@^3.0.0: 181 | version "3.0.1" 182 | resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" 183 | integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== 184 | dependencies: 185 | clean-stack "^2.0.0" 186 | indent-string "^4.0.0" 187 | 188 | ansi-colors@4.1.1: 189 | version "4.1.1" 190 | resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" 191 | integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== 192 | 193 | ansi-regex@^3.0.0: 194 | version "3.0.1" 195 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" 196 | integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== 197 | 198 | ansi-regex@^4.1.0: 199 | version "4.1.0" 200 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" 201 | integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== 202 | 203 | ansi-regex@^5.0.0: 204 | version "5.0.0" 205 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" 206 | integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== 207 | 208 | ansi-styles@^3.2.0, ansi-styles@^3.2.1: 209 | version "3.2.1" 210 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 211 | dependencies: 212 | color-convert "^1.9.0" 213 | 214 | ansi-styles@^4.0.0: 215 | version "4.2.0" 216 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.0.tgz#5681f0dcf7ae5880a7841d8831c4724ed9cc0172" 217 | integrity sha512-7kFQgnEaMdRtwf6uSfUnVr9gSGC7faurn+J/Mv90/W+iTtN0405/nLdopfMWwchyxhbGYl6TC4Sccn9TUkGAgg== 218 | dependencies: 219 | "@types/color-name" "^1.1.1" 220 | color-convert "^2.0.1" 221 | 222 | ansi-styles@^4.1.0: 223 | version "4.3.0" 224 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 225 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 226 | dependencies: 227 | color-convert "^2.0.1" 228 | 229 | anymatch@~3.1.1: 230 | version "3.1.1" 231 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" 232 | integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== 233 | dependencies: 234 | normalize-path "^3.0.0" 235 | picomatch "^2.0.4" 236 | 237 | append-transform@^2.0.0: 238 | version "2.0.0" 239 | resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" 240 | integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg== 241 | dependencies: 242 | default-require-extensions "^3.0.0" 243 | 244 | archy@^1.0.0: 245 | version "1.0.0" 246 | resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" 247 | 248 | arg@^4.1.0: 249 | version "4.1.1" 250 | resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.1.tgz#485f8e7c390ce4c5f78257dbea80d4be11feda4c" 251 | integrity sha512-SlmP3fEA88MBv0PypnXZ8ZfJhwmDeIE3SP71j37AiXQBXYosPV0x6uISAaHYSlSVhmHOVkomen0tbGk6Anlebw== 252 | 253 | argparse@^1.0.7: 254 | version "1.0.10" 255 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 256 | dependencies: 257 | sprintf-js "~1.0.2" 258 | 259 | balanced-match@^1.0.0: 260 | version "1.0.0" 261 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 262 | 263 | binary-extensions@^2.0.0: 264 | version "2.0.0" 265 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" 266 | integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== 267 | 268 | brace-expansion@^1.1.7: 269 | version "1.1.11" 270 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 271 | dependencies: 272 | balanced-match "^1.0.0" 273 | concat-map "0.0.1" 274 | 275 | braces@~3.0.2: 276 | version "3.0.2" 277 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 278 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 279 | dependencies: 280 | fill-range "^7.0.1" 281 | 282 | browser-stdout@1.3.1: 283 | version "1.3.1" 284 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" 285 | 286 | buffer-from@^1.0.0: 287 | version "1.1.1" 288 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" 289 | 290 | builtin-modules@^1.1.1: 291 | version "1.1.1" 292 | resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" 293 | 294 | caching-transform@^4.0.0: 295 | version "4.0.0" 296 | resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz#00d297a4206d71e2163c39eaffa8157ac0651f0f" 297 | integrity sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA== 298 | dependencies: 299 | hasha "^5.0.0" 300 | make-dir "^3.0.0" 301 | package-hash "^4.0.0" 302 | write-file-atomic "^3.0.0" 303 | 304 | camelcase@^5.0.0, camelcase@^5.3.1: 305 | version "5.3.1" 306 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" 307 | integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== 308 | 309 | camelcase@^6.0.0: 310 | version "6.2.0" 311 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" 312 | integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== 313 | 314 | chalk@^2.0.0, chalk@^2.3.0: 315 | version "2.4.1" 316 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" 317 | dependencies: 318 | ansi-styles "^3.2.1" 319 | escape-string-regexp "^1.0.5" 320 | supports-color "^5.3.0" 321 | 322 | chalk@^4.0.0: 323 | version "4.1.0" 324 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" 325 | integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== 326 | dependencies: 327 | ansi-styles "^4.1.0" 328 | supports-color "^7.1.0" 329 | 330 | chokidar@3.4.3: 331 | version "3.4.3" 332 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b" 333 | integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ== 334 | dependencies: 335 | anymatch "~3.1.1" 336 | braces "~3.0.2" 337 | glob-parent "~5.1.0" 338 | is-binary-path "~2.1.0" 339 | is-glob "~4.0.1" 340 | normalize-path "~3.0.0" 341 | readdirp "~3.5.0" 342 | optionalDependencies: 343 | fsevents "~2.1.2" 344 | 345 | clean-stack@^2.0.0: 346 | version "2.2.0" 347 | resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" 348 | integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== 349 | 350 | cliui@^5.0.0: 351 | version "5.0.0" 352 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" 353 | integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== 354 | dependencies: 355 | string-width "^3.1.0" 356 | strip-ansi "^5.2.0" 357 | wrap-ansi "^5.1.0" 358 | 359 | cliui@^6.0.0: 360 | version "6.0.0" 361 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" 362 | integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== 363 | dependencies: 364 | string-width "^4.2.0" 365 | strip-ansi "^6.0.0" 366 | wrap-ansi "^6.2.0" 367 | 368 | color-convert@^1.9.0: 369 | version "1.9.2" 370 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" 371 | dependencies: 372 | color-name "1.1.1" 373 | 374 | color-convert@^2.0.1: 375 | version "2.0.1" 376 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 377 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 378 | dependencies: 379 | color-name "~1.1.4" 380 | 381 | color-name@1.1.1: 382 | version "1.1.1" 383 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" 384 | 385 | color-name@~1.1.4: 386 | version "1.1.4" 387 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 388 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 389 | 390 | commander@2.15.1: 391 | version "2.15.1" 392 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" 393 | 394 | commander@^2.12.1: 395 | version "2.17.1" 396 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" 397 | 398 | commondir@^1.0.1: 399 | version "1.0.1" 400 | resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" 401 | 402 | concat-map@0.0.1: 403 | version "0.0.1" 404 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 405 | 406 | convert-source-map@^1.7.0: 407 | version "1.7.0" 408 | resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" 409 | integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== 410 | dependencies: 411 | safe-buffer "~5.1.1" 412 | 413 | cross-spawn@^7.0.0: 414 | version "7.0.1" 415 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.1.tgz#0ab56286e0f7c24e153d04cc2aa027e43a9a5d14" 416 | integrity sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg== 417 | dependencies: 418 | path-key "^3.1.0" 419 | shebang-command "^2.0.0" 420 | which "^2.0.1" 421 | 422 | debug@3.1.0: 423 | version "3.1.0" 424 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" 425 | dependencies: 426 | ms "2.0.0" 427 | 428 | debug@4: 429 | version "4.3.1" 430 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" 431 | integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== 432 | dependencies: 433 | ms "2.1.2" 434 | 435 | debug@4.2.0: 436 | version "4.2.0" 437 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" 438 | integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== 439 | dependencies: 440 | ms "2.1.2" 441 | 442 | debug@^3.1.0: 443 | version "3.2.6" 444 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" 445 | integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== 446 | dependencies: 447 | ms "^2.1.1" 448 | 449 | debug@^4.1.0, debug@^4.1.1: 450 | version "4.1.1" 451 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" 452 | integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== 453 | dependencies: 454 | ms "^2.1.1" 455 | 456 | decamelize@^1.2.0: 457 | version "1.2.0" 458 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" 459 | integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= 460 | 461 | decamelize@^4.0.0: 462 | version "4.0.0" 463 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" 464 | integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== 465 | 466 | default-require-extensions@^3.0.0: 467 | version "3.0.0" 468 | resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.0.tgz#e03f93aac9b2b6443fc52e5e4a37b3ad9ad8df96" 469 | integrity sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg== 470 | dependencies: 471 | strip-bom "^4.0.0" 472 | 473 | diff@3.5.0: 474 | version "3.5.0" 475 | resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" 476 | 477 | diff@4.0.2: 478 | version "4.0.2" 479 | resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" 480 | integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== 481 | 482 | diff@^4.0.1: 483 | version "4.0.1" 484 | resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff" 485 | integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q== 486 | 487 | emoji-regex@^7.0.1: 488 | version "7.0.3" 489 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" 490 | integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== 491 | 492 | emoji-regex@^8.0.0: 493 | version "8.0.0" 494 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 495 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 496 | 497 | es6-error@^4.0.1: 498 | version "4.1.1" 499 | resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" 500 | 501 | es6-promise@^4.0.3: 502 | version "4.2.8" 503 | resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" 504 | integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== 505 | 506 | es6-promisify@^5.0.0: 507 | version "5.0.0" 508 | resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" 509 | integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= 510 | dependencies: 511 | es6-promise "^4.0.3" 512 | 513 | escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: 514 | version "1.0.5" 515 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 516 | 517 | escape-string-regexp@4.0.0: 518 | version "4.0.0" 519 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 520 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 521 | 522 | esprima@^4.0.0: 523 | version "4.0.1" 524 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 525 | 526 | esutils@^2.0.2: 527 | version "2.0.2" 528 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" 529 | 530 | fill-range@^7.0.1: 531 | version "7.0.1" 532 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 533 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 534 | dependencies: 535 | to-regex-range "^5.0.1" 536 | 537 | find-cache-dir@^3.2.0: 538 | version "3.2.0" 539 | resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.2.0.tgz#e7fe44c1abc1299f516146e563108fd1006c1874" 540 | integrity sha512-1JKclkYYsf1q9WIJKLZa9S9muC+08RIjzAlLrK4QcYLJMS6mk9yombQ9qf+zJ7H9LS800k0s44L4sDq9VYzqyg== 541 | dependencies: 542 | commondir "^1.0.1" 543 | make-dir "^3.0.0" 544 | pkg-dir "^4.1.0" 545 | 546 | find-up@5.0.0: 547 | version "5.0.0" 548 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" 549 | integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 550 | dependencies: 551 | locate-path "^6.0.0" 552 | path-exists "^4.0.0" 553 | 554 | find-up@^3.0.0: 555 | version "3.0.0" 556 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" 557 | integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== 558 | dependencies: 559 | locate-path "^3.0.0" 560 | 561 | find-up@^4.0.0, find-up@^4.1.0: 562 | version "4.1.0" 563 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" 564 | integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== 565 | dependencies: 566 | locate-path "^5.0.0" 567 | path-exists "^4.0.0" 568 | 569 | flat@^5.0.2: 570 | version "5.0.2" 571 | resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" 572 | integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== 573 | 574 | foreground-child@^2.0.0: 575 | version "2.0.0" 576 | resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" 577 | integrity sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA== 578 | dependencies: 579 | cross-spawn "^7.0.0" 580 | signal-exit "^3.0.2" 581 | 582 | fromentries@^1.2.0: 583 | version "1.2.0" 584 | resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.2.0.tgz#e6aa06f240d6267f913cea422075ef88b63e7897" 585 | integrity sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ== 586 | 587 | fs.realpath@^1.0.0: 588 | version "1.0.0" 589 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 590 | 591 | fsevents@~2.1.2: 592 | version "2.1.3" 593 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" 594 | integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== 595 | 596 | get-caller-file@^2.0.1: 597 | version "2.0.5" 598 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 599 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 600 | 601 | get-package-type@^0.1.0: 602 | version "0.1.0" 603 | resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" 604 | integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== 605 | 606 | glob-parent@~5.1.0: 607 | version "5.1.2" 608 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 609 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 610 | dependencies: 611 | is-glob "^4.0.1" 612 | 613 | glob@7.1.2, glob@^7.1.1, glob@^7.1.2: 614 | version "7.1.2" 615 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" 616 | dependencies: 617 | fs.realpath "^1.0.0" 618 | inflight "^1.0.4" 619 | inherits "2" 620 | minimatch "^3.0.4" 621 | once "^1.3.0" 622 | path-is-absolute "^1.0.0" 623 | 624 | glob@7.1.6, glob@^7.1.4, glob@^7.1.6: 625 | version "7.1.6" 626 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" 627 | integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== 628 | dependencies: 629 | fs.realpath "^1.0.0" 630 | inflight "^1.0.4" 631 | inherits "2" 632 | minimatch "^3.0.4" 633 | once "^1.3.0" 634 | path-is-absolute "^1.0.0" 635 | 636 | glob@^7.1.3: 637 | version "7.1.3" 638 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" 639 | integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== 640 | dependencies: 641 | fs.realpath "^1.0.0" 642 | inflight "^1.0.4" 643 | inherits "2" 644 | minimatch "^3.0.4" 645 | once "^1.3.0" 646 | path-is-absolute "^1.0.0" 647 | 648 | globals@^11.1.0: 649 | version "11.7.0" 650 | resolved "https://registry.yarnpkg.com/globals/-/globals-11.7.0.tgz#a583faa43055b1aca771914bf68258e2fc125673" 651 | 652 | graceful-fs@^4.1.15: 653 | version "4.2.2" 654 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" 655 | integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== 656 | 657 | growl@1.10.5: 658 | version "1.10.5" 659 | resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" 660 | 661 | has-flag@^3.0.0: 662 | version "3.0.0" 663 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 664 | 665 | has-flag@^4.0.0: 666 | version "4.0.0" 667 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 668 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 669 | 670 | hasha@^5.0.0: 671 | version "5.1.0" 672 | resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.1.0.tgz#dd05ccdfcfe7dab626247ce2a58efe461922f4ca" 673 | integrity sha512-OFPDWmzPN1l7atOV1TgBVmNtBxaIysToK6Ve9DK+vT6pYuklw/nPNT+HJbZi0KDcI6vWB+9tgvZ5YD7fA3CXcA== 674 | dependencies: 675 | is-stream "^2.0.0" 676 | type-fest "^0.8.0" 677 | 678 | he@1.1.1: 679 | version "1.1.1" 680 | resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" 681 | 682 | he@1.2.0: 683 | version "1.2.0" 684 | resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" 685 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== 686 | 687 | html-escaper@^2.0.0: 688 | version "2.0.0" 689 | resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.0.tgz#71e87f931de3fe09e56661ab9a29aadec707b491" 690 | integrity sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig== 691 | 692 | http-proxy-agent@^2.1.0: 693 | version "2.1.0" 694 | resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" 695 | integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg== 696 | dependencies: 697 | agent-base "4" 698 | debug "3.1.0" 699 | 700 | http-proxy-agent@^4.0.1: 701 | version "4.0.1" 702 | resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" 703 | integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== 704 | dependencies: 705 | "@tootallnate/once" "1" 706 | agent-base "6" 707 | debug "4" 708 | 709 | https-proxy-agent@^2.2.1: 710 | version "2.2.4" 711 | resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" 712 | integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== 713 | dependencies: 714 | agent-base "^4.3.0" 715 | debug "^3.1.0" 716 | 717 | https-proxy-agent@^5.0.0: 718 | version "5.0.0" 719 | resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" 720 | integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== 721 | dependencies: 722 | agent-base "6" 723 | debug "4" 724 | 725 | imurmurhash@^0.1.4: 726 | version "0.1.4" 727 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 728 | 729 | indent-string@^4.0.0: 730 | version "4.0.0" 731 | resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" 732 | integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== 733 | 734 | inflight@^1.0.4: 735 | version "1.0.6" 736 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 737 | dependencies: 738 | once "^1.3.0" 739 | wrappy "1" 740 | 741 | inherits@2: 742 | version "2.0.3" 743 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 744 | 745 | is-binary-path@~2.1.0: 746 | version "2.1.0" 747 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 748 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 749 | dependencies: 750 | binary-extensions "^2.0.0" 751 | 752 | is-extglob@^2.1.1: 753 | version "2.1.1" 754 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 755 | integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= 756 | 757 | is-fullwidth-code-point@^2.0.0: 758 | version "2.0.0" 759 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 760 | 761 | is-fullwidth-code-point@^3.0.0: 762 | version "3.0.0" 763 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 764 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 765 | 766 | is-glob@^4.0.1, is-glob@~4.0.1: 767 | version "4.0.1" 768 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" 769 | integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== 770 | dependencies: 771 | is-extglob "^2.1.1" 772 | 773 | is-number@^7.0.0: 774 | version "7.0.0" 775 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 776 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 777 | 778 | is-plain-obj@^1.0.0: 779 | version "1.1.0" 780 | resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" 781 | 782 | is-plain-obj@^2.1.0: 783 | version "2.1.0" 784 | resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" 785 | integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== 786 | 787 | is-regexp@^1.0.0: 788 | version "1.0.0" 789 | resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" 790 | 791 | is-stream@^2.0.0: 792 | version "2.0.0" 793 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" 794 | integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== 795 | 796 | is-typedarray@^1.0.0: 797 | version "1.0.0" 798 | resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" 799 | integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= 800 | 801 | is-windows@^1.0.2: 802 | version "1.0.2" 803 | resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" 804 | integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== 805 | 806 | isexe@^2.0.0: 807 | version "2.0.0" 808 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 809 | 810 | istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.0.0-alpha.1: 811 | version "3.0.0" 812 | resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" 813 | integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== 814 | 815 | istanbul-lib-hook@^3.0.0: 816 | version "3.0.0" 817 | resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz#8f84c9434888cc6b1d0a9d7092a76d239ebf0cc6" 818 | integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ== 819 | dependencies: 820 | append-transform "^2.0.0" 821 | 822 | istanbul-lib-instrument@^4.0.0: 823 | version "4.0.0" 824 | resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.0.tgz#53321a7970f076262fd3292c8f9b2e4ac544aae1" 825 | integrity sha512-Nm4wVHdo7ZXSG30KjZ2Wl5SU/Bw7bDx1PdaiIFzEStdjs0H12mOTncn1GVYuqQSaZxpg87VGBRsVRPGD2cD1AQ== 826 | dependencies: 827 | "@babel/core" "^7.7.5" 828 | "@babel/parser" "^7.7.5" 829 | "@babel/template" "^7.7.4" 830 | "@babel/traverse" "^7.7.4" 831 | "@istanbuljs/schema" "^0.1.2" 832 | istanbul-lib-coverage "^3.0.0" 833 | semver "^6.3.0" 834 | 835 | istanbul-lib-processinfo@^2.0.2: 836 | version "2.0.2" 837 | resolved "https://registry.yarnpkg.com/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz#e1426514662244b2f25df728e8fd1ba35fe53b9c" 838 | integrity sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw== 839 | dependencies: 840 | archy "^1.0.0" 841 | cross-spawn "^7.0.0" 842 | istanbul-lib-coverage "^3.0.0-alpha.1" 843 | make-dir "^3.0.0" 844 | p-map "^3.0.0" 845 | rimraf "^3.0.0" 846 | uuid "^3.3.3" 847 | 848 | istanbul-lib-report@^3.0.0: 849 | version "3.0.0" 850 | resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" 851 | integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== 852 | dependencies: 853 | istanbul-lib-coverage "^3.0.0" 854 | make-dir "^3.0.0" 855 | supports-color "^7.1.0" 856 | 857 | istanbul-lib-source-maps@^4.0.0: 858 | version "4.0.0" 859 | resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" 860 | integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== 861 | dependencies: 862 | debug "^4.1.1" 863 | istanbul-lib-coverage "^3.0.0" 864 | source-map "^0.6.1" 865 | 866 | istanbul-reports@^3.0.2: 867 | version "3.0.2" 868 | resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b" 869 | integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== 870 | dependencies: 871 | html-escaper "^2.0.0" 872 | istanbul-lib-report "^3.0.0" 873 | 874 | js-tokens@^4.0.0: 875 | version "4.0.0" 876 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 877 | 878 | js-yaml@3.14.0: 879 | version "3.14.0" 880 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" 881 | integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== 882 | dependencies: 883 | argparse "^1.0.7" 884 | esprima "^4.0.0" 885 | 886 | js-yaml@^3.13.1: 887 | version "3.13.1" 888 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" 889 | integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== 890 | dependencies: 891 | argparse "^1.0.7" 892 | esprima "^4.0.0" 893 | 894 | jsesc@^2.5.1: 895 | version "2.5.1" 896 | resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" 897 | 898 | json5@^2.1.0: 899 | version "2.2.3" 900 | resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" 901 | integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== 902 | 903 | locate-path@^3.0.0: 904 | version "3.0.0" 905 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" 906 | dependencies: 907 | p-locate "^3.0.0" 908 | path-exists "^3.0.0" 909 | 910 | locate-path@^5.0.0: 911 | version "5.0.0" 912 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" 913 | integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== 914 | dependencies: 915 | p-locate "^4.1.0" 916 | 917 | locate-path@^6.0.0: 918 | version "6.0.0" 919 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" 920 | integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== 921 | dependencies: 922 | p-locate "^5.0.0" 923 | 924 | lodash.flattendeep@^4.4.0: 925 | version "4.4.0" 926 | resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" 927 | 928 | lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15: 929 | version "4.17.21" 930 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 931 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 932 | 933 | log-symbols@4.0.0: 934 | version "4.0.0" 935 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" 936 | integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== 937 | dependencies: 938 | chalk "^4.0.0" 939 | 940 | make-dir@^3.0.0: 941 | version "3.0.0" 942 | resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.0.0.tgz#1b5f39f6b9270ed33f9f054c5c0f84304989f801" 943 | integrity sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw== 944 | dependencies: 945 | semver "^6.0.0" 946 | 947 | make-error@^1.1.1: 948 | version "1.3.4" 949 | resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.4.tgz#19978ed575f9e9545d2ff8c13e33b5d18a67d535" 950 | 951 | minimatch@3.0.4, minimatch@^3.0.4: 952 | version "3.0.4" 953 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 954 | dependencies: 955 | brace-expansion "^1.1.7" 956 | 957 | minimist@0.0.8, minimist@^1.2.5: 958 | version "1.2.6" 959 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" 960 | integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== 961 | 962 | mkdirp@0.5.1: 963 | version "0.5.1" 964 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 965 | dependencies: 966 | minimist "0.0.8" 967 | 968 | mkdirp@^0.5.3: 969 | version "0.5.5" 970 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" 971 | integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== 972 | dependencies: 973 | minimist "^1.2.5" 974 | 975 | mocha@^5.2.0: 976 | version "5.2.0" 977 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" 978 | dependencies: 979 | browser-stdout "1.3.1" 980 | commander "2.15.1" 981 | debug "3.1.0" 982 | diff "3.5.0" 983 | escape-string-regexp "1.0.5" 984 | glob "7.1.2" 985 | growl "1.10.5" 986 | he "1.1.1" 987 | minimatch "3.0.4" 988 | mkdirp "0.5.1" 989 | supports-color "5.4.0" 990 | 991 | mocha@^8.2.1: 992 | version "8.2.1" 993 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.2.1.tgz#f2fa68817ed0e53343d989df65ccd358bc3a4b39" 994 | integrity sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w== 995 | dependencies: 996 | "@ungap/promise-all-settled" "1.1.2" 997 | ansi-colors "4.1.1" 998 | browser-stdout "1.3.1" 999 | chokidar "3.4.3" 1000 | debug "4.2.0" 1001 | diff "4.0.2" 1002 | escape-string-regexp "4.0.0" 1003 | find-up "5.0.0" 1004 | glob "7.1.6" 1005 | growl "1.10.5" 1006 | he "1.2.0" 1007 | js-yaml "3.14.0" 1008 | log-symbols "4.0.0" 1009 | minimatch "3.0.4" 1010 | ms "2.1.2" 1011 | nanoid "3.1.12" 1012 | serialize-javascript "5.0.1" 1013 | strip-json-comments "3.1.1" 1014 | supports-color "7.2.0" 1015 | which "2.0.2" 1016 | wide-align "1.1.3" 1017 | workerpool "6.0.2" 1018 | yargs "13.3.2" 1019 | yargs-parser "13.1.2" 1020 | yargs-unparser "2.0.0" 1021 | 1022 | ms@2.0.0: 1023 | version "2.0.0" 1024 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 1025 | 1026 | ms@2.1.2, ms@^2.1.1: 1027 | version "2.1.2" 1028 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 1029 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 1030 | 1031 | nanoid@3.1.12: 1032 | version "3.1.12" 1033 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.12.tgz#6f7736c62e8d39421601e4a0c77623a97ea69654" 1034 | integrity sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A== 1035 | 1036 | node-preload@^0.2.1: 1037 | version "0.2.1" 1038 | resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301" 1039 | integrity sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ== 1040 | dependencies: 1041 | process-on-spawn "^1.0.0" 1042 | 1043 | normalize-path@^3.0.0, normalize-path@~3.0.0: 1044 | version "3.0.0" 1045 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 1046 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 1047 | 1048 | nyc@^15.1.0: 1049 | version "15.1.0" 1050 | resolved "https://registry.yarnpkg.com/nyc/-/nyc-15.1.0.tgz#1335dae12ddc87b6e249d5a1994ca4bdaea75f02" 1051 | integrity sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A== 1052 | dependencies: 1053 | "@istanbuljs/load-nyc-config" "^1.0.0" 1054 | "@istanbuljs/schema" "^0.1.2" 1055 | caching-transform "^4.0.0" 1056 | convert-source-map "^1.7.0" 1057 | decamelize "^1.2.0" 1058 | find-cache-dir "^3.2.0" 1059 | find-up "^4.1.0" 1060 | foreground-child "^2.0.0" 1061 | get-package-type "^0.1.0" 1062 | glob "^7.1.6" 1063 | istanbul-lib-coverage "^3.0.0" 1064 | istanbul-lib-hook "^3.0.0" 1065 | istanbul-lib-instrument "^4.0.0" 1066 | istanbul-lib-processinfo "^2.0.2" 1067 | istanbul-lib-report "^3.0.0" 1068 | istanbul-lib-source-maps "^4.0.0" 1069 | istanbul-reports "^3.0.2" 1070 | make-dir "^3.0.0" 1071 | node-preload "^0.2.1" 1072 | p-map "^3.0.0" 1073 | process-on-spawn "^1.0.0" 1074 | resolve-from "^5.0.0" 1075 | rimraf "^3.0.0" 1076 | signal-exit "^3.0.2" 1077 | spawn-wrap "^2.0.0" 1078 | test-exclude "^6.0.0" 1079 | yargs "^15.0.2" 1080 | 1081 | once@^1.3.0: 1082 | version "1.4.0" 1083 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 1084 | dependencies: 1085 | wrappy "1" 1086 | 1087 | p-limit@^2.0.0: 1088 | version "2.0.0" 1089 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec" 1090 | dependencies: 1091 | p-try "^2.0.0" 1092 | 1093 | p-limit@^2.2.0: 1094 | version "2.2.1" 1095 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" 1096 | integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== 1097 | dependencies: 1098 | p-try "^2.0.0" 1099 | 1100 | p-limit@^3.0.2: 1101 | version "3.1.0" 1102 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" 1103 | integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 1104 | dependencies: 1105 | yocto-queue "^0.1.0" 1106 | 1107 | p-locate@^3.0.0: 1108 | version "3.0.0" 1109 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" 1110 | dependencies: 1111 | p-limit "^2.0.0" 1112 | 1113 | p-locate@^4.1.0: 1114 | version "4.1.0" 1115 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" 1116 | integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== 1117 | dependencies: 1118 | p-limit "^2.2.0" 1119 | 1120 | p-locate@^5.0.0: 1121 | version "5.0.0" 1122 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" 1123 | integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== 1124 | dependencies: 1125 | p-limit "^3.0.2" 1126 | 1127 | p-map@^3.0.0: 1128 | version "3.0.0" 1129 | resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" 1130 | integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== 1131 | dependencies: 1132 | aggregate-error "^3.0.0" 1133 | 1134 | p-try@^2.0.0: 1135 | version "2.0.0" 1136 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" 1137 | 1138 | package-hash@^4.0.0: 1139 | version "4.0.0" 1140 | resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-4.0.0.tgz#3537f654665ec3cc38827387fc904c163c54f506" 1141 | integrity sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ== 1142 | dependencies: 1143 | graceful-fs "^4.1.15" 1144 | hasha "^5.0.0" 1145 | lodash.flattendeep "^4.4.0" 1146 | release-zalgo "^1.0.0" 1147 | 1148 | path-exists@^3.0.0: 1149 | version "3.0.0" 1150 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" 1151 | 1152 | path-exists@^4.0.0: 1153 | version "4.0.0" 1154 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 1155 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 1156 | 1157 | path-is-absolute@^1.0.0: 1158 | version "1.0.1" 1159 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 1160 | 1161 | path-key@^3.1.0: 1162 | version "3.1.1" 1163 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 1164 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 1165 | 1166 | path-parse@^1.0.5, path-parse@^1.0.6: 1167 | version "1.0.7" 1168 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" 1169 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 1170 | 1171 | picomatch@^2.0.4, picomatch@^2.2.1: 1172 | version "2.2.2" 1173 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" 1174 | integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== 1175 | 1176 | pkg-dir@^4.1.0: 1177 | version "4.2.0" 1178 | resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" 1179 | integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== 1180 | dependencies: 1181 | find-up "^4.0.0" 1182 | 1183 | process-on-spawn@^1.0.0: 1184 | version "1.0.0" 1185 | resolved "https://registry.yarnpkg.com/process-on-spawn/-/process-on-spawn-1.0.0.tgz#95b05a23073d30a17acfdc92a440efd2baefdc93" 1186 | integrity sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg== 1187 | dependencies: 1188 | fromentries "^1.2.0" 1189 | 1190 | quibble@^0.5.7: 1191 | version "0.5.7" 1192 | resolved "https://registry.yarnpkg.com/quibble/-/quibble-0.5.7.tgz#34ea5467eee32dfa37968742a5af21b02cd6ebe0" 1193 | integrity sha512-QnHxlD12qhGGjvoEW4PIp8tA80tKjh5CxTg5wLTPp/aqvHElBA+Ag3JN0dWlHY96CUaJqSGmLxTLi+7wbysyZw== 1194 | dependencies: 1195 | lodash "^4.17.14" 1196 | resolve "^1.11.1" 1197 | 1198 | randombytes@^2.1.0: 1199 | version "2.1.0" 1200 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" 1201 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== 1202 | dependencies: 1203 | safe-buffer "^5.1.0" 1204 | 1205 | readdirp@~3.5.0: 1206 | version "3.5.0" 1207 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" 1208 | integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== 1209 | dependencies: 1210 | picomatch "^2.2.1" 1211 | 1212 | release-zalgo@^1.0.0: 1213 | version "1.0.0" 1214 | resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" 1215 | dependencies: 1216 | es6-error "^4.0.1" 1217 | 1218 | require-directory@^2.1.1: 1219 | version "2.1.1" 1220 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 1221 | 1222 | require-main-filename@^2.0.0: 1223 | version "2.0.0" 1224 | resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" 1225 | integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== 1226 | 1227 | resolve-from@^5.0.0: 1228 | version "5.0.0" 1229 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" 1230 | integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== 1231 | 1232 | resolve@^1.11.1: 1233 | version "1.12.0" 1234 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" 1235 | integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== 1236 | dependencies: 1237 | path-parse "^1.0.6" 1238 | 1239 | resolve@^1.3.2: 1240 | version "1.8.1" 1241 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" 1242 | dependencies: 1243 | path-parse "^1.0.5" 1244 | 1245 | rimraf@^3.0.0: 1246 | version "3.0.0" 1247 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.0.tgz#614176d4b3010b75e5c390eb0ee96f6dc0cebb9b" 1248 | integrity sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg== 1249 | dependencies: 1250 | glob "^7.1.3" 1251 | 1252 | safe-buffer@^5.1.0: 1253 | version "5.2.1" 1254 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 1255 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 1256 | 1257 | safe-buffer@~5.1.1: 1258 | version "5.1.2" 1259 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 1260 | 1261 | semver@^5.3.0, semver@^5.4.1: 1262 | version "5.5.0" 1263 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" 1264 | 1265 | semver@^6.0.0, semver@^6.3.0: 1266 | version "6.3.0" 1267 | resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" 1268 | integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== 1269 | 1270 | serialize-javascript@5.0.1: 1271 | version "5.0.1" 1272 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" 1273 | integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== 1274 | dependencies: 1275 | randombytes "^2.1.0" 1276 | 1277 | set-blocking@^2.0.0: 1278 | version "2.0.0" 1279 | resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" 1280 | 1281 | shebang-command@^2.0.0: 1282 | version "2.0.0" 1283 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 1284 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 1285 | dependencies: 1286 | shebang-regex "^3.0.0" 1287 | 1288 | shebang-regex@^3.0.0: 1289 | version "3.0.0" 1290 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 1291 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 1292 | 1293 | signal-exit@^3.0.2: 1294 | version "3.0.2" 1295 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" 1296 | 1297 | source-map-support@^0.5.0: 1298 | version "0.5.8" 1299 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.8.tgz#04f5581713a8a65612d0175fbf3a01f80a162613" 1300 | dependencies: 1301 | buffer-from "^1.0.0" 1302 | source-map "^0.6.0" 1303 | 1304 | source-map-support@^0.5.17: 1305 | version "0.5.19" 1306 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" 1307 | integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== 1308 | dependencies: 1309 | buffer-from "^1.0.0" 1310 | source-map "^0.6.0" 1311 | 1312 | source-map@^0.5.0: 1313 | version "0.5.7" 1314 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" 1315 | 1316 | source-map@^0.6.0, source-map@^0.6.1: 1317 | version "0.6.1" 1318 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 1319 | 1320 | spawn-wrap@^2.0.0: 1321 | version "2.0.0" 1322 | resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-2.0.0.tgz#103685b8b8f9b79771318827aa78650a610d457e" 1323 | integrity sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg== 1324 | dependencies: 1325 | foreground-child "^2.0.0" 1326 | is-windows "^1.0.2" 1327 | make-dir "^3.0.0" 1328 | rimraf "^3.0.0" 1329 | signal-exit "^3.0.2" 1330 | which "^2.0.1" 1331 | 1332 | sprintf-js@~1.0.2: 1333 | version "1.0.3" 1334 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 1335 | 1336 | "string-width@^1.0.2 || 2": 1337 | version "2.1.1" 1338 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" 1339 | integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== 1340 | dependencies: 1341 | is-fullwidth-code-point "^2.0.0" 1342 | strip-ansi "^4.0.0" 1343 | 1344 | string-width@^3.0.0, string-width@^3.1.0: 1345 | version "3.1.0" 1346 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" 1347 | integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== 1348 | dependencies: 1349 | emoji-regex "^7.0.1" 1350 | is-fullwidth-code-point "^2.0.0" 1351 | strip-ansi "^5.1.0" 1352 | 1353 | string-width@^4.1.0, string-width@^4.2.0: 1354 | version "4.2.0" 1355 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" 1356 | integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== 1357 | dependencies: 1358 | emoji-regex "^8.0.0" 1359 | is-fullwidth-code-point "^3.0.0" 1360 | strip-ansi "^6.0.0" 1361 | 1362 | stringify-object-es5@^2.5.0: 1363 | version "2.5.0" 1364 | resolved "https://registry.yarnpkg.com/stringify-object-es5/-/stringify-object-es5-2.5.0.tgz#057c3c9a90a127339bb9d1704a290bb7bd0a1ec5" 1365 | dependencies: 1366 | is-plain-obj "^1.0.0" 1367 | is-regexp "^1.0.0" 1368 | 1369 | strip-ansi@^4.0.0: 1370 | version "4.0.0" 1371 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" 1372 | dependencies: 1373 | ansi-regex "^3.0.0" 1374 | 1375 | strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: 1376 | version "5.2.0" 1377 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" 1378 | integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== 1379 | dependencies: 1380 | ansi-regex "^4.1.0" 1381 | 1382 | strip-ansi@^6.0.0: 1383 | version "6.0.0" 1384 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" 1385 | integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== 1386 | dependencies: 1387 | ansi-regex "^5.0.0" 1388 | 1389 | strip-bom@^4.0.0: 1390 | version "4.0.0" 1391 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" 1392 | integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== 1393 | 1394 | strip-json-comments@3.1.1: 1395 | version "3.1.1" 1396 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" 1397 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 1398 | 1399 | supports-color@5.4.0, supports-color@^5.3.0: 1400 | version "5.4.0" 1401 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" 1402 | dependencies: 1403 | has-flag "^3.0.0" 1404 | 1405 | supports-color@7.2.0: 1406 | version "7.2.0" 1407 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 1408 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 1409 | dependencies: 1410 | has-flag "^4.0.0" 1411 | 1412 | supports-color@^7.1.0: 1413 | version "7.1.0" 1414 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" 1415 | integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== 1416 | dependencies: 1417 | has-flag "^4.0.0" 1418 | 1419 | test-exclude@^6.0.0: 1420 | version "6.0.0" 1421 | resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" 1422 | integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== 1423 | dependencies: 1424 | "@istanbuljs/schema" "^0.1.2" 1425 | glob "^7.1.4" 1426 | minimatch "^3.0.4" 1427 | 1428 | testdouble@^3.13.1: 1429 | version "3.13.1" 1430 | resolved "https://registry.yarnpkg.com/testdouble/-/testdouble-3.13.1.tgz#22a8cb06a92973a917d57419d4b080bbd349e43d" 1431 | integrity sha512-3fMIiKxi64WfVyPpPH0psKLNV2VDBt2fjNOOmp9g3ZPW6CTtbpAH2GK5Y3m0uK6vkerWOK41orfWNI8R2iDCTw== 1432 | dependencies: 1433 | lodash "^4.17.15" 1434 | quibble "^0.5.7" 1435 | stringify-object-es5 "^2.5.0" 1436 | theredoc "^1.0.0" 1437 | 1438 | theredoc@^1.0.0: 1439 | version "1.0.0" 1440 | resolved "https://registry.yarnpkg.com/theredoc/-/theredoc-1.0.0.tgz#bcace376af6feb1873efbdd0f91ed026570ff062" 1441 | 1442 | to-fast-properties@^2.0.0: 1443 | version "2.0.0" 1444 | resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" 1445 | 1446 | to-regex-range@^5.0.1: 1447 | version "5.0.1" 1448 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 1449 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1450 | dependencies: 1451 | is-number "^7.0.0" 1452 | 1453 | ts-node@^9.0.0: 1454 | version "9.0.0" 1455 | resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.0.0.tgz#e7699d2a110cc8c0d3b831715e417688683460b3" 1456 | integrity sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg== 1457 | dependencies: 1458 | arg "^4.1.0" 1459 | diff "^4.0.1" 1460 | make-error "^1.1.1" 1461 | source-map-support "^0.5.17" 1462 | yn "3.1.1" 1463 | 1464 | tslib@^1.13.0: 1465 | version "1.14.1" 1466 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" 1467 | integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== 1468 | 1469 | tslib@^1.8.1: 1470 | version "1.9.3" 1471 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" 1472 | 1473 | tslint@^6.1.3: 1474 | version "6.1.3" 1475 | resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904" 1476 | integrity sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg== 1477 | dependencies: 1478 | "@babel/code-frame" "^7.0.0" 1479 | builtin-modules "^1.1.1" 1480 | chalk "^2.3.0" 1481 | commander "^2.12.1" 1482 | diff "^4.0.1" 1483 | glob "^7.1.1" 1484 | js-yaml "^3.13.1" 1485 | minimatch "^3.0.4" 1486 | mkdirp "^0.5.3" 1487 | resolve "^1.3.2" 1488 | semver "^5.3.0" 1489 | tslib "^1.13.0" 1490 | tsutils "^2.29.0" 1491 | 1492 | tsutils@^2.29.0: 1493 | version "2.29.0" 1494 | resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" 1495 | integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== 1496 | dependencies: 1497 | tslib "^1.8.1" 1498 | 1499 | type-fest@^0.8.0: 1500 | version "0.8.1" 1501 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" 1502 | integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== 1503 | 1504 | typedarray-to-buffer@^3.1.5: 1505 | version "3.1.5" 1506 | resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" 1507 | integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== 1508 | dependencies: 1509 | is-typedarray "^1.0.0" 1510 | 1511 | typescript@^4.1.2: 1512 | version "4.1.2" 1513 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.2.tgz#6369ef22516fe5e10304aae5a5c4862db55380e9" 1514 | integrity sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ== 1515 | 1516 | uuid@^3.3.3: 1517 | version "3.3.3" 1518 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" 1519 | integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== 1520 | 1521 | vscode-test@^0.4.1: 1522 | version "0.4.3" 1523 | resolved "https://registry.yarnpkg.com/vscode-test/-/vscode-test-0.4.3.tgz#461ebf25fc4bc93d77d982aed556658a2e2b90b8" 1524 | integrity sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w== 1525 | dependencies: 1526 | http-proxy-agent "^2.1.0" 1527 | https-proxy-agent "^2.2.1" 1528 | 1529 | vscode@^1.1.37: 1530 | version "1.1.37" 1531 | resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.37.tgz#c2a770bee4bb3fff765e2b72c7bcc813b8a6bb0a" 1532 | integrity sha512-vJNj6IlN7IJPdMavlQa1KoFB3Ihn06q1AiN3ZFI/HfzPNzbKZWPPuiU+XkpNOfGU5k15m4r80nxNPlM7wcc0wg== 1533 | dependencies: 1534 | glob "^7.1.2" 1535 | http-proxy-agent "^4.0.1" 1536 | https-proxy-agent "^5.0.0" 1537 | mocha "^5.2.0" 1538 | semver "^5.4.1" 1539 | source-map-support "^0.5.0" 1540 | vscode-test "^0.4.1" 1541 | 1542 | which-module@^2.0.0: 1543 | version "2.0.0" 1544 | resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" 1545 | 1546 | which@2.0.2, which@^2.0.1: 1547 | version "2.0.2" 1548 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 1549 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 1550 | dependencies: 1551 | isexe "^2.0.0" 1552 | 1553 | wide-align@1.1.3: 1554 | version "1.1.3" 1555 | resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" 1556 | integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== 1557 | dependencies: 1558 | string-width "^1.0.2 || 2" 1559 | 1560 | workerpool@6.0.2: 1561 | version "6.0.2" 1562 | resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.0.2.tgz#e241b43d8d033f1beb52c7851069456039d1d438" 1563 | integrity sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q== 1564 | 1565 | wrap-ansi@^5.1.0: 1566 | version "5.1.0" 1567 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" 1568 | integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== 1569 | dependencies: 1570 | ansi-styles "^3.2.0" 1571 | string-width "^3.0.0" 1572 | strip-ansi "^5.0.0" 1573 | 1574 | wrap-ansi@^6.2.0: 1575 | version "6.2.0" 1576 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" 1577 | integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== 1578 | dependencies: 1579 | ansi-styles "^4.0.0" 1580 | string-width "^4.1.0" 1581 | strip-ansi "^6.0.0" 1582 | 1583 | wrappy@1: 1584 | version "1.0.2" 1585 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1586 | 1587 | write-file-atomic@^3.0.0: 1588 | version "3.0.1" 1589 | resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.1.tgz#558328352e673b5bb192cf86500d60b230667d4b" 1590 | integrity sha512-JPStrIyyVJ6oCSz/691fAjFtefZ6q+fP6tm+OS4Qw6o+TGQxNp1ziY2PgS+X/m0V8OWhZiO/m4xSj+Pr4RrZvw== 1591 | dependencies: 1592 | imurmurhash "^0.1.4" 1593 | is-typedarray "^1.0.0" 1594 | signal-exit "^3.0.2" 1595 | typedarray-to-buffer "^3.1.5" 1596 | 1597 | y18n@^4.0.0: 1598 | version "4.0.1" 1599 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" 1600 | integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== 1601 | 1602 | yargs-parser@13.1.2, yargs-parser@^13.1.2: 1603 | version "13.1.2" 1604 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" 1605 | integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== 1606 | dependencies: 1607 | camelcase "^5.0.0" 1608 | decamelize "^1.2.0" 1609 | 1610 | yargs-parser@^16.1.0: 1611 | version "16.1.0" 1612 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-16.1.0.tgz#73747d53ae187e7b8dbe333f95714c76ea00ecf1" 1613 | integrity sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg== 1614 | dependencies: 1615 | camelcase "^5.0.0" 1616 | decamelize "^1.2.0" 1617 | 1618 | yargs-unparser@2.0.0: 1619 | version "2.0.0" 1620 | resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" 1621 | integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== 1622 | dependencies: 1623 | camelcase "^6.0.0" 1624 | decamelize "^4.0.0" 1625 | flat "^5.0.2" 1626 | is-plain-obj "^2.1.0" 1627 | 1628 | yargs@13.3.2: 1629 | version "13.3.2" 1630 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" 1631 | integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== 1632 | dependencies: 1633 | cliui "^5.0.0" 1634 | find-up "^3.0.0" 1635 | get-caller-file "^2.0.1" 1636 | require-directory "^2.1.1" 1637 | require-main-filename "^2.0.0" 1638 | set-blocking "^2.0.0" 1639 | string-width "^3.0.0" 1640 | which-module "^2.0.0" 1641 | y18n "^4.0.0" 1642 | yargs-parser "^13.1.2" 1643 | 1644 | yargs@^15.0.2: 1645 | version "15.0.2" 1646 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.0.2.tgz#4248bf218ef050385c4f7e14ebdf425653d13bd3" 1647 | integrity sha512-GH/X/hYt+x5hOat4LMnCqMd8r5Cv78heOMIJn1hr7QPPBqfeC6p89Y78+WB9yGDvfpCvgasfmWLzNzEioOUD9Q== 1648 | dependencies: 1649 | cliui "^6.0.0" 1650 | decamelize "^1.2.0" 1651 | find-up "^4.1.0" 1652 | get-caller-file "^2.0.1" 1653 | require-directory "^2.1.1" 1654 | require-main-filename "^2.0.0" 1655 | set-blocking "^2.0.0" 1656 | string-width "^4.2.0" 1657 | which-module "^2.0.0" 1658 | y18n "^4.0.0" 1659 | yargs-parser "^16.1.0" 1660 | 1661 | yn@3.1.1: 1662 | version "3.1.1" 1663 | resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" 1664 | integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== 1665 | 1666 | yocto-queue@^0.1.0: 1667 | version "0.1.0" 1668 | resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" 1669 | integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== 1670 | --------------------------------------------------------------------------------