├── .github └── workflows │ ├── CODEOWNERS │ └── ci.yml ├── .gitignore ├── .replit ├── CHANGELOG.md ├── LICENSE ├── README.md ├── dev ├── cm5 │ ├── .gitignore │ ├── bin │ │ └── build.js │ ├── index.html │ ├── index.js │ ├── package.json │ └── test │ │ └── webtest-cm5.js ├── index.html ├── index.ts ├── test.html ├── vite.config.js └── web-demo.html ├── package.json ├── pull_request_template.md ├── replit.nix ├── scripts ├── addVersion.cjs └── build-test-package.sh ├── src ├── block-cursor.ts ├── cm_adapter.ts ├── index.ts ├── types.ts └── vim.js ├── test ├── vim_test.js └── webtest-vim.js ├── tsconfig.json └── yarn.lock /.github/workflows/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @replit/workspace nightwing 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: main 2 | on: 3 | push: 4 | branches: [ master ] 5 | pull_request: 6 | branches: [ master ] 7 | jobs: 8 | build-and-test: 9 | runs-on: ubuntu-latest 10 | name: Build and test 11 | steps: 12 | - uses: styfle/cancel-workflow-action@0.6.0 13 | with: 14 | access_token: ${{ github.token }} 15 | 16 | - uses: actions/checkout@v1 17 | 18 | - uses: actions/setup-node@v2 19 | with: 20 | node-version: 18 21 | 22 | - run: yarn install 23 | - run: cd ./dev/cm5 && yarn install 24 | - run: yarn run build 25 | - run: yarn run testAll 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | dist 4 | out 5 | /test/*.js 6 | /test/*.d.ts 7 | /test/*.d.ts.map 8 | .* 9 | .DS_Store -------------------------------------------------------------------------------- /.replit: -------------------------------------------------------------------------------- 1 | run="yarn run dev" 2 | 3 | [packager] 4 | language = "nodejs-yarn" 5 | [packager.features] 6 | packageSearch = true 7 | guessImports = false 8 | 9 | [languages.js] 10 | pattern = "**/*.ts" 11 | [languages.js.languageServer] 12 | start = ["typescript-language-server", "--stdio"] -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/replit/codemirror-vim/71919db3d4466d487d53aae551ab035a490dd75a/CHANGELOG.md -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2018-2021 by Marijn Haverbeke and others 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vim keybindings for CM6 2 | 3 | Run on Replit badge 4 | NPM version badge 5 | 6 | ## Installation 7 | 8 | ```sh 9 | npm i @replit/codemirror-vim 10 | ``` 11 | 12 | ## Usage 13 | 14 | ```js 15 | import { basicSetup, EditorView } from 'codemirror'; 16 | import { vim } from "@replit/codemirror-vim" 17 | 18 | let view = new EditorView({ 19 | doc: "", 20 | extensions: [ 21 | // make sure vim is included before other keymaps 22 | vim(), 23 | // include the default keymap and all other keymaps you want to use in insert mode 24 | basicSetup, 25 | ], 26 | parent: document.querySelector('#editor'), 27 | }) 28 | ``` 29 | > **Note**: 30 | > if you are not using `basicSetup`, make sure you include the [drawSelection](https://codemirror.net/docs/ref/#view.drawSelection) plugin to correctly render the selection in visual mode. 31 | 32 | ## Usage of cm5 vim extension api 33 | 34 | The same api that could be used in previous version of codemirror https://codemirror.net/doc/manual.html#vimapi, can be used with this plugin too, just replace the old editor instance with `view.cm` in your code 35 | 36 | ```js 37 | import {Vim, getCM} from "@replit/codemirror-vim" 38 | 39 | let cm = getCM(view) 40 | // use cm to access the old cm5 api 41 | Vim.exitInsertMode(cm) 42 | Vim.handleKey(cm, "") 43 | ``` 44 | 45 | ### Define additional ex commands 46 | ```js 47 | Vim.defineEx('write', 'w', function() { 48 | // save the file 49 | }); 50 | ``` 51 | 52 | ### Map keys 53 | ```js 54 | Vim.map("jj", "", "insert"); // in insert mode 55 | Vim.map("Y", "y$"); // in normal mode 56 | ``` 57 | 58 | ### Unmap keys 59 | 60 | ```js 61 | Vim.unmap("jj", "insert"); 62 | ``` 63 | 64 | ### Add custom key 65 | 66 | ```js 67 | defaultKeymap.push({ keys: 'gq', type: 'operator', operator: 'hardWrap' }); 68 | Vim.defineOperator("hardWrap", function(cm, operatorArgs, ranges, oldAnchor, newHead) { 69 | // make changes and return new cursor position 70 | }); 71 | ``` 72 | 73 | ## Credits 74 | 75 | This plugin was originally authored by [@mightyguava](https://github.com/mightyguava) (Yunchi Luo) as part of [CodeMirror](https://github.com/codemirror/dev), before being extracted and maintained here. 76 | -------------------------------------------------------------------------------- /dev/cm5/.gitignore: -------------------------------------------------------------------------------- 1 | vim.js 2 | vim_test.js 3 | .* -------------------------------------------------------------------------------- /dev/cm5/bin/build.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"); 2 | var { rollup } = require('rollup'); 3 | 4 | rollup({ 5 | input: "./index" 6 | }).then(function(a) { 7 | return a.write({ 8 | file: "./bin/.bundle.js", 9 | format: "es", 10 | }); 11 | }).then(function(a) { 12 | var bundle = fs.readFileSync("./bin/.bundle.js", "utf8"); 13 | bundle = bundle.replace(/export {\s*initVim\s*};?/, ""); 14 | 15 | bundle = `(function(mod) { 16 | if (typeof exports == "object" && typeof module == "object") // CommonJS 17 | mod(require("../lib/codemirror"), require("../addon/search/searchcursor"), require("../addon/dialog/dialog"), require("../addon/edit/matchbrackets.js")); 18 | else if (typeof define == "function" && define.amd) // AMD 19 | define(["../lib/codemirror", "../addon/search/searchcursor", "../addon/dialog/dialog", "../addon/edit/matchbrackets"], mod); 20 | else // Plain browser env 21 | mod(CodeMirror); 22 | })(function(CodeMirror) { 23 | 'use strict'; 24 | ` 25 | + bundle + 26 | ` 27 | CodeMirror.Vim = initVim(CodeMirror); 28 | }); 29 | `; 30 | 31 | fs.writeFileSync("vim.js", bundle, "utf8"); 32 | }); 33 | 34 | 35 | var test = fs.readFileSync("../../test/vim_test.js", "utf8"); 36 | test = test.replace(/export function/, "function") + "\nvimTests(CodeMirror, test);"; 37 | fs.writeFileSync("vim_test.js", test, "utf8"); 38 | 39 | // update version 40 | var version = require("../../../package.json").version; 41 | var package = require("../package.json"); 42 | package.version = version; 43 | fs.writeFileSync("./package.json", JSON.stringify(package, null, 2), "utf8"); 44 | -------------------------------------------------------------------------------- /dev/cm5/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | CodeMirror 5: Vim bindings demo 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 43 | 44 |

Vim bindings for CodeMirror 5 demo

45 | 46 |
61 |
Key buffer:
62 |
Vim mode:
63 | 64 | 97 | 98 |
99 | 100 | 101 |
102 |
103 |
104 |
105 | 106 | 108 | 109 | -------------------------------------------------------------------------------- /dev/cm5/index.js: -------------------------------------------------------------------------------- 1 | import { initVim as initVimInternal } from "../../src/vim.js"; 2 | 3 | export function initVim(CodeMirror) { 4 | var Vim = CodeMirror.Vim = initVimInternal(CodeMirror); 5 | var Pos = CodeMirror.Pos; 6 | 7 | function transformCursor(cm, range) { 8 | var vim = cm.state.vim; 9 | if (!vim || vim.insertMode) return range.head; 10 | var head = vim.sel.head; 11 | if (!head) return range.head; 12 | 13 | if (vim.visualBlock) { 14 | if (range.head.line != head.line) { 15 | return; 16 | } 17 | } 18 | if (range.from() == range.anchor && !range.empty()) { 19 | if (range.head.line == head.line && range.head.ch != head.ch) 20 | return new Pos(range.head.line, range.head.ch - 1); 21 | } 22 | 23 | return range.head; 24 | } 25 | 26 | CodeMirror.keyMap['vim-insert'] = { 27 | // TODO: override navigation keys so that Esc will cancel automatic 28 | // indentation from o, O, i_ 29 | fallthrough: ['default'], 30 | attach: attachVimMap, 31 | detach: detachVimMap, 32 | call: cmKey 33 | }; 34 | 35 | CodeMirror.keyMap['vim-replace'] = { 36 | 'Backspace': 'goCharLeft', 37 | fallthrough: ['vim-insert'], 38 | attach: attachVimMap, 39 | detach: detachVimMap 40 | }; 41 | 42 | 43 | CodeMirror.keyMap.vim = { 44 | attach: attachVimMap, 45 | detach: detachVimMap, 46 | call: cmKey 47 | }; 48 | 49 | // Deprecated, simply setting the keymap works again. 50 | CodeMirror.defineOption('vimMode', false, function(cm, val, prev) { 51 | if (val && cm.getOption("keyMap") != "vim") 52 | cm.setOption("keyMap", "vim"); 53 | else if (!val && prev != CodeMirror.Init && /^vim/.test(cm.getOption("keyMap"))) 54 | cm.setOption("keyMap", "default"); 55 | }); 56 | 57 | function cmKey(key, cm) { 58 | if (!cm) { return undefined; } 59 | if (this[key]) { return this[key]; } 60 | var vimKey = cmKeyToVimKey(key); 61 | if (!vimKey) { 62 | return false; 63 | } 64 | var cmd = Vim.findKey(cm, vimKey); 65 | if (typeof cmd == 'function') { 66 | CodeMirror.signal(cm, 'vim-keypress', vimKey); 67 | } 68 | return cmd; 69 | } 70 | 71 | var modifiers = {Shift:'S',Ctrl:'C',Alt:'A',Cmd:'D',Mod:'A',CapsLock:''}; 72 | var specialKeys = {Enter:'CR',Backspace:'BS',Delete:'Del',Insert:'Ins'}; 73 | 74 | function cmKeyToVimKey(key) { 75 | if (key.charAt(0) == '\'') { 76 | // Keypress character binding of format "'a'" 77 | return key.charAt(1); 78 | } 79 | var pieces = key.split(/-(?!$)/); 80 | var lastPiece = pieces[pieces.length - 1]; 81 | if (pieces.length == 1 && pieces[0].length == 1) { 82 | // No-modifier bindings use literal character bindings above. Skip. 83 | return false; 84 | } else if (pieces.length == 2 && pieces[0] == 'Shift' && lastPiece.length == 1) { 85 | // Ignore Shift+char bindings as they should be handled by literal character. 86 | return false; 87 | } 88 | var hasCharacter = false; 89 | for (var i = 0; i < pieces.length; i++) { 90 | var piece = pieces[i]; 91 | if (piece in modifiers) { pieces[i] = modifiers[piece]; } 92 | else { hasCharacter = true; } 93 | if (piece in specialKeys) { pieces[i] = specialKeys[piece]; } 94 | } 95 | if (!hasCharacter) { 96 | // Vim does not support modifier only keys. 97 | return false; 98 | } 99 | // TODO: Current bindings expect the character to be lower case, but 100 | // it looks like vim key notation uses upper case. 101 | if (/^[A-Z]$/.test(lastPiece)) 102 | pieces[pieces.length - 1] = lastPiece.toLowerCase(); 103 | 104 | return '<' + pieces.join('-') + '>'; 105 | } 106 | 107 | function detachVimMap(cm, next) { 108 | if (this == CodeMirror.keyMap.vim) { 109 | cm.options.$customCursor = null; 110 | CodeMirror.rmClass(cm.getWrapperElement(), "cm-fat-cursor"); 111 | } 112 | 113 | if (!next || next.attach != attachVimMap) 114 | Vim.leaveVimMode(cm); 115 | } 116 | function attachVimMap(cm, prev) { 117 | if (this == CodeMirror.keyMap.vim) { 118 | if (cm.curOp) cm.curOp.selectionChanged = true; 119 | cm.options.$customCursor = transformCursor; 120 | CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor"); 121 | } 122 | 123 | if (!prev || prev.attach != attachVimMap) 124 | Vim.enterVimMode(cm); 125 | } 126 | 127 | return CodeMirror.Vim; 128 | } 129 | -------------------------------------------------------------------------------- /dev/cm5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cm5-vim", 3 | "version": "0.0.6", 4 | "description": "Vim keybindings for CodeMirror 5", 5 | "files": [ 6 | "vim.js", 7 | "vim_test.js" 8 | ], 9 | "scripts": { 10 | "test": "cm-runtests .", 11 | "build": "node bin/build.js", 12 | "buildAndTest": "yarn run build && yarn test", 13 | "publish": "yarn run build && npm publish" 14 | }, 15 | "keywords": [ 16 | "editor", 17 | "code" 18 | ], 19 | "main": "vim.js", 20 | "sideEffects": false, 21 | "license": "MIT", 22 | "devDependencies": { 23 | "codemirror": "5.*" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "https://github.com/replit/codemirror-vim.git" 28 | } 29 | } -------------------------------------------------------------------------------- /dev/cm5/test/webtest-cm5.js: -------------------------------------------------------------------------------- 1 | import { vimTests } from "../../../test/vim_test.js" 2 | import "codemirror/lib/codemirror.js" 3 | import "codemirror/addon/dialog/dialog.js" 4 | import "codemirror/addon/search/searchcursor.js" 5 | import "codemirror/addon/edit/matchbrackets.js" 6 | import "codemirror/addon/fold/foldcode.js" 7 | import "codemirror/addon/fold/xml-fold.js" 8 | import "codemirror/addon/fold/brace-fold.js" 9 | import "codemirror/addon/mode/simple.js" 10 | import "codemirror/mode/css/css.js" 11 | import "codemirror/mode/clike/clike.js" 12 | import "codemirror/mode/xml/xml.js" 13 | 14 | import "../vim.js" 15 | function addStyleSheet(href) { 16 | var link = document.createElement("link") 17 | link.rel = "stylesheet" 18 | link.href = "/cm5/node_modules/codemirror/" + href 19 | document.body.appendChild(link); 20 | } 21 | ;[ 22 | "lib/codemirror.css", 23 | "addon/dialog/dialog.css", 24 | "addon/fold/foldgutter.css" 25 | ].forEach(addStyleSheet) 26 | 27 | 28 | 29 | var disabled = {}; 30 | 31 | describe("Vim CM5", () => { 32 | var onlyType, lastView 33 | 34 | function transformTest(name, fn) { 35 | if (disabled[name]) { 36 | return it.skip(name, function () { }); 37 | } 38 | 39 | if (onlyType && localStorage[name] && localStorage[name] !== onlyType) 40 | return; 41 | return it(name, function () { 42 | var oldContainer = document.getElementById("testground"); 43 | if (oldContainer) oldContainer.remove(); 44 | var container = document.createElement("div"); 45 | document.body.appendChild(container); 46 | container.id = "testground"; 47 | 48 | if (onlyType) localStorage[name] = "fail"; 49 | fn(); 50 | if (onlyType) localStorage[name] = "pass"; 51 | if (lastView) { 52 | // TODO without calling destroy old cm instances throw errors and break the test runner 53 | lastView.destroy(); 54 | lastView = null; 55 | } 56 | }); 57 | } 58 | vimTests(CodeMirror, transformTest); 59 | }); 60 | -------------------------------------------------------------------------------- /dev/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vite App 7 | 15 | 16 | 17 |
18 |
19 | 20 |
21 | tests |  22 | cm5 demo 23 | 24 | 25 | -------------------------------------------------------------------------------- /dev/index.ts: -------------------------------------------------------------------------------- 1 | import { basicSetup, EditorView } from 'codemirror' 2 | import { highlightActiveLine, keymap, Decoration, DecorationSet, 3 | ViewPlugin, ViewUpdate, WidgetType, drawSelection } from '@codemirror/view'; 4 | import { javascript } from '@codemirror/lang-javascript'; 5 | import { xml } from '@codemirror/lang-xml'; 6 | import { Vim, vim } from "../src/index" // "@replit/codemirror-vim" 7 | 8 | import * as commands from "@codemirror/commands"; 9 | import { Annotation, Compartment, EditorState, Extension, Transaction, Range } from '@codemirror/state'; 10 | 11 | const doc = `//\t🌞 אבג 12 | import { basicSetup, EditorView } from 'codemirror' 13 | import { javascript } from '@codemirror/lang-javascript'; 14 | import { vim } from "../src/" 15 | 16 | const doc = \` 17 | console.log('hi') 18 | \` 19 | 20 | new EditorView({ 21 | doc, 22 | extensions: [vim(), basicSetup, javascript()], 23 | parent: document.querySelector('#editor'), 24 | }); 25 | 26 | `; 27 | 28 | function addOption(name: "wrap"|"html"|"status"|"jj"|"split"|"readOnly", 29 | description?: string, onclick?: (value: boolean) => void) { 30 | let checkbox = document.createElement("input"); 31 | checkbox.type = "checkbox"; 32 | checkbox.id = name; 33 | let label = document.createElement("label"); 34 | label.setAttribute("for", name); 35 | label.textContent = description || name; 36 | 37 | let value = localStorage[name] == "true" 38 | checkbox.checked = value; 39 | checkbox.onclick = function() { 40 | options[name] = checkbox.checked; 41 | updateView(); 42 | if (onclick) onclick(options[name]) 43 | localStorage[name] = checkbox.checked; 44 | } 45 | document.getElementById("toolbar")?.append(checkbox, label, " ") 46 | return value 47 | } 48 | 49 | class TestWidget extends WidgetType { 50 | constructor(private side: number) { 51 | super(); 52 | } 53 | override eq(other: TestWidget) { 54 | return other == this; 55 | } 56 | toDOM() { 57 | const wrapper = document.createElement('span'); 58 | wrapper.textContent = " widget" + this.side + " " 59 | wrapper.style.opacity = '0.4'; 60 | return wrapper; 61 | } 62 | override ignoreEvent() { 63 | return false; 64 | } 65 | } 66 | 67 | function widgets(view: EditorView) { 68 | let widgets: Range[] = []; 69 | for (let i = 0; i < 10; i++) { 70 | let side = widgets.length % 2 ? 1 : -1 71 | let deco = Decoration.widget({ 72 | widget: new TestWidget(side), 73 | side: side 74 | }) 75 | widgets.push(deco.range(200 + 10 * i)) 76 | } 77 | console.log(widgets, view) 78 | return Decoration.set(widgets) 79 | } 80 | 81 | const testWidgetPlugin = ViewPlugin.fromClass(class { 82 | decorations: DecorationSet 83 | 84 | constructor(view: EditorView) { 85 | this.decorations = widgets(view) 86 | } 87 | 88 | update(update: ViewUpdate) { 89 | if (update.docChanged || update.viewportChanged) 90 | this.decorations = widgets(update.view) 91 | } 92 | }, { 93 | decorations: v => v.decorations, 94 | 95 | eventHandlers: { 96 | mousedown: (e, view) => { 97 | console.log("mousedown", e, view) 98 | } 99 | } 100 | }) 101 | 102 | if (!localStorage.status) localStorage.status = "true"; 103 | var options = { 104 | wrap: addOption("wrap"), 105 | html: addOption("html"), 106 | status: addOption("status", "status bar"), 107 | jj: addOption("jj", "map jj to Esc", function(on) { 108 | if (on) 109 | Vim.map("jj", "", "insert"); 110 | else 111 | Vim.unmap("jj", "insert") 112 | }), 113 | split: addOption("split", "", function() { 114 | 115 | }), 116 | readOnly: addOption("readOnly") 117 | }; 118 | 119 | 120 | 121 | Vim.defineOption('wrap', false, 'boolean', null, function(val, cm) { 122 | if (!cm) console.log("should set global option"); 123 | if (val == undefined) return options.wrap; 124 | var checkbox = document.getElementById("wrap") as HTMLInputElement; 125 | if (checkbox) { 126 | checkbox.checked = val; 127 | //@ts-ignore 128 | checkbox.onclick(); 129 | } 130 | }); 131 | 132 | var focusEditorButton = document.createElement("button"); 133 | focusEditorButton.onclick = function(e) { 134 | e.preventDefault(); 135 | view?.focus(); 136 | } 137 | focusEditorButton.textContent = "focusEditor"; 138 | focusEditorButton.onmousedown = function(e) { 139 | e.preventDefault(); 140 | } 141 | document.getElementById("toolbar")?.append(focusEditorButton," ") 142 | 143 | 144 | let global = window as any; 145 | global._commands = commands; 146 | global._Vim = Vim; 147 | 148 | let container = document.querySelector('#editor')!; 149 | let view: EditorView|undefined, view2: EditorView|undefined; 150 | let enableVim = true; 151 | let vimCompartement = new Compartment(); 152 | 153 | var defaultExtensions = [ 154 | // make sure vim is included before all other keymaps 155 | vimCompartement.of([ 156 | vim({status: true}), 157 | ]), 158 | // include the default keymap and all other keymaps you want to use in insert mode 159 | basicSetup, 160 | highlightActiveLine(), 161 | keymap.of([ 162 | { 163 | key: "Alt-v", 164 | run: () => { 165 | enableVim = !enableVim 166 | updateView() 167 | return true 168 | } 169 | } 170 | ]), 171 | ] 172 | 173 | function saveTab(name: string) { 174 | return EditorView.updateListener.of((v) => { 175 | tabs[name] = v.state; 176 | }) 177 | } 178 | 179 | 180 | var tabs: Record = { 181 | js: EditorState.create({ 182 | doc: doc, 183 | extensions: [...defaultExtensions, javascript(), saveTab("js")] 184 | }), 185 | html: EditorState.create({ 186 | doc: document.documentElement.outerHTML, 187 | extensions: [...defaultExtensions, testWidgetPlugin, xml(), saveTab("html")] 188 | }), 189 | } 190 | 191 | function updateView() { 192 | if (options.split && !view2) createSplit(); 193 | if (!options.split && view2) deleteSplit(); 194 | 195 | if (!view) view = createView(); 196 | addLogListeners(); 197 | 198 | selectTab(options.html ? "html": "js") 199 | 200 | var extensions = [ 201 | EditorState.readOnly.of(options.readOnly), 202 | enableVim && vim({status: options.status}), 203 | options.wrap && EditorView.lineWrapping, 204 | drawSelection({cursorBlinkRate: window.blinkRate}) 205 | ].filter((x)=>!!x) as Extension[]; 206 | 207 | view.dispatch({ 208 | effects: vimCompartement.reconfigure(extensions) 209 | }) 210 | } 211 | 212 | declare global { 213 | interface Window { 214 | blinkRate?: number; 215 | } 216 | } 217 | 218 | function selectTab(tab: string) { 219 | let state = tabs[tab]; 220 | if (!state) return; 221 | if (view) view.setState(state) 222 | if (view2) view2.setState(state) 223 | addLogListeners(); 224 | } 225 | 226 | Vim.defineEx("tabnext", "tabn", () => { 227 | tabs.scratch = EditorState.create({ 228 | doc: "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", 229 | extensions: [defaultExtensions, saveTab("scratch")], 230 | }); 231 | selectTab("scratch") 232 | }); 233 | 234 | 235 | 236 | Vim.defineEx("split", "sp", () => { 237 | options.split = !options.split; 238 | updateView(); 239 | }); 240 | 241 | 242 | 243 | // splitting 244 | let syncAnnotation = Annotation.define() 245 | 246 | function syncDispatch(tr: Transaction, view: EditorView, other: EditorView) { 247 | view.update([tr]) 248 | if (!tr.changes.empty && !tr.annotation(syncAnnotation)) { 249 | let annotations: Annotation[] = [syncAnnotation.of(true)] 250 | let userEvent = tr.annotation(Transaction.userEvent) 251 | if (userEvent) annotations.push(Transaction.userEvent.of(userEvent)) 252 | other.dispatch({changes: tr.changes, annotations}) 253 | } 254 | } 255 | 256 | 257 | function createSplit() { 258 | deleteSplit(); 259 | 260 | view = global._view = new EditorView({ 261 | doc: "", 262 | extensions: defaultExtensions, 263 | parent: container, 264 | dispatch: tr => syncDispatch(tr, view!, view2!) 265 | }); 266 | view2 = global._view2 = new EditorView({ 267 | doc: "", 268 | extensions: defaultExtensions, 269 | parent: container, 270 | dispatch: tr => syncDispatch(tr, view2!, view!) 271 | }); 272 | 273 | container.classList.add("split") 274 | } 275 | 276 | function deleteSplit() { 277 | if (view) view.destroy(); 278 | if (view2) view2.destroy(); 279 | view = view2 = undefined; 280 | container.classList.remove("split"); 281 | } 282 | 283 | function createView() { 284 | if (view) view.destroy(); 285 | view = global._view = new EditorView({ 286 | doc: "", 287 | extensions: defaultExtensions, 288 | parent: container, 289 | }); 290 | return view; 291 | } 292 | 293 | function addLogListeners() { 294 | var cm = (view as any)?.cm; 295 | if (cm) { 296 | cm.off("inputEvent", logHandler); 297 | cm.on("inputEvent", logHandler); 298 | } 299 | } 300 | var i = 0; 301 | function logHandler(e: any) { 302 | var message = [i++, e.type.padEnd(10), e.key, e.code].join(" "); 303 | var entry = logContainer.childNodes.length < 1000 304 | ? document.createElement("div") 305 | : logContainer.lastChild! as HTMLElement; 306 | entry.textContent = message 307 | logContainer.insertBefore(entry, logContainer.firstChild); 308 | } 309 | var logContainer = document.createElement("pre"); 310 | document.body.appendChild(logContainer); 311 | logContainer.className = ".logContainer" 312 | 313 | 314 | 315 | updateView() 316 | 317 | // save and restor search history 318 | 319 | 320 | function saveHistory(name: "exCommandHistoryController"|"searchHistoryController") { 321 | var controller = Vim.getVimGlobalState_()[name]; 322 | var json = JSON.stringify(controller); 323 | if (json.length > 10000) { 324 | var toTrim = JSON.parse(json); 325 | toTrim.historyBuffer = toTrim.historyBuffer.slice(toTrim.historyBuffer.lenght/2); 326 | toTrim.iterator = toTrim.historyBuffer.lenght; 327 | json = JSON.stringify(toTrim); 328 | } 329 | localStorage[name] = json; 330 | } 331 | function restoreHistory(name: "exCommandHistoryController"|"searchHistoryController") { 332 | try { 333 | var json = JSON.parse(localStorage[name]); 334 | var controller = Vim.getVimGlobalState_()[name]; 335 | controller.historyBuffer = json.historyBuffer.filter((x: unknown) => typeof x == "string" && x) 336 | controller.iterator = Math.min(parseInt(json.iterator) || Infinity, controller.historyBuffer.length) 337 | } catch(e) { 338 | 339 | } 340 | } 341 | 342 | restoreHistory('exCommandHistoryController'); 343 | restoreHistory('searchHistoryController'); 344 | 345 | window.onunload = function() { 346 | saveHistory('exCommandHistoryController'); 347 | saveHistory('searchHistoryController'); 348 | } 349 | 350 | Vim.defineEx("write", "w", (cm) => { 351 | console.log("called", cm); 352 | }) -------------------------------------------------------------------------------- /dev/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | CodeMirror view tests 4 | 5 |

CodeMirror view tests

6 | 7 |
8 | 9 |
10 | 11 | 32 | -------------------------------------------------------------------------------- /dev/vite.config.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'url'; 2 | import * as path from 'path'; 3 | 4 | const filename = fileURLToPath(import.meta.url); 5 | const dirname = path.dirname(filename); 6 | 7 | const isReplit = Boolean(process.env.REPL_SLUG); 8 | 9 | export default { 10 | server: { 11 | host: '0.0.0.0', 12 | 13 | ...(isReplit 14 | ? { 15 | hmr: { 16 | clientPort: 443, 17 | }, 18 | } 19 | : {}), 20 | }, 21 | resolve: { 22 | alias: [{ find: /^..$/, replacement: dirname + '/../src/index.ts' }], 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /dev/web-demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 607 | 608 | 609 |
610 |
611 |
612 |
613 | tests
614 | cm5 demo 615 | 649 | 724 | 725 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@replit/codemirror-vim", 3 | "version": "6.3.0", 4 | "description": "Vim keybindings for CodeMirror 6", 5 | "author": { 6 | "name": "Yunchi Luo", 7 | "email": "mightyguava@gmail.com" 8 | }, 9 | "scripts": { 10 | "dev": "vite ./dev", 11 | "test": "cm-runtests", 12 | "build-types": "rm -rf out && tsc && dts-bundle-generator out/index.ts -o dist/index.d.ts && cp dist/index.d.ts dist/index.d.cts", 13 | "testAll": "yarn run build-test-package && yarn run test && cd dev/cm5 && yarn run buildAndTest", 14 | "build": "cm-buildhelper src/index.ts && node scripts/addVersion.cjs && npm run build-types", 15 | "publish": "yarn run build && npm publish", 16 | "build-test-package": "bash ./scripts/build-test-package.sh", 17 | "prepare": "yarn run build" 18 | }, 19 | "keywords": [ 20 | "editor", 21 | "code" 22 | ], 23 | "type": "module", 24 | "main": "dist/index.cjs", 25 | "exports": { 26 | "import": "./dist/index.js", 27 | "require": "./dist/index.cjs" 28 | }, 29 | "types": "dist/index.d.ts", 30 | "module": "dist/index.js", 31 | "sideEffects": false, 32 | "license": "MIT", 33 | "peerDependencies": { 34 | "@codemirror/commands": "6.x.x", 35 | "@codemirror/language": "6.x.x", 36 | "@codemirror/search": "6.x.x", 37 | "@codemirror/state": "6.x.x", 38 | "@codemirror/view": "6.x.x" 39 | }, 40 | "devDependencies": { 41 | "@codemirror/buildhelper": "^1.0.2", 42 | "@codemirror/lang-javascript": "6.x.x", 43 | "@codemirror/lang-xml": "6.x.x", 44 | "@codemirror/language": "6.x.x", 45 | "codemirror": "6.x.x", 46 | "dts-bundle-generator": "^9.5.1", 47 | "typescript": "^5.8.2", 48 | "vite": "^6.2.2" 49 | }, 50 | "files": [ 51 | "dist", 52 | "README.md" 53 | ], 54 | "repository": { 55 | "type": "git", 56 | "url": "https://github.com/replit/codemirror-vim.git" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Why 2 | 3 | 7 | 8 | # What changed 9 | 10 | 16 | 17 | # Test plan 18 | 19 | 24 | -------------------------------------------------------------------------------- /replit.nix: -------------------------------------------------------------------------------- 1 | { pkgs }: { 2 | deps = [ 3 | pkgs.nodejs-16_x 4 | pkgs.nodePackages.yarn 5 | pkgs.nodePackages.typescript-language-server 6 | pkgs.chromedriver 7 | pkgs.chromium 8 | ]; 9 | } -------------------------------------------------------------------------------- /scripts/addVersion.cjs: -------------------------------------------------------------------------------- 1 | var fs = require("fs") 2 | var json = fs.readFileSync(__dirname + "/../package.json", "utf-8") 3 | var version = JSON.parse(json).version 4 | 5 | console.log(version) 6 | function replace(path) { 7 | var value = fs.readFileSync(path, "utf-8") 8 | value = value.replace("", version); 9 | fs.writeFileSync(path, value , "utf-8") 10 | } 11 | 12 | replace(__dirname + "/../dist/index.js") 13 | replace(__dirname + "/../dist/index.cjs") -------------------------------------------------------------------------------- /scripts/build-test-package.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | # Navigate to the repository root 5 | cd "$(dirname "$0")/.." 6 | ROOT="$(pwd)" 7 | 8 | # npm pack the repository 9 | rm -f replit-codemirror-vim-*.tgz 10 | npm pack 11 | 12 | # Get the name of the packed file 13 | PACKAGE_FILE=$(ls replit-codemirror-vim-*.tgz | sort -V | tail -n 1) 14 | 15 | mv "$PACKAGE_FILE" replit-codemirror-vim-latest.tgz 16 | 17 | rm -rf ../.test_package 18 | mkdir -p ../.test_package 19 | cd ../.test_package 20 | 21 | cp "$ROOT"/dev/index.ts index.ts 22 | cp "$ROOT"/dev/index.html index.html 23 | node -e " 24 | const fs = require('fs'); 25 | const filePath = 'index.ts'; 26 | let data = fs.readFileSync(filePath, 'utf8'); 27 | data = data.replace(/\"..\/src\/index\" \/\//g, ''); 28 | fs.writeFileSync(filePath, data, 'utf8'); 29 | " 30 | 31 | echo '{ 32 | "name": "test_package", 33 | "scripts": { 34 | "build": "tsc", 35 | "test": "echo \"No tests yet\"" 36 | } 37 | }' > package.json 38 | 39 | echo ' 40 | import { defineConfig } from "vite"; 41 | export default defineConfig({ 42 | base: "", 43 | });' > vite.config.js 44 | 45 | echo '{ 46 | "compilerOptions": { 47 | "strict": true, 48 | "noImplicitAny": true, 49 | "strictNullChecks": true, 50 | "strictFunctionTypes": true, 51 | "strictBindCallApply": true, 52 | "strictPropertyInitialization": true, 53 | "noImplicitThis": true, 54 | "alwaysStrict": true, 55 | "noUnusedLocals": true, 56 | "noUnusedParameters": true, 57 | "noImplicitReturns": false, 58 | "noFallthroughCasesInSwitch": true, 59 | "noUncheckedIndexedAccess": true, 60 | "noImplicitOverride": true, 61 | "esModuleInterop": true, 62 | "forceConsistentCasingInFileNames": true, 63 | "module": "commonjs", 64 | "target": "es2020", 65 | "moduleResolution": "node" 66 | }, 67 | "include": ["*.ts"], 68 | "exclude": ["node_modules"] 69 | } 70 | ' > tsconfig.json 71 | 72 | # Install the ace package from the npm pack result 73 | npm i "$ROOT"/replit-codemirror-vim-latest.tgz 74 | npm i codemirror @codemirror/lang-javascript @codemirror/lang-xml 75 | 76 | # Install TypeScript 77 | npm i typescript@latest 78 | rm -f index.js 79 | npm run build 80 | 81 | # Install old version of TypeScript 82 | npm i typescript@4 83 | rm -f index.js 84 | npm run build 85 | -------------------------------------------------------------------------------- /src/block-cursor.ts: -------------------------------------------------------------------------------- 1 | import { SelectionRange, Prec } from "@codemirror/state" 2 | import { ViewUpdate, EditorView, Direction } from "@codemirror/view" 3 | import { CodeMirror } from "." 4 | 5 | import * as View from "@codemirror/view" 6 | // backwards compatibility for old versions not supporting getDrawSelectionConfig 7 | let getDrawSelectionConfig = View.getDrawSelectionConfig || function() { 8 | let defaultConfig = {cursorBlinkRate: 1200}; 9 | return function() { 10 | return defaultConfig; 11 | } 12 | }(); 13 | 14 | type Measure = {cursors: Piece[]} 15 | 16 | class Piece { 17 | constructor(readonly left: number, readonly top: number, 18 | readonly height: number, 19 | readonly fontFamily: string, 20 | readonly fontSize: string, 21 | readonly fontWeight: string, 22 | readonly color: string, 23 | readonly className: string, 24 | readonly letter: string, 25 | readonly partial: boolean) {} 26 | 27 | draw() { 28 | let elt = document.createElement("div") 29 | elt.className = this.className 30 | this.adjust(elt) 31 | return elt 32 | } 33 | 34 | adjust(elt: HTMLElement) { 35 | elt.style.left = this.left + "px" 36 | elt.style.top = this.top + "px" 37 | elt.style.height = this.height + "px" 38 | elt.style.lineHeight = this.height + "px" 39 | elt.style.fontFamily = this.fontFamily; 40 | elt.style.fontSize = this.fontSize; 41 | elt.style.fontWeight = this.fontWeight; 42 | elt.style.color = this.partial ? "transparent" : this.color; 43 | 44 | elt.className = this.className; 45 | elt.textContent = this.letter; 46 | } 47 | 48 | eq(p: Piece) { 49 | return this.left == p.left && this.top == p.top && this.height == p.height && 50 | this.fontFamily == p.fontFamily && this.fontSize == p.fontSize && 51 | this.fontWeight == p.fontWeight && this.color == p.color && 52 | this.className == p.className && 53 | this.letter == p.letter; 54 | } 55 | } 56 | 57 | export class BlockCursorPlugin { 58 | rangePieces: readonly Piece[] = [] 59 | cursors: readonly Piece[] = [] 60 | measureReq: {read: () => Measure, write: (value: Measure) => void} 61 | cursorLayer: HTMLElement 62 | cm: CodeMirror 63 | 64 | constructor(readonly view: EditorView, cm: CodeMirror) { 65 | this.cm = cm; 66 | this.measureReq = {read: this.readPos.bind(this), write: this.drawSel.bind(this)} 67 | this.cursorLayer = view.scrollDOM.appendChild(document.createElement("div")) 68 | this.cursorLayer.className = "cm-cursorLayer cm-vimCursorLayer" 69 | this.cursorLayer.setAttribute("aria-hidden", "true") 70 | view.requestMeasure(this.measureReq) 71 | this.setBlinkRate() 72 | } 73 | 74 | setBlinkRate() { 75 | let config = getDrawSelectionConfig(this.cm.cm6.state); 76 | let blinkRate = config.cursorBlinkRate; 77 | this.cursorLayer.style.animationDuration = blinkRate + "ms"; 78 | } 79 | 80 | update(update: ViewUpdate) { 81 | if (update.selectionSet || update.geometryChanged || update.viewportChanged) { 82 | this.view.requestMeasure(this.measureReq) 83 | this.cursorLayer.style.animationName = this.cursorLayer.style.animationName == "cm-blink" ? "cm-blink2" : "cm-blink" 84 | } 85 | if (configChanged(update)) this.setBlinkRate(); 86 | } 87 | 88 | scheduleRedraw() { 89 | this.view.requestMeasure(this.measureReq) 90 | } 91 | 92 | readPos(): Measure { 93 | let {state} = this.view 94 | let cursors: Piece[] = [] 95 | for (let r of state.selection.ranges) { 96 | let prim = r == state.selection.main 97 | let piece = measureCursor(this.cm, this.view, r, prim) 98 | if (piece) cursors.push(piece) 99 | } 100 | return {cursors} 101 | } 102 | 103 | drawSel({cursors}: Measure) { 104 | if (cursors.length != this.cursors.length || cursors.some((c, i) => !c.eq(this.cursors[i]))) { 105 | let oldCursors = this.cursorLayer.children 106 | if (oldCursors.length !== cursors.length) { 107 | this.cursorLayer.textContent = "" 108 | for (const c of cursors) 109 | this.cursorLayer.appendChild(c.draw()) 110 | } else { 111 | cursors.forEach((c, idx) => c.adjust(oldCursors[idx] as HTMLElement)) 112 | } 113 | this.cursors = cursors 114 | } 115 | } 116 | 117 | destroy() { 118 | this.cursorLayer.remove() 119 | } 120 | } 121 | function configChanged(update: ViewUpdate) { 122 | return getDrawSelectionConfig(update.startState) != getDrawSelectionConfig(update.state) 123 | } 124 | 125 | const themeSpec = { 126 | ".cm-vimMode .cm-line": { 127 | "& ::selection": {backgroundColor: "transparent !important"}, 128 | "&::selection": {backgroundColor: "transparent !important"}, 129 | caretColor: "transparent !important", 130 | }, 131 | ".cm-fat-cursor": { 132 | position: "absolute", 133 | background: "#ff9696", 134 | border: "none", 135 | whiteSpace: "pre", 136 | }, 137 | "&:not(.cm-focused) .cm-fat-cursor": { 138 | background: "none", 139 | outline: "solid 1px #ff9696", 140 | color: "transparent !important", 141 | }, 142 | } 143 | 144 | export const hideNativeSelection = Prec.highest(EditorView.theme(themeSpec)) 145 | 146 | function getBase(view: EditorView) { 147 | let rect = view.scrollDOM.getBoundingClientRect() 148 | let left = view.textDirection == Direction.LTR ? rect.left : rect.right - view.scrollDOM.clientWidth 149 | return {left: left - view.scrollDOM.scrollLeft * view.scaleX, top: rect.top - view.scrollDOM.scrollTop * view.scaleY} 150 | } 151 | 152 | function measureCursor(cm: CodeMirror, view: EditorView, cursor: SelectionRange, primary: boolean): Piece | null { 153 | let head = cursor.head; 154 | let fatCursor = false; 155 | let hCoeff = 1; 156 | let vim = cm.state.vim; 157 | if (vim && (!vim.insertMode || cm.state.overwrite)) { 158 | fatCursor = true; 159 | if (vim.visualBlock && !primary) 160 | return null; 161 | if (cursor.anchor < cursor.head) { 162 | let letter = head < view.state.doc.length && view.state.sliceDoc(head, head + 1); 163 | if (letter != "\n") 164 | head--; 165 | } 166 | if (cm.state.overwrite) hCoeff = 0.2; 167 | else if (vim.status) hCoeff = 0.5; 168 | } 169 | 170 | if (fatCursor) { 171 | let letter = head < view.state.doc.length && view.state.sliceDoc(head, head + 1); 172 | if (letter && (/[\uDC00-\uDFFF]/.test(letter) && head > 1)) { 173 | // step back if cursor is on the second half of a surrogate pair 174 | head--; 175 | letter = view.state.sliceDoc(head, head + 1); 176 | } 177 | let pos = view.coordsAtPos(head, 1); 178 | if (!pos) return null; 179 | let base = getBase(view); 180 | let domAtPos = view.domAtPos(head); 181 | let node = domAtPos ? domAtPos.node : view.contentDOM; 182 | if (node instanceof Text && domAtPos.offset >= node.data.length) { 183 | if (node.parentElement?.nextSibling) { 184 | node = node.parentElement?.nextSibling; 185 | domAtPos = {node: node, offset: 0}; 186 | }; 187 | } 188 | while (domAtPos && domAtPos.node instanceof HTMLElement) { 189 | node = domAtPos.node; 190 | domAtPos = {node: domAtPos.node.childNodes[domAtPos.offset], offset: 0}; 191 | } 192 | if (!(node instanceof HTMLElement)) { 193 | if (!node.parentNode) return null; 194 | node = node.parentNode; 195 | } 196 | let style = getComputedStyle(node as HTMLElement); 197 | let left = pos.left; 198 | // TODO remove coordsAtPos when all supported versions of codemirror have coordsForChar api 199 | let charCoords = (view as any).coordsForChar?.(head); 200 | if (charCoords) { 201 | left = charCoords.left; 202 | } 203 | if (!letter || letter == "\n" || letter == "\r") { 204 | letter = "\xa0"; 205 | } else if (letter == "\t") { 206 | letter = "\xa0"; 207 | var nextPos = view.coordsAtPos(head + 1, -1); 208 | if (nextPos) { 209 | left = nextPos.left - (nextPos.left - pos.left) / parseInt(style.tabSize); 210 | } 211 | } else if ((/[\uD800-\uDBFF]/.test(letter) && head < view.state.doc.length - 1)) { 212 | // include the second half of a surrogate pair in cursor 213 | letter += view.state.sliceDoc(head + 1, head + 2); 214 | } 215 | let h = (pos.bottom - pos.top); 216 | return new Piece((left - base.left)/view.scaleX, (pos.top - base.top + h * (1 - hCoeff))/view.scaleY, h * hCoeff/view.scaleY, 217 | style.fontFamily, style.fontSize, style.fontWeight, style.color, 218 | primary ? "cm-fat-cursor cm-cursor-primary" : "cm-fat-cursor cm-cursor-secondary", 219 | letter, hCoeff != 1) 220 | } else { 221 | return null; 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /src/cm_adapter.ts: -------------------------------------------------------------------------------- 1 | import { EditorSelection, Text, MapMode, ChangeDesc } from "@codemirror/state" 2 | import { StringStream, matchBrackets, indentUnit, ensureSyntaxTree, foldCode } from "@codemirror/language" 3 | import { EditorView, runScopeHandlers, ViewUpdate } from "@codemirror/view" 4 | import { RegExpCursor, setSearchQuery, SearchQuery } from "@codemirror/search" 5 | import { 6 | insertNewlineAndIndent, indentMore, indentLess, indentSelection, cursorCharLeft, 7 | undo, redo, cursorLineBoundaryBackward, cursorLineBoundaryForward, cursorCharBackward, 8 | } from "@codemirror/commands" 9 | import {vimState, CM5RangeInterface} from "./types" 10 | 11 | function indexFromPos(doc: Text, pos: Pos): number { 12 | var ch = pos.ch; 13 | var lineNumber = pos.line + 1; 14 | if (lineNumber < 1) { 15 | lineNumber = 1 16 | ch = 0 17 | } 18 | if (lineNumber > doc.lines) { 19 | lineNumber = doc.lines 20 | ch = Number.MAX_VALUE 21 | } 22 | var line = doc.line(lineNumber) 23 | return Math.min(line.from + Math.max(0, ch), line.to) 24 | } 25 | function posFromIndex(doc: Text, offset: number): Pos { 26 | let line = doc.lineAt(offset) 27 | return { line: line.number - 1, ch: offset - line.from } 28 | } 29 | class Pos { 30 | line: number 31 | ch: number 32 | sticky?: string 33 | constructor(line: number, ch: number) { 34 | this.line = line; this.ch = ch; 35 | } 36 | }; 37 | 38 | function on(emitter: any, type: string, f: Function) { 39 | if (emitter.addEventListener) { 40 | emitter.addEventListener(type, f, false); 41 | } else { 42 | var map = emitter._handlers || (emitter._handlers = {}); 43 | map[type] = (map[type] || []).concat(f); 44 | } 45 | }; 46 | 47 | function off(emitter: any, type: string, f: Function) { 48 | if (emitter.removeEventListener) { 49 | emitter.removeEventListener(type, f, false); 50 | } else { 51 | var map = emitter._handlers, arr = map && map[type]; 52 | if (arr) { 53 | var index = arr.indexOf(f); 54 | if (index > -1) { map[type] = arr.slice(0, index).concat(arr.slice(index + 1)); } 55 | } 56 | } 57 | } 58 | 59 | function signal(emitter: any, type: string, ...args: any[]) { 60 | var handlers = emitter._handlers?.[type] 61 | if (!handlers) return 62 | for (var i = 0; i < handlers.length; ++i) { handlers[i](...args); } 63 | } 64 | 65 | function signalTo(handlers: any, ...args: any[]) { 66 | if (!handlers) return 67 | for (var i = 0; i < handlers.length; ++i) { handlers[i](...args); } 68 | } 69 | 70 | let wordChar: RegExp 71 | try { 72 | wordChar = new RegExp("[\\w\\p{Alphabetic}\\p{Number}_]", "u") 73 | } catch (_) { 74 | wordChar = /[\w]/ 75 | } 76 | 77 | interface Operation { 78 | $d: number, 79 | isVimOp?: boolean, 80 | cursorActivityHandlers?: Function[], 81 | cursorActivity?: boolean, 82 | lastChange?: any, 83 | change?: any, 84 | changeHandlers?: Function[], 85 | $changeStart?: number, 86 | } 87 | 88 | // workaround for missing api for merging transactions 89 | function dispatchChange(cm: CodeMirror, transaction: any) { 90 | var view = cm.cm6; 91 | if (view.state.readOnly) 92 | return; 93 | var type = "input.type.compose"; 94 | if (cm.curOp) { 95 | if (!cm.curOp.lastChange) type = "input.type.compose.start"; 96 | } 97 | if (transaction.annotations) { 98 | try { 99 | transaction.annotations.some(function (note: any) { 100 | if (note.value == "input") note.value = type; 101 | }); 102 | } catch (e) { 103 | console.error(e); 104 | } 105 | } else { 106 | transaction.userEvent = type; 107 | } 108 | return view.dispatch(transaction) 109 | } 110 | 111 | function runHistoryCommand(cm: CodeMirror, revert: boolean) { 112 | if (cm.curOp) { 113 | cm.curOp.$changeStart = undefined; 114 | } 115 | (revert ? undo : redo)(cm.cm6); 116 | let changeStartIndex = cm.curOp?.$changeStart; 117 | // vim mode expects the changed text to be either selected or cursor placed at the start 118 | if (changeStartIndex != null) { 119 | cm.cm6.dispatch({ selection: { anchor: changeStartIndex } }); 120 | } 121 | } 122 | 123 | var keys: Record void> = { 124 | Left: (cm:CodeMirror) => runScopeHandlers(cm.cm6, {key: "Left"} as KeyboardEvent, "editor"), 125 | Right: (cm:CodeMirror) => runScopeHandlers(cm.cm6, {key: "Right"} as KeyboardEvent, "editor"), 126 | Up: (cm:CodeMirror) => runScopeHandlers(cm.cm6, {key: "Up"} as KeyboardEvent, "editor"), 127 | Down: (cm:CodeMirror) => runScopeHandlers(cm.cm6, {key: "Down"} as KeyboardEvent, "editor"), 128 | Backspace: (cm:CodeMirror) => runScopeHandlers(cm.cm6, {key: "Backspace"} as KeyboardEvent, "editor"), 129 | Delete: (cm:CodeMirror) => runScopeHandlers(cm.cm6, {key: "Delete"} as KeyboardEvent, "editor"), 130 | }; 131 | 132 | export class CodeMirror { 133 | static isMac = typeof navigator != "undefined" && /Mac/.test(navigator.platform); 134 | // -------------------------- 135 | static Pos = Pos; 136 | static StringStream = StringStream as unknown as StringStream & { new(_: string): StringStream } 137 | static commands = { 138 | cursorCharLeft: function (cm: CodeMirror) { cursorCharLeft(cm.cm6); }, 139 | redo: function (cm: CodeMirror) { runHistoryCommand(cm, false); }, 140 | undo: function (cm: CodeMirror) { runHistoryCommand(cm, true); }, 141 | newlineAndIndent: function (cm: CodeMirror) { 142 | insertNewlineAndIndent({ 143 | state: cm.cm6.state, 144 | dispatch: (tr) => { 145 | return dispatchChange(cm, tr); 146 | } 147 | }) 148 | }, 149 | indentAuto: function (cm: CodeMirror) { 150 | indentSelection(cm.cm6) 151 | }, 152 | newlineAndIndentContinueComment: undefined as any, 153 | save: undefined as any, 154 | }; 155 | static isWordChar = function (ch: string) { 156 | return wordChar.test(ch); 157 | }; 158 | static keys: any = keys; 159 | static addClass = function (el: any, str: string) { }; 160 | static rmClass = function (el: any, str: string) { }; 161 | static e_preventDefault = function (e: Event) { 162 | e.preventDefault() 163 | }; 164 | static e_stop = function (e: Event) { 165 | e?.stopPropagation?.() 166 | e?.preventDefault?.() 167 | }; 168 | 169 | static lookupKey = function lookupKey(key: string, map: string, handle: Function) { 170 | var result = CodeMirror.keys[key]; 171 | if (!result && /^Arrow/.test(key)) result = CodeMirror.keys[key.slice(5)]; 172 | if (result) handle(result); 173 | }; 174 | 175 | static on = on 176 | static off = off; 177 | static signal = signal; 178 | 179 | // -------------------------- 180 | openDialog(template: Element, callback: Function|undefined, options: any) { 181 | return openDialog(this, template, callback, options); 182 | }; 183 | openNotification(template: Node, options: NotificationOptions) { 184 | return openNotification(this, template, options); 185 | }; 186 | 187 | static findMatchingTag = findMatchingTag; 188 | static findEnclosingTag = findEnclosingTag; 189 | 190 | // -------------------------- 191 | cm6: EditorView 192 | state: { 193 | statusbar?: Element | null, 194 | dialog?: HTMLElement | null, 195 | vimPlugin?: any, 196 | vim?: vimState | null, 197 | currentNotificationClose?: Function | null, 198 | closeVimNotification?: Function | null, 199 | keyMap?: string, 200 | overwrite?: boolean, 201 | textwidth?: number, 202 | } = {}; 203 | marks: Record = Object.create(null); 204 | $mid = 0; // marker id counter 205 | curOp: Operation | null | undefined; 206 | options: any = {}; 207 | _handlers: any = {}; 208 | constructor(cm6: EditorView) { 209 | this.cm6 = cm6; 210 | this.onChange = this.onChange.bind(this); 211 | this.onSelectionChange = this.onSelectionChange.bind(this); 212 | }; 213 | 214 | on(type: string, f: Function) { on(this, type, f) } 215 | off(type: string, f: Function) { off(this, type, f) } 216 | signal(type: string, e: any, handlers?: any) { signal(this, type, e, handlers) } 217 | 218 | indexFromPos(pos: Pos) { 219 | return indexFromPos(this.cm6.state.doc, pos); 220 | }; 221 | posFromIndex(offset: number) { 222 | return posFromIndex(this.cm6.state.doc, offset); 223 | }; 224 | 225 | 226 | foldCode(pos: Pos) { 227 | let view = this.cm6 228 | let ranges = view.state.selection.ranges 229 | let doc = this.cm6.state.doc 230 | let index = indexFromPos(doc, pos) 231 | let tmpRanges = EditorSelection.create([EditorSelection.range(index, index)], 0).ranges; 232 | 233 | (view.state.selection as any).ranges = tmpRanges; 234 | foldCode(view); 235 | (view.state.selection as any).ranges = ranges; 236 | } 237 | 238 | firstLine() { return 0; }; 239 | lastLine() { return this.cm6.state.doc.lines - 1; }; 240 | lineCount() { return this.cm6.state.doc.lines }; 241 | setCursor(line: number, ch: number): void; 242 | setCursor(line: Pos): void; 243 | setCursor(line: Pos | number, ch?: number) { 244 | if (typeof line === 'object') { 245 | ch = line.ch; 246 | line = line.line; 247 | } 248 | var offset = indexFromPos(this.cm6.state.doc, { line, ch: ch || 0 }) 249 | this.cm6.dispatch({ selection: { anchor: offset } }, { scrollIntoView: !this.curOp }) 250 | if (this.curOp && !this.curOp.isVimOp) 251 | this.onBeforeEndOperation(); 252 | }; 253 | getCursor(p?: "head" | "anchor" | "start" | "end"): Pos { 254 | var sel = this.cm6.state.selection.main; 255 | 256 | var offset = p == "head" || !p 257 | ? sel.head 258 | : p == "anchor" 259 | ? sel.anchor 260 | : p == "start" 261 | ? sel.from 262 | : p == "end" 263 | ? sel.to 264 | : null 265 | if (offset == null) throw new Error("Invalid cursor type") 266 | return this.posFromIndex(offset); 267 | }; 268 | 269 | listSelections() { 270 | var doc = this.cm6.state.doc 271 | return this.cm6.state.selection.ranges.map(r => { 272 | return { 273 | anchor: posFromIndex(doc, r.anchor), 274 | head: posFromIndex(doc, r.head), 275 | }; 276 | }); 277 | }; 278 | setSelections(p: CM5RangeInterface[], primIndex?: number) { 279 | var doc = this.cm6.state.doc 280 | var ranges = p.map(x => { 281 | var head = indexFromPos(doc, x.head) 282 | var anchor = indexFromPos(doc, x.anchor) 283 | // workaround for codemirror bug, see https://github.com/replit/codemirror-vim/issues/169 284 | if (head == anchor) 285 | return EditorSelection.cursor(head, 1) 286 | return EditorSelection.range(anchor, head) 287 | }) 288 | this.cm6.dispatch({ 289 | selection: EditorSelection.create(ranges, primIndex) 290 | }) 291 | }; 292 | setSelection(anchor: Pos, head: Pos, options?: any) { 293 | this.setSelections([{anchor, head}], 0); 294 | if (options && options.origin == '*mouse') { 295 | this.onBeforeEndOperation(); 296 | } 297 | }; 298 | getLine(row: number): string { 299 | var doc = this.cm6.state.doc 300 | if (row < 0 || row >= doc.lines) return ""; 301 | return this.cm6.state.doc.line(row + 1).text; 302 | }; 303 | getLineHandle(row: number) { 304 | if (!this.$lineHandleChanges) this.$lineHandleChanges = []; 305 | return { row: row, index: this.indexFromPos(new Pos(row, 0))}; 306 | } 307 | getLineNumber(handle: any) { 308 | var updates = this.$lineHandleChanges; 309 | 310 | if (!updates) return null; 311 | var offset = handle.index; 312 | for (var i = 0; i < updates.length; i++) { 313 | offset = updates[i].changes .mapPos(offset, 1, MapMode.TrackAfter); 314 | if (offset == null) return null; 315 | } 316 | var pos = this.posFromIndex(offset); 317 | return pos.ch == 0 ? pos.line : null; 318 | } 319 | releaseLineHandles() { 320 | this.$lineHandleChanges = undefined; 321 | } 322 | getRange(s: Pos, e: Pos) { 323 | var doc = this.cm6.state.doc; 324 | return this.cm6.state.sliceDoc( 325 | indexFromPos(doc, s), 326 | indexFromPos(doc, e) 327 | ) 328 | }; 329 | replaceRange(text: string, s: Pos, e?: Pos, source?: string) { 330 | if (!e) e = s; 331 | var doc = this.cm6.state.doc; 332 | var from = indexFromPos(doc, s); 333 | var to = indexFromPos(doc, e); 334 | dispatchChange(this, { changes: { from, to, insert: text } }); 335 | }; 336 | replaceSelection(text: string) { 337 | dispatchChange(this, this.cm6.state.replaceSelection(text)) 338 | }; 339 | replaceSelections(replacements: string[]) { 340 | var ranges = this.cm6.state.selection.ranges; 341 | var changes = ranges.map((r, i) => { 342 | return { from: r.from, to: r.to, insert: replacements[i] || "" } 343 | }); 344 | dispatchChange(this, { changes }); 345 | }; 346 | getSelection() { 347 | return this.getSelections().join("\n"); 348 | }; 349 | getSelections() { 350 | var cm = this.cm6; 351 | return cm.state.selection.ranges.map(r => cm.state.sliceDoc(r.from, r.to)) 352 | }; 353 | 354 | somethingSelected() { 355 | return this.cm6.state.selection.ranges.some(r => !r.empty) 356 | }; 357 | getInputField() { 358 | return this.cm6.contentDOM; 359 | }; 360 | clipPos(p: Pos) { 361 | var doc = this.cm6.state.doc 362 | var ch = p.ch; 363 | var lineNumber = p.line + 1; 364 | if (lineNumber < 1) { 365 | lineNumber = 1 366 | ch = 0 367 | } 368 | if (lineNumber > doc.lines) { 369 | lineNumber = doc.lines 370 | ch = Number.MAX_VALUE 371 | } 372 | var line = doc.line(lineNumber) 373 | ch = Math.min(Math.max(0, ch), line.to - line.from) 374 | return new Pos(lineNumber - 1, ch); 375 | }; 376 | 377 | 378 | getValue(): string { 379 | return this.cm6.state.doc.toString(); 380 | }; 381 | setValue(text: string) { 382 | var cm = this.cm6; 383 | return cm.dispatch({ 384 | changes: { from: 0, to: cm.state.doc.length, insert: text }, 385 | selection: EditorSelection.range(0, 0) 386 | }) 387 | }; 388 | 389 | focus() { 390 | return this.cm6.focus(); 391 | }; 392 | blur() { 393 | return this.cm6.contentDOM.blur(); 394 | }; 395 | defaultTextHeight() { 396 | return this.cm6.defaultLineHeight 397 | }; 398 | 399 | findMatchingBracket(pos: Pos, _options?: any) { 400 | var state = this.cm6.state 401 | var offset = indexFromPos(state.doc, pos); 402 | var m = matchBrackets(state, offset + 1, -1) 403 | if (m && m.end) { 404 | return { to: posFromIndex(state.doc, m.end.from) }; 405 | } 406 | m = matchBrackets(state, offset, 1) 407 | if (m && m.end) { 408 | return { to: posFromIndex(state.doc, m.end.from) }; 409 | } 410 | return { to: undefined }; 411 | }; 412 | scanForBracket(pos: Pos, dir: 1 | -1, style: any, config: any) { 413 | return scanForBracket(this, pos, dir, style, config); 414 | }; 415 | 416 | indentLine(line: number, more?: boolean) { 417 | // todo how to indent only one line instead of selection 418 | if (more) this.indentMore() 419 | else this.indentLess() 420 | }; 421 | 422 | indentMore() { 423 | indentMore(this.cm6); 424 | }; 425 | indentLess() { 426 | indentLess(this.cm6); 427 | }; 428 | 429 | execCommand(name: string) { 430 | if (name == "indentAuto") CodeMirror.commands.indentAuto(this); 431 | else if (name == "goLineLeft") cursorLineBoundaryBackward(this.cm6); 432 | else if (name == "goLineRight") { 433 | cursorLineBoundaryForward(this.cm6); 434 | let state = this.cm6.state 435 | let cur = state.selection.main.head; 436 | if (cur < state.doc.length && state.sliceDoc(cur, cur + 1) !== "\n") { 437 | cursorCharBackward(this.cm6); 438 | } 439 | } 440 | else console.log(name + " is not implemented"); 441 | }; 442 | 443 | setBookmark(cursor: Pos, options?: { insertLeft: boolean }) { 444 | var assoc = options?.insertLeft ? 1 : -1; 445 | var offset = this.indexFromPos(cursor) 446 | var bm = new Marker(this, offset, assoc); 447 | return bm; 448 | }; 449 | 450 | cm6Query?: SearchQuery 451 | addOverlay({ query }: { query: RegExp }) { 452 | let cm6Query = new SearchQuery({ 453 | regexp: true, 454 | search: query.source, 455 | caseSensitive: !/i/.test(query.flags), 456 | }); 457 | if (cm6Query.valid) { 458 | (cm6Query as any).forVim = true; 459 | this.cm6Query = cm6Query; 460 | let effect = setSearchQuery.of(cm6Query); 461 | this.cm6.dispatch({ effects: effect }); 462 | return cm6Query 463 | } 464 | }; 465 | removeOverlay(overlay?: any) { 466 | if (!this.cm6Query) return 467 | (this.cm6Query as any).forVim = false; 468 | let effect = setSearchQuery.of(this.cm6Query); 469 | this.cm6.dispatch({ effects: effect }); 470 | }; 471 | 472 | getSearchCursor(query: RegExp, pos: Pos) { 473 | var cm = this; 474 | type CM6Result = { from: number, to: number, match: string[] } | null; 475 | type CM5Result = { from: Pos, to: Pos, match: string[] } | null; 476 | var last: CM6Result = null; 477 | var lastCM5Result: CM5Result = null; 478 | var afterEmptyMatch = false; 479 | 480 | if (pos.ch == undefined) pos.ch = Number.MAX_VALUE; 481 | var firstOffset = indexFromPos(cm.cm6.state.doc, pos); 482 | 483 | var source = query.source.replace(/(\\.|{(?:\d+(?:,\d*)?|,\d+)})|[{}]/g, function (a, b) { 484 | if (!b) return "\\" + a 485 | return b; 486 | }); 487 | 488 | function rCursor(doc: Text, from = 0, to = doc.length) { 489 | return new RegExpCursor(doc, source, { ignoreCase: query.ignoreCase }, from, to); 490 | } 491 | 492 | function nextMatch(from: number) { 493 | var doc = cm.cm6.state.doc 494 | if (from > doc.length) return null; 495 | let res = rCursor(doc, from).next() 496 | return res.done ? null : res.value 497 | } 498 | 499 | var ChunkSize = 10000 500 | function prevMatchInRange(from: number, to: number) { 501 | var doc = cm.cm6.state.doc 502 | for (let size = 1; ; size++) { 503 | let start = Math.max(from, to - size * ChunkSize) 504 | let cursor = rCursor(doc, start, to), range: CM6Result = null 505 | while (!cursor.next().done) range = cursor.value 506 | if (range && (start == from || range.from > start + 10)) return range 507 | if (start == from) return null 508 | } 509 | } 510 | return { 511 | findNext: function () { return this.find(false) }, 512 | findPrevious: function () { return this.find(true) }, 513 | find: function (back?: boolean): string[] | null | undefined { 514 | var doc = cm.cm6.state.doc 515 | if (back) { 516 | let endAt = last ? (afterEmptyMatch ? last.to - 1 : last.from) : firstOffset 517 | last = prevMatchInRange(0, endAt); 518 | } else { 519 | let startFrom = last ? (afterEmptyMatch ? last.to + 1 : last.to) : firstOffset 520 | last = nextMatch(startFrom) 521 | } 522 | lastCM5Result = last && { 523 | from: posFromIndex(doc, last.from), 524 | to: posFromIndex(doc, last.to), 525 | match: last.match, 526 | } 527 | afterEmptyMatch = last ? last.from == last.to : false; 528 | return last && last.match 529 | }, 530 | from: function () { return lastCM5Result?.from }, 531 | to: function () { return lastCM5Result?.to }, 532 | replace: function (text: string) { 533 | if (last) { 534 | dispatchChange(cm, { 535 | changes: { from: last.from, to: last.to, insert: text } 536 | }); 537 | last.to = last.from + text.length 538 | if (lastCM5Result) { 539 | lastCM5Result.to = posFromIndex(cm.cm6.state.doc, last.to); 540 | } 541 | } 542 | }, 543 | get match() { 544 | return lastCM5Result && lastCM5Result.match 545 | } 546 | }; 547 | }; 548 | findPosV(start: Pos, amount: number, unit: "page" | "line", goalColumn?: number) { 549 | let { cm6 } = this; 550 | const doc = cm6.state.doc; 551 | let pixels = unit == 'page' ? cm6.dom.clientHeight : 0; 552 | 553 | const startOffset = indexFromPos(doc, start); 554 | let range = EditorSelection.cursor(startOffset, 1, undefined, goalColumn); 555 | let count = Math.round(Math.abs(amount)) 556 | for (let i = 0; i < count; i++) { 557 | if (unit == 'page') { 558 | range = cm6.moveVertically(range, amount > 0, pixels); 559 | } 560 | else if (unit == 'line') { 561 | range = cm6.moveVertically(range, amount > 0); 562 | } 563 | } 564 | 565 | let pos = posFromIndex(doc, range.head) as Pos&{hitSide?: boolean}; 566 | // set hitside to true if there was no place to move and cursor was clipped to the edge 567 | // of document. Needed for gj/gk 568 | if ( 569 | ( 570 | amount < 0 && 571 | range.head == 0 && goalColumn != 0 && 572 | start.line == 0 && start.ch != 0 573 | ) || ( 574 | amount > 0 && 575 | range.head == doc.length && pos.ch != goalColumn 576 | && start.line == pos.line 577 | ) 578 | ) { 579 | pos.hitSide = true; 580 | } 581 | return pos; 582 | }; 583 | charCoords(pos: Pos, mode: "div" | "local") { 584 | var rect = this.cm6.contentDOM.getBoundingClientRect(); 585 | var offset = indexFromPos(this.cm6.state.doc, pos) 586 | var coords = this.cm6.coordsAtPos(offset) 587 | var d = -rect.top 588 | return { left: (coords?.left || 0) - rect.left, top: (coords?.top || 0) + d, bottom: (coords?.bottom || 0) + d } 589 | }; 590 | coordsChar(coords: { left: number, top: number }, mode: "div" | "local") { 591 | var rect = this.cm6.contentDOM.getBoundingClientRect() 592 | 593 | var offset = this.cm6.posAtCoords({ x: coords.left + rect.left, y: coords.top + rect.top }) || 0 594 | return posFromIndex(this.cm6.state.doc, offset) 595 | }; 596 | 597 | getScrollInfo() { 598 | var scroller = this.cm6.scrollDOM 599 | return { 600 | left: scroller.scrollLeft, top: scroller.scrollTop, 601 | height: scroller.scrollHeight, 602 | width: scroller.scrollWidth, 603 | clientHeight: scroller.clientHeight, clientWidth: scroller.clientWidth 604 | }; 605 | }; 606 | scrollTo(x?: number|null, y?: number|null) { 607 | if (x != null) 608 | this.cm6.scrollDOM.scrollLeft = x 609 | if (y != null) 610 | this.cm6.scrollDOM.scrollTop = y 611 | }; 612 | scrollIntoView(pos?: Pos, margin?: number) { 613 | if (pos) { 614 | var offset = this.indexFromPos(pos); 615 | this.cm6.dispatch({ 616 | effects: EditorView.scrollIntoView(offset) 617 | }); 618 | } else { 619 | this.cm6.dispatch({ scrollIntoView: true, userEvent: "scroll" }); 620 | } 621 | }; 622 | 623 | getWrapperElement() { 624 | return this.cm6.dom; 625 | }; 626 | 627 | // for tests 628 | getMode() { 629 | return { name: this.getOption("mode") }; 630 | }; 631 | setSize(w: number, h: number) { 632 | this.cm6.dom.style.width = w + 4 + "px" 633 | this.cm6.dom.style.height = h + "px" 634 | this.refresh() 635 | } 636 | refresh() { 637 | (this.cm6 as any).measure() 638 | } 639 | 640 | // event listeners 641 | destroy() { 642 | this.removeOverlay(); 643 | }; 644 | 645 | getLastEditEnd() { 646 | return this.posFromIndex(this.$lastChangeEndOffset); 647 | }; 648 | $lastChangeEndOffset = 0; 649 | $lineHandleChanges: undefined|ViewUpdate[] 650 | onChange(update: ViewUpdate) { 651 | if (this.$lineHandleChanges) { 652 | this.$lineHandleChanges.push(update); 653 | } 654 | for (let i in this.marks) { 655 | let m = this.marks[i]; 656 | m.update(update.changes) 657 | } 658 | if (this.virtualSelection) { 659 | this.virtualSelection.ranges = this.virtualSelection.ranges.map(range => range.map(update.changes)) 660 | } 661 | var curOp = this.curOp = this.curOp || ({} as Operation); 662 | update.changes.iterChanges((fromA: number, toA: number, fromB: number, toB: number, text: Text) => { 663 | if (curOp.$changeStart == null || curOp.$changeStart > fromB) 664 | curOp.$changeStart = fromB; 665 | this.$lastChangeEndOffset = toB; 666 | var change = { text: text.toJSON() }; 667 | if (!curOp.lastChange) { 668 | curOp.lastChange = curOp.change = change; 669 | } else { 670 | curOp.lastChange.next = curOp.lastChange = change; 671 | } 672 | }, true); 673 | if (!curOp.changeHandlers) 674 | curOp.changeHandlers = this._handlers["change"] && this._handlers["change"].slice(); 675 | }; 676 | onSelectionChange() { 677 | var curOp = this.curOp = this.curOp || ({} as Operation); 678 | if (!curOp.cursorActivityHandlers) 679 | curOp.cursorActivityHandlers = this._handlers["cursorActivity"] && this._handlers["cursorActivity"].slice(); 680 | this.curOp.cursorActivity = true; 681 | }; 682 | operation(fn: ()=>T, force?: boolean) { 683 | if (!this.curOp) 684 | this.curOp = { $d: 0 }; 685 | this.curOp.$d++; 686 | try { 687 | var result = fn() 688 | } finally { 689 | if (this.curOp) { 690 | this.curOp.$d-- 691 | if (!this.curOp.$d) 692 | this.onBeforeEndOperation() 693 | } 694 | } 695 | return result 696 | }; 697 | onBeforeEndOperation() { 698 | var op = this.curOp; 699 | var scrollIntoView = false; 700 | if (op) { 701 | if (op.change) { signalTo(op.changeHandlers, this, op.change); } 702 | if (op && op.cursorActivity) { 703 | signalTo(op.cursorActivityHandlers, this, null); 704 | if (op.isVimOp) 705 | scrollIntoView = true; 706 | } 707 | this.curOp = null; 708 | } 709 | if (scrollIntoView) 710 | this.scrollIntoView(); 711 | }; 712 | moveH(increment: number, unit: string) { 713 | if (unit == 'char') { 714 | // todo 715 | var cur = this.getCursor(); 716 | this.setCursor(cur.line, cur.ch + increment); 717 | } 718 | }; 719 | 720 | setOption(name: string, val: any) { 721 | switch (name) { 722 | case "keyMap": 723 | this.state.keyMap = val; 724 | break; 725 | case "textwidth": 726 | this.state.textwidth = val; 727 | break; 728 | // TODO cm6 doesn't provide any method to reconfigure these 729 | case "tabSize": 730 | case "indentWithTabs": 731 | break 732 | 733 | } 734 | }; 735 | getOption(name:"firstLineNumber"|"tabSize"|"textwidth"): number; 736 | getOption(name:string): number|boolean|string|undefined; 737 | getOption(name: string) { 738 | switch (name) { 739 | case "firstLineNumber": return 1; 740 | case "tabSize": return this.cm6.state.tabSize || 4; 741 | case "readOnly": return this.cm6.state.readOnly; 742 | case "indentWithTabs": return this.cm6.state.facet(indentUnit) == "\t"; // TODO 743 | case "indentUnit": return this.cm6.state.facet(indentUnit).length || 2; 744 | case "textwidth": return this.state.textwidth; 745 | // for tests 746 | case "keyMap": return this.state.keyMap || "vim"; 747 | } 748 | }; 749 | toggleOverwrite(on: boolean) { 750 | this.state.overwrite = on; 751 | }; 752 | getTokenTypeAt(pos: Pos) { 753 | // only comment|string are needed 754 | var offset = this.indexFromPos(pos) 755 | var tree = ensureSyntaxTree(this.cm6.state, offset) 756 | var node = tree?.resolve(offset) 757 | var type = node?.type?.name || "" 758 | if (/comment/i.test(type)) return "comment"; 759 | if (/string/i.test(type)) return "string"; 760 | return "" 761 | }; 762 | 763 | overWriteSelection(text: string) { 764 | var doc = this.cm6.state.doc 765 | var sel = this.cm6.state.selection; 766 | var ranges = sel.ranges.map(x => { 767 | if (x.empty) { 768 | var ch = x.to < doc.length ? doc.sliceString(x.from, x.to + 1) : "" 769 | if (ch && !/\n/.test(ch)) 770 | return EditorSelection.range(x.from, x.to + 1) 771 | } 772 | return x; 773 | }); 774 | this.cm6.dispatch({ 775 | selection: EditorSelection.create(ranges, sel.mainIndex) 776 | }) 777 | this.replaceSelection(text) 778 | } 779 | 780 | /*** multiselect ****/ 781 | isInMultiSelectMode() { 782 | return this.cm6.state.selection.ranges.length > 1 783 | } 784 | virtualSelectionMode() { 785 | return !!this.virtualSelection 786 | } 787 | virtualSelection: Mutable | null = null; 788 | forEachSelection(command: Function) { 789 | var selection = this.cm6.state.selection; 790 | this.virtualSelection = EditorSelection.create(selection.ranges, selection.mainIndex) 791 | for (var i = 0; i < this.virtualSelection.ranges.length; i++) { 792 | var range = this.virtualSelection.ranges[i] 793 | if (!range) continue 794 | this.cm6.dispatch({ selection: EditorSelection.create([range]) }); 795 | command(); 796 | (this.virtualSelection as any).ranges[i] = this.cm6.state.selection.ranges[0] 797 | } 798 | this.cm6.dispatch({ selection: this.virtualSelection }) 799 | this.virtualSelection = null; 800 | } 801 | 802 | hardWrap(options: hardWrapOptions) { 803 | return hardWrap(this, options); 804 | } 805 | 806 | showMatchesOnScrollbar?: Function // not implemented 807 | save?: Function 808 | static keyName?: Function = undefined 809 | }; 810 | 811 | type Mutable = { 812 | -readonly [Key in keyof Type]: Type[Key]; 813 | }; 814 | 815 | /************* dialog *************/ 816 | 817 | 818 | function dialogDiv(cm: CodeMirror, template: Node, bottom?: boolean) { 819 | var dialog = document.createElement("div"); 820 | dialog.appendChild(template); 821 | return dialog; 822 | } 823 | 824 | function closeNotification(cm: CodeMirror, newVal?: Function) { 825 | if (cm.state.currentNotificationClose) 826 | cm.state.currentNotificationClose(); 827 | cm.state.currentNotificationClose = newVal; 828 | } 829 | interface NotificationOptions { bottom?: boolean, duration?: number } 830 | function openNotification(cm: CodeMirror, template: Node, options: NotificationOptions) { 831 | closeNotification(cm, close); 832 | var dialog = dialogDiv(cm, template, options && options.bottom); 833 | var closed = false; 834 | var doneTimer: number; 835 | var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000; 836 | 837 | function close() { 838 | if (closed) return; 839 | closed = true; 840 | clearTimeout(doneTimer); 841 | dialog.remove(); 842 | hideDialog(cm, dialog) 843 | } 844 | 845 | dialog.onclick = function (e) { 846 | e.preventDefault(); 847 | close(); 848 | }; 849 | 850 | showDialog(cm, dialog) 851 | 852 | if (duration) 853 | doneTimer = setTimeout(close, duration); 854 | 855 | return close; 856 | } 857 | 858 | 859 | function showDialog(cm: CodeMirror, dialog: HTMLElement) { 860 | var oldDialog = cm.state.dialog 861 | cm.state.dialog = dialog; 862 | dialog.style.flex = "1"; 863 | 864 | if (dialog && oldDialog !== dialog) { 865 | if (oldDialog && oldDialog.contains(document.activeElement)) 866 | cm.focus() 867 | if (oldDialog && oldDialog.parentElement) { 868 | oldDialog.parentElement.replaceChild(dialog, oldDialog) 869 | } else if (oldDialog) { 870 | oldDialog.remove() 871 | } 872 | CodeMirror.signal(cm, "dialog") 873 | } 874 | } 875 | 876 | function hideDialog(cm: CodeMirror, dialog: Element) { 877 | if (cm.state.dialog == dialog) { 878 | cm.state.dialog = null; 879 | CodeMirror.signal(cm, "dialog") 880 | } 881 | } 882 | 883 | function openDialog(me: CodeMirror, template: Element, callback: Function|undefined, options: any) { 884 | if (!options) options = {}; 885 | 886 | closeNotification(me, undefined); 887 | 888 | var dialog = dialogDiv(me, template, options.bottom); 889 | var closed = false; 890 | showDialog(me, dialog); 891 | 892 | function close(newVal?: string) { 893 | if (typeof newVal == 'string') { 894 | inp.value = newVal; 895 | } else { 896 | if (closed) return; 897 | 898 | closed = true; 899 | hideDialog(me, dialog) 900 | if (!me.state.dialog) 901 | me.focus(); 902 | 903 | if (options.onClose) options.onClose(dialog); 904 | } 905 | } 906 | 907 | var inp = dialog.getElementsByTagName("input")[0]; 908 | if (inp) { 909 | if (options.value) { 910 | inp.value = options.value; 911 | if (options.selectValueOnOpen !== false) inp.select(); 912 | } 913 | 914 | if (options.onInput) 915 | CodeMirror.on(inp, "input", function (e: KeyboardEvent) { options.onInput(e, inp.value, close); }); 916 | if (options.onKeyUp) 917 | CodeMirror.on(inp, "keyup", function (e: KeyboardEvent) { options.onKeyUp(e, inp.value, close); }); 918 | 919 | CodeMirror.on(inp, "keydown", function (e: KeyboardEvent) { 920 | if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; } 921 | if (e.keyCode == 13) callback && callback(inp.value); 922 | if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) { 923 | inp.blur(); 924 | CodeMirror.e_stop(e); 925 | close(); 926 | } 927 | }); 928 | 929 | if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", function () { 930 | setTimeout(function () { 931 | if (document.activeElement === inp) 932 | return; 933 | close() 934 | }) 935 | }); 936 | 937 | inp.focus(); 938 | } 939 | return close; 940 | } 941 | 942 | var matching: any = { "(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<", "<": ">>", ">": "<<" }; 943 | 944 | function bracketRegex(config: any) { 945 | return config && config.bracketRegex || /[(){}[\]]/ 946 | } 947 | 948 | function scanForBracket(cm: CodeMirror, where: Pos, dir: -1 | 1, style: any, config: any) { 949 | var maxScanLen = (config && config.maxScanLineLength) || 10000; 950 | var maxScanLines = (config && config.maxScanLines) || 1000; 951 | 952 | var stack: string[] = []; 953 | var re = bracketRegex(config) 954 | var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1) 955 | : Math.max(cm.firstLine() - 1, where.line - maxScanLines); 956 | for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) { 957 | var line = cm.getLine(lineNo); 958 | if (!line) continue; 959 | var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1; 960 | if (line.length > maxScanLen) continue; 961 | if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0); 962 | for (; pos != end; pos += dir) { 963 | var ch = line.charAt(pos); 964 | if (re.test(ch) /*&& (style === undefined || 965 | (cm.getTokenTypeAt(new Pos(lineNo, pos + 1)) || "") == (style || ""))*/) { 966 | var match = matching[ch]; 967 | if (match && (match.charAt(1) == ">") == (dir > 0)) stack.push(ch); 968 | else if (!stack.length) return { pos: new Pos(lineNo, pos), ch: ch }; 969 | else stack.pop(); 970 | } 971 | } 972 | } 973 | return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null; 974 | } 975 | 976 | function findMatchingTag(cm: CodeMirror, pos: Pos) { 977 | return null; 978 | } 979 | 980 | function findEnclosingTag(cm: CodeMirror, pos: Pos) { 981 | var state = cm.cm6.state; 982 | var offset = cm.indexFromPos(pos); 983 | if (offset < state.doc.length) { 984 | var text = state.sliceDoc(offset, offset + 1) 985 | if (text == "<") offset++; 986 | } 987 | var tree = ensureSyntaxTree(state, offset); 988 | var node = tree?.resolve(offset) || null; 989 | while (node) { 990 | if ( 991 | node.firstChild?.type.name == 'OpenTag' 992 | && node.lastChild?.type.name == 'CloseTag' 993 | ) { 994 | return { 995 | open: convertRange(state.doc, node.firstChild), 996 | close: convertRange(state.doc, node.lastChild), 997 | }; 998 | } 999 | node = node.parent; 1000 | } 1001 | } 1002 | 1003 | function convertRange(doc: Text, cm6Range: { from: number, to: number }) { 1004 | return { 1005 | from: posFromIndex(doc, cm6Range.from), 1006 | to: posFromIndex(doc, cm6Range.to) 1007 | } 1008 | } 1009 | 1010 | 1011 | 1012 | class Marker { 1013 | cm: CodeMirror; 1014 | id: number; 1015 | offset: number | null; 1016 | assoc: number; 1017 | 1018 | constructor(cm: CodeMirror, offset: number, assoc: number) { 1019 | this.cm = cm; 1020 | this.id = cm.$mid++; 1021 | this.offset = offset; 1022 | this.assoc = assoc; 1023 | cm.marks[this.id] = this; 1024 | }; 1025 | clear() { delete this.cm.marks[this.id] }; 1026 | find(): Pos | null { 1027 | if (this.offset == null) return null; 1028 | return this.cm.posFromIndex(this.offset) 1029 | }; 1030 | update(change: ChangeDesc) { 1031 | if (this.offset != null) 1032 | this.offset = change.mapPos(this.offset, this.assoc, MapMode.TrackDel) 1033 | } 1034 | } 1035 | 1036 | 1037 | type hardWrapOptions = {from: number, to: number, column?: number, allowMerge?: boolean}; 1038 | function hardWrap(cm: CodeMirror, options: hardWrapOptions) { 1039 | var max = options.column || cm.getOption('textwidth') || 80; 1040 | var allowMerge = options.allowMerge != false; 1041 | 1042 | var row = Math.min(options.from, options.to); 1043 | var endRow = Math.max(options.from, options.to); 1044 | 1045 | while (row <= endRow) { 1046 | var line = cm.getLine(row); 1047 | if (line.length > max) { 1048 | var space = findSpace(line, max, 5); 1049 | if (space) { 1050 | var indentation = /^\s*/.exec(line)?.[0]; 1051 | cm.replaceRange("\n" + indentation, new Pos(row, space.start), new Pos(row, space.end)); 1052 | } 1053 | endRow++; 1054 | } else if (allowMerge && /\S/.test(line) && row != endRow) { 1055 | var nextLine = cm.getLine(row + 1); 1056 | if (nextLine && /\S/.test(nextLine)) { 1057 | var trimmedLine = line.replace(/\s+$/, ""); 1058 | var trimmedNextLine = nextLine.replace(/^\s+/, ""); 1059 | var mergedLine = trimmedLine + " " + trimmedNextLine; 1060 | 1061 | var space = findSpace(mergedLine, max, 5); 1062 | if (space && space.start > trimmedLine.length || mergedLine.length < max) { 1063 | cm.replaceRange(" ", new Pos(row, trimmedLine.length), new Pos(row + 1, nextLine.length - trimmedNextLine.length)); 1064 | row--; 1065 | endRow--; 1066 | } else if (trimmedLine.length < line.length) { 1067 | cm.replaceRange("", new Pos(row, trimmedLine.length), new Pos(row, line.length)); 1068 | } 1069 | } 1070 | } 1071 | row++; 1072 | } 1073 | return row; 1074 | 1075 | function findSpace(line: string, max: number, min: number) { 1076 | if (line.length < max) 1077 | return; 1078 | var before = line.slice(0, max); 1079 | var after = line.slice(max); 1080 | var spaceAfter = /^(?:(\s+)|(\S+)(\s+))/.exec(after); 1081 | var spaceBefore = /(?:(\s+)|(\s+)(\S+))$/.exec(before); 1082 | var start = 0; 1083 | var end = 0; 1084 | if (spaceBefore && !spaceBefore[2]) { 1085 | start = max - spaceBefore[1].length; 1086 | end = max; 1087 | } 1088 | if (spaceAfter && !spaceAfter[2]) { 1089 | if (!start) 1090 | start = max; 1091 | end = max + spaceAfter[1].length; 1092 | } 1093 | if (start) { 1094 | return { 1095 | start: start, 1096 | end: end 1097 | }; 1098 | } 1099 | if (spaceBefore && spaceBefore[2] && spaceBefore.index > min) { 1100 | return { 1101 | start: spaceBefore.index, 1102 | end: spaceBefore.index + spaceBefore[2].length 1103 | }; 1104 | } 1105 | if (spaceAfter && spaceAfter[2]) { 1106 | start = max + spaceAfter[2].length; 1107 | return { 1108 | start: start, 1109 | end: start + spaceAfter[3].length 1110 | }; 1111 | } 1112 | } 1113 | } 1114 | 1115 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { initVim } from "./vim"; 2 | import { CodeMirror } from "./cm_adapter"; 3 | import { BlockCursorPlugin, hideNativeSelection } from "./block-cursor"; 4 | import { 5 | Extension, 6 | StateField, 7 | StateEffect, 8 | RangeSetBuilder, 9 | } from "@codemirror/state"; 10 | import { 11 | ViewPlugin, 12 | PluginValue, 13 | ViewUpdate, 14 | Decoration, 15 | EditorView, 16 | showPanel, 17 | Panel, 18 | } from "@codemirror/view"; 19 | import { setSearchQuery } from "@codemirror/search"; 20 | 21 | var FIREFOX_LINUX = typeof navigator != "undefined" 22 | && /linux/i.test(navigator.platform) 23 | && / Gecko\/\d+/.exec(navigator.userAgent); 24 | 25 | const Vim = initVim(CodeMirror); 26 | 27 | const HighlightMargin = 250; 28 | 29 | const vimStyle = EditorView.baseTheme({ 30 | ".cm-vimMode .cm-cursorLayer:not(.cm-vimCursorLayer)": { 31 | display: "none", 32 | }, 33 | ".cm-vim-panel": { 34 | padding: "0px 10px", 35 | fontFamily: "monospace", 36 | minHeight: "1.3em", 37 | display: 'flex', 38 | }, 39 | ".cm-vim-panel input": { 40 | border: "none", 41 | outline: "none", 42 | backgroundColor: "inherit", 43 | }, 44 | 45 | "&light .cm-searchMatch": { backgroundColor: "#ffff0054" }, 46 | "&dark .cm-searchMatch": { backgroundColor: "#00ffff8a" }, 47 | }); 48 | type EditorViewExtended = EditorView & { cm: CodeMirror }; 49 | 50 | const vimPlugin = ViewPlugin.fromClass( 51 | class implements PluginValue { 52 | private dom: HTMLElement; 53 | private statusButton: HTMLElement; 54 | private spacer: HTMLElement; 55 | public view: EditorViewExtended; 56 | public cm: CodeMirror; 57 | public status = ""; 58 | blockCursor: BlockCursorPlugin; 59 | constructor(view: EditorView) { 60 | this.view = view as EditorViewExtended; 61 | const cm = (this.cm = new CodeMirror(view)); 62 | Vim.enterVimMode(this.cm); 63 | 64 | this.view.cm = this.cm; 65 | this.cm.state.vimPlugin = this; 66 | 67 | this.blockCursor = new BlockCursorPlugin(view, cm); 68 | this.updateClass(); 69 | 70 | this.cm.on("vim-command-done", () => { 71 | if (cm.state.vim) cm.state.vim.status = ""; 72 | this.blockCursor.scheduleRedraw(); 73 | this.updateStatus(); 74 | }); 75 | this.cm.on("vim-mode-change", (e: any) => { 76 | if (!cm.state.vim) return; 77 | cm.state.vim.mode = e.mode; 78 | if (e.subMode) { 79 | cm.state.vim.mode += e.subMode === "linewise" ? " line" : " block"; 80 | } 81 | cm.state.vim.status = ""; 82 | this.blockCursor.scheduleRedraw(); 83 | this.updateClass(); 84 | this.updateStatus(); 85 | }); 86 | 87 | this.cm.on("dialog", () => { 88 | if (this.cm.state.statusbar) { 89 | this.updateStatus(); 90 | } else { 91 | view.dispatch({ 92 | effects: showVimPanel.of(!!this.cm.state.dialog), 93 | }); 94 | } 95 | }); 96 | 97 | this.dom = document.createElement("span"); 98 | this.spacer = document.createElement("span"); 99 | this.spacer.style.flex = "1"; 100 | this.statusButton = document.createElement("span"); 101 | this.statusButton.onclick = (e) => { 102 | Vim.handleKey(this.cm, "", "user"); 103 | this.cm.focus(); 104 | }; 105 | this.statusButton.style.cssText = "cursor: pointer"; 106 | } 107 | 108 | update(update: ViewUpdate) { 109 | if ((update.viewportChanged || update.docChanged) && this.query) { 110 | this.highlight(this.query); 111 | } 112 | if (update.docChanged) { 113 | this.cm.onChange(update); 114 | } 115 | if (update.selectionSet) { 116 | this.cm.onSelectionChange(); 117 | } 118 | if (update.viewportChanged) { 119 | // scroll 120 | } 121 | if (this.cm.curOp && !this.cm.curOp.isVimOp) { 122 | this.cm.onBeforeEndOperation(); 123 | } 124 | if (update.transactions) { 125 | for (let tr of update.transactions) 126 | for (let effect of tr.effects) { 127 | if (effect.is(setSearchQuery)) { 128 | let forVim = (effect.value as any)?.forVim; 129 | if (!forVim) { 130 | this.highlight(null); 131 | } else { 132 | let query = (effect.value as any).create(); 133 | this.highlight(query); 134 | } 135 | } 136 | } 137 | } 138 | 139 | this.blockCursor.update(update); 140 | } 141 | updateClass() { 142 | const state = this.cm.state; 143 | if (!state.vim || (state.vim.insertMode && !state.overwrite)) 144 | this.view.scrollDOM.classList.remove("cm-vimMode"); 145 | else this.view.scrollDOM.classList.add("cm-vimMode"); 146 | } 147 | updateStatus() { 148 | let dom = this.cm.state.statusbar; 149 | let vim = this.cm.state.vim; 150 | if (!dom || !vim) return; 151 | let dialog = this.cm.state.dialog; 152 | if (dialog) { 153 | if (dialog.parentElement != dom) { 154 | dom.textContent = ""; 155 | dom.appendChild(dialog); 156 | } 157 | } else { 158 | dom.textContent = "" 159 | var status = (vim.mode || "normal").toUpperCase(); 160 | if (vim.insertModeReturn) status += "(C-O)" 161 | this.statusButton.textContent = `--${status}--`; 162 | dom.appendChild(this.statusButton); 163 | dom.appendChild(this.spacer); 164 | } 165 | 166 | this.dom.textContent = vim.status; 167 | dom.appendChild(this.dom); 168 | } 169 | 170 | destroy() { 171 | Vim.leaveVimMode(this.cm); 172 | this.updateClass(); 173 | this.blockCursor.destroy(); 174 | delete (this.view as any).cm; 175 | } 176 | 177 | highlight(query: any) { 178 | this.query = query; 179 | if (!query) return (this.decorations = Decoration.none); 180 | let { view } = this; 181 | let builder = new RangeSetBuilder(); 182 | for ( 183 | let i = 0, ranges = view.visibleRanges, l = ranges.length; 184 | i < l; 185 | i++ 186 | ) { 187 | let { from, to } = ranges[i]; 188 | while (i < l - 1 && to > ranges[i + 1].from - 2 * HighlightMargin) 189 | to = ranges[++i].to; 190 | query.highlight( 191 | view.state, 192 | from, 193 | to, 194 | (from: number, to: number) => { 195 | builder.add(from, to, matchMark); 196 | } 197 | ); 198 | } 199 | return (this.decorations = builder.finish()); 200 | } 201 | query = null; 202 | decorations = Decoration.none; 203 | waitForCopy = false; 204 | handleKey(e: KeyboardEvent, view: EditorView) { 205 | const cm = this.cm; 206 | let vim = cm.state.vim; 207 | if (!vim) return; 208 | 209 | const key = Vim.vimKeyFromEvent(e, vim); 210 | CodeMirror.signal(this.cm, 'inputEvent', {type: "handleKey", key}); 211 | if (!key) return; 212 | 213 | // clear search highlight 214 | if ( 215 | key == "" && 216 | !vim.insertMode && 217 | !vim.visualMode && 218 | this.query /* && !cm.inMultiSelectMode*/ 219 | ) { 220 | const searchState = vim.searchState_ 221 | if (searchState) { 222 | cm.removeOverlay(searchState.getOverlay()) 223 | searchState.setOverlay(null); 224 | } 225 | } 226 | 227 | let isCopy = key === "" && !CodeMirror.isMac; 228 | if (isCopy && cm.somethingSelected()) { 229 | this.waitForCopy = true; 230 | return true; 231 | } 232 | 233 | vim.status = (vim.status || "") + key; 234 | let result = Vim.multiSelectHandleKey(cm, key, "user"); 235 | vim = Vim.maybeInitVimState_(cm); // the object can change if there is an exception in handleKey 236 | 237 | // insert mode 238 | if (!result && vim.insertMode && cm.state.overwrite) { 239 | if (e.key && e.key.length == 1 && !/\n/.test(e.key)) { 240 | result = true; 241 | cm.overWriteSelection(e.key); 242 | } else if (e.key == "Backspace") { 243 | result = true; 244 | CodeMirror.commands.cursorCharLeft(cm); 245 | } 246 | } 247 | if (result) { 248 | CodeMirror.signal(this.cm, 'vim-keypress', key); 249 | e.preventDefault(); 250 | e.stopPropagation(); 251 | this.blockCursor.scheduleRedraw(); 252 | } 253 | 254 | this.updateStatus(); 255 | 256 | return !!result; 257 | } 258 | lastKeydown = '' 259 | useNextTextInput = false 260 | compositionText = '' 261 | }, 262 | { 263 | eventHandlers: { 264 | copy: function(e: ClipboardEvent, view: EditorView) { 265 | if (!this.waitForCopy) return; 266 | this.waitForCopy = false; 267 | Promise.resolve().then(() => { 268 | var cm = this.cm; 269 | var vim = cm.state.vim; 270 | if (!vim) return; 271 | if (vim.insertMode) { 272 | cm.setSelection(cm.getCursor(), cm.getCursor()); 273 | } else { 274 | cm.operation(() => { 275 | if (cm.curOp) cm.curOp.isVimOp = true; 276 | Vim.handleKey(cm, '', 'user'); 277 | }); 278 | } 279 | }); 280 | }, 281 | compositionstart: function(e: Event, view: EditorView) { 282 | this.useNextTextInput = true; 283 | CodeMirror.signal(this.cm, 'inputEvent', e); 284 | }, 285 | compositionupdate: function(e: Event, view: EditorView) { 286 | CodeMirror.signal(this.cm, 'inputEvent', e); 287 | }, 288 | compositionend: function(e: Event, view: EditorView) { 289 | CodeMirror.signal(this.cm, 'inputEvent', e); 290 | }, 291 | keypress: function(e: KeyboardEvent, view: EditorView) { 292 | CodeMirror.signal(this.cm, 'inputEvent', e); 293 | if (this.lastKeydown == "Dead") 294 | this.handleKey(e, view); 295 | }, 296 | keydown: function(e: KeyboardEvent, view: EditorView) { 297 | CodeMirror.signal(this.cm, 'inputEvent', e); 298 | this.lastKeydown = e.key; 299 | if ( 300 | this.lastKeydown == "Unidentified" 301 | || this.lastKeydown == "Process" 302 | || this.lastKeydown == "Dead" 303 | ) { 304 | this.useNextTextInput = true; 305 | } else { 306 | this.useNextTextInput = false; 307 | this.handleKey(e, view); 308 | } 309 | }, 310 | }, 311 | provide: () => { 312 | return [ 313 | EditorView.inputHandler.of((view, from, to, text) => { 314 | var cm = getCM(view); 315 | if (!cm) return false; 316 | var vim = cm.state?.vim; 317 | var vimPlugin = cm.state.vimPlugin; 318 | 319 | if (vim && !vim.insertMode && !cm.curOp?.isVimOp) { 320 | if (text === "\0\0") { 321 | return true; 322 | } 323 | CodeMirror.signal(cm, 'inputEvent', { 324 | type: "text", 325 | text, 326 | from, 327 | to, 328 | }); 329 | if (text.length == 1 && vimPlugin.useNextTextInput) { 330 | if (vim.expectLiteralNext && view.composing) { 331 | vimPlugin.compositionText = text; 332 | return false 333 | } 334 | if (vimPlugin.compositionText) { 335 | var toRemove = vimPlugin.compositionText; 336 | vimPlugin.compositionText = ''; 337 | var head = view.state.selection.main.head 338 | var textInDoc = view.state.sliceDoc(head - toRemove.length, head); 339 | if (toRemove === textInDoc) { 340 | var pos = cm.getCursor(); 341 | cm.replaceRange('', cm.posFromIndex(head - toRemove.length), pos); 342 | } 343 | } 344 | vimPlugin.handleKey({ 345 | key: text, 346 | preventDefault: ()=>{}, 347 | stopPropagation: ()=>{} 348 | }); 349 | forceEndComposition(view); 350 | return true; 351 | } 352 | } 353 | return false; 354 | }) 355 | ] 356 | }, 357 | 358 | decorations: (v) => v.decorations, 359 | } 360 | ); 361 | 362 | /** 363 | * removes contenteditable element and adds it back to end 364 | * IME composition in normal mode 365 | * this method works on all browsers except for Firefox on Linux 366 | * where we need to reset textContent of editor 367 | * (which doesn't work on other browsers) 368 | */ 369 | function forceEndComposition(view: EditorView) { 370 | var parent = view.scrollDOM.parentElement; 371 | if (!parent) return; 372 | 373 | if (FIREFOX_LINUX) { 374 | view.contentDOM.textContent = "\0\0"; 375 | view.contentDOM.dispatchEvent(new CustomEvent("compositionend")); 376 | return; 377 | } 378 | var sibling = view.scrollDOM.nextSibling; 379 | var selection = window.getSelection(); 380 | var savedSelection = selection && { 381 | anchorNode: selection.anchorNode, 382 | anchorOffset: selection.anchorOffset, 383 | focusNode: selection.focusNode, 384 | focusOffset: selection.focusOffset 385 | }; 386 | 387 | view.scrollDOM.remove(); 388 | parent.insertBefore(view.scrollDOM, sibling); 389 | try { 390 | if (savedSelection && selection) { 391 | selection.setPosition(savedSelection.anchorNode, savedSelection.anchorOffset); 392 | if (savedSelection.focusNode) { 393 | selection.extend(savedSelection.focusNode, savedSelection.focusOffset); 394 | } 395 | } 396 | } catch(e) { 397 | console.error(e); 398 | } 399 | view.focus(); 400 | view.contentDOM.dispatchEvent(new CustomEvent("compositionend")); 401 | } 402 | 403 | const matchMark = Decoration.mark({ class: "cm-searchMatch" }); 404 | 405 | const showVimPanel = StateEffect.define(); 406 | 407 | const vimPanelState = StateField.define({ 408 | create: () => false, 409 | update(value, tr) { 410 | for (let e of tr.effects) if (e.is(showVimPanel)) value = e.value; 411 | return value; 412 | }, 413 | provide: (f) => { 414 | return showPanel.from(f, (on) => (on ? createVimPanel : null)); 415 | }, 416 | }); 417 | 418 | function createVimPanel(view: EditorView) { 419 | let dom = document.createElement("div"); 420 | dom.className = "cm-vim-panel"; 421 | let cm = (view as EditorViewExtended).cm; 422 | if (cm.state.dialog) { 423 | dom.appendChild(cm.state.dialog); 424 | } 425 | return { top: false, dom }; 426 | } 427 | 428 | function statusPanel(view: EditorView): Panel { 429 | let dom = document.createElement("div"); 430 | dom.className = "cm-vim-panel"; 431 | let cm = (view as EditorViewExtended).cm; 432 | cm.state.statusbar = dom; 433 | cm.state.vimPlugin.updateStatus(); 434 | return { dom }; 435 | } 436 | 437 | export function vim(options: { status?: boolean } = {}): Extension { 438 | return [ 439 | vimStyle, 440 | vimPlugin, 441 | hideNativeSelection, 442 | options.status ? showPanel.of(statusPanel) : vimPanelState, 443 | ]; 444 | } 445 | 446 | export { CodeMirror, Vim }; 447 | 448 | export function getCM(view: EditorView): CodeMirror | null { 449 | return (view as EditorViewExtended).cm || null; 450 | } 451 | 452 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | import { CodeMirror } from "./cm_adapter" 2 | import {initVim} from "./vim" 3 | export type Vim = ReturnType 4 | export type vimState = { 5 | onPasteFn?: () => void, 6 | sel: {head: Pos, anchor: Pos}, 7 | insertModeReturn: boolean, 8 | visualBlock: boolean, 9 | marks: {[mark: string]: Marker}, 10 | visualMode: boolean, 11 | insertMode: boolean, 12 | pasteFn?: any, 13 | lastSelection: { 14 | anchorMark: Marker, 15 | headMark: Marker, 16 | visualLine: boolean, 17 | visualBlock: boolean, 18 | visualMode: boolean, 19 | anchor: Pos, 20 | head: Pos, 21 | }, 22 | searchState_?: SearchStateInterface, 23 | lastEditActionCommand: actionCommand|void, 24 | lastPastedText?: string, 25 | lastMotion?: MotionFn|null, 26 | options: {[optionName: string]: vimOption}, 27 | lastEditInputState: InputStateInterface|void, 28 | inputState: InputStateInterface, 29 | visualLine: boolean, 30 | insertModeRepeat?: number, 31 | lastHSPos: number, 32 | lastHPos: number, 33 | wasInVisualBlock?: boolean, 34 | insertEnd?: Marker, 35 | status: string, 36 | exMode?: boolean, 37 | mode?: string, 38 | expectLiteralNext?: boolean, 39 | } 40 | export type Marker = ReturnType 41 | export type LineHandle = ReturnType 42 | export type Pos = { line: number, ch: number, sticky?: string } 43 | 44 | export interface CM5Range { 45 | anchor: Pos, 46 | head: Pos, 47 | 48 | from(): Pos, 49 | empty(): boolean 50 | } 51 | export interface CM5RangeInterface { 52 | anchor: Pos, 53 | head: Pos, 54 | } 55 | 56 | export type RegisterController = ReturnType 57 | export type Register = ReturnType 58 | 59 | export type SearchArgs = { 60 | forward?: boolean, 61 | toJumplist?: boolean, 62 | wholeWordOnly?: boolean, 63 | querySrc?: string, 64 | } 65 | 66 | export type OperatorArgs = { 67 | repeat?: number, 68 | forward?: boolean, 69 | linewise?: boolean, 70 | fullLine?: boolean, 71 | registerName?: string|null, 72 | indentRight?: boolean, 73 | toLower?: boolean, 74 | shouldMoveCursor?: boolean, 75 | selectedCharacter?: string, 76 | lastSel?: { 77 | head: Pos, 78 | anchor: Pos, 79 | visualLine: boolean, 80 | visualBlock: boolean, 81 | }, 82 | keepCursor?: boolean; 83 | } 84 | // version of CodeMirror with vim state checked 85 | export type CodeMirrorV = CodeMirror & {state: {vim: vimState}} 86 | export type OperatorFn = (cm: CodeMirrorV, args: OperatorArgs, ranges: CM5RangeInterface[], oldAnchor: Pos, newHead?: Pos) => Pos|void 87 | export type vimOperators = { 88 | change(cm: CodeMirrorV, args: OperatorArgs, ranges: CM5RangeInterface[]): void, 89 | delete(cm: CodeMirrorV, args: OperatorArgs, ranges: CM5RangeInterface[]): void, 90 | indent(cm: CodeMirrorV, args: OperatorArgs, ranges: CM5RangeInterface[]): void, 91 | indentAuto(cm: CodeMirrorV, args: OperatorArgs, ranges: CM5RangeInterface[]): void, 92 | hardWrap(cm: CodeMirrorV, args: OperatorArgs, ranges: CM5RangeInterface[], oldAnchor: Pos): Pos|void, 93 | changeCase(cm: CodeMirrorV, args: OperatorArgs, ranges: CM5RangeInterface[], oldAnchor: Pos, newHead?: Pos): Pos|void, 94 | yank(cm: CodeMirrorV, args: OperatorArgs, ranges: CM5RangeInterface[], oldAnchor: Pos): Pos|void, 95 | } & { 96 | [key: string]: OperatorFn 97 | } 98 | 99 | export type ActionArgsPartial = { 100 | repeat?: number, 101 | forward?: boolean, 102 | head?: Pos, 103 | position?: string 104 | backtrack?: boolean, 105 | increase?: boolean, 106 | repeatIsExplicit?: boolean, 107 | indentRight?: boolean, 108 | selectedCharacter?: string, 109 | after?: boolean, 110 | matchIndent?: boolean, 111 | registerName?: string, 112 | isEdit?: boolean 113 | linewise?: boolean, 114 | insertAt?: string, 115 | blockwise?: boolean, 116 | keepSpaces?: boolean, 117 | replace?: boolean, 118 | keepCursor?: boolean 119 | } 120 | export type ActionArgs = ActionArgsPartial & {repeat: number}; 121 | 122 | export type ActionFn = (cm: CodeMirrorV, actionArgs: ActionArgs, vim: vimState) => void 123 | 124 | export type vimActions = { 125 | jumpListWalk(cm: CodeMirrorV, actionArgs: ActionArgs, vim: vimState): void, 126 | continuePaste(cm: CodeMirrorV, actionArgs: ActionArgs, vim: vimState, text: string, register: Register): void 127 | enterInsertMode(cm: CodeMirrorV, actionArgs: ActionArgsPartial, vum: vimState): void, 128 | } & { 129 | [key: string]: ActionFn 130 | } 131 | 132 | export type MotionArgsPartial = { 133 | repeat?: number, 134 | forward?: boolean, 135 | selectedCharacter?: string, 136 | linewise?: boolean, 137 | textObjectInner?: boolean, 138 | sameLine?: boolean, 139 | repeatOffset?: number, 140 | toJumplist?: boolean, 141 | inclusive?: boolean, 142 | wordEnd?: boolean, 143 | toFirstChar?:boolean, 144 | explicitRepeat?: boolean, 145 | bigWord?: boolean, 146 | repeatIsExplicit?: boolean, 147 | noRepeat?: boolean 148 | }; 149 | 150 | export type MotionArgs = MotionArgsPartial & {repeat: number}; 151 | 152 | export type MotionFn = (cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs, vim: vimState, inputState: InputStateInterface) => Pos|[Pos,Pos]|null|undefined 153 | export type vimMotions = { 154 | moveToTopLine(cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs): Pos 155 | moveToMiddleLine(cm: CodeMirrorV): Pos 156 | moveToBottomLine(cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs): Pos 157 | expandToLine(_cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs): Pos 158 | findNext(_cm: CodeMirrorV, _head: Pos, motionArgs: MotionArgs): Pos | undefined 159 | findAndSelectNextInclusive(cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs, vim: vimState, inputState: InputStateInterface): Pos|[Pos,Pos] | undefined 160 | goToMark(cm: CodeMirrorV, _head: Pos, motionArgs: MotionArgs, vim: vimState, inputState: InputStateInterface): Pos | undefined | null 161 | moveToOtherHighlightedEnd(cm: CodeMirrorV, _head: Pos, motionArgs: MotionArgs, vim: vimState): [Pos,Pos] 162 | jumpToMark(cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs, vim: vimState):Pos 163 | moveByCharacters(_cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs): Pos 164 | moveByLines(cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs, vim: vimState): Pos 165 | moveByDisplayLines(cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs, vim: vimState): Pos 166 | moveByPage(cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs): Pos 167 | moveByParagraph(cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs): Pos 168 | moveBySentence(cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs): Pos 169 | moveByScroll(cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs, vim: vimState): Pos | null 170 | moveByWords(cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs): Pos | undefined 171 | moveTillCharacter(cm: CodeMirrorV, _head: Pos, motionArgs: MotionArgs): Pos | null 172 | moveToCharacter(cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs): Pos 173 | moveToSymbol(cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs): Pos 174 | moveToColumn(cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs, vim: vimState): Pos 175 | moveToEol(cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs, vim: vimState): Pos 176 | moveToFirstNonWhiteSpaceCharacter(cm: CodeMirrorV, head: Pos): Pos 177 | moveToMatchedSymbol(cm: CodeMirrorV, head: Pos): Pos | undefined 178 | moveToStartOfLine(_cm: CodeMirrorV, head: Pos, motionArgs?: MotionArgs, vim?: vimState): Pos 179 | moveToLineOrEdgeOfDocument(cm: CodeMirrorV, _head: Pos, motionArgs: MotionArgs): Pos 180 | moveToStartOfDisplayLine(cm: CodeMirrorV): Pos 181 | moveToEndOfDisplayLine(cm: CodeMirrorV): Pos 182 | textObjectManipulation(cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs, vim: vimState): Pos | [Pos, Pos] | null 183 | repeatLastCharacterSearch(cm: CodeMirrorV, head: Pos, motionArgs: MotionArgs): Pos 184 | [key: string]: MotionFn 185 | } 186 | 187 | export type exCommandDefinition = { 188 | name: string, 189 | shortName?: string, 190 | possiblyAsync?: boolean, 191 | excludeFromCommandHistory?: boolean, 192 | argDelimiter?: string, 193 | type? : string, 194 | toKeys? : string, 195 | toInput?: string, 196 | user?: boolean, 197 | noremap?: boolean, 198 | }; 199 | 200 | export type optionCallback = (value?: string|undefined, cm?: CodeMirror) => any 201 | export type booleanOptionCallback = (value?: boolean, cm?: CodeMirror) => any 202 | export type numberOptionCallback = (value?: number, cm?: CodeMirror) => any 203 | export type stringOptionCallback = (value?: string, cm?: CodeMirror) => any 204 | 205 | export type vimOption = { 206 | type?: string, 207 | defaultValue?: unknown, 208 | callback?: optionCallback, 209 | value?: unknown 210 | } | { 211 | type: 'boolean', 212 | defaultValue?: boolean|null|undefined, 213 | callback?: booleanOptionCallback, 214 | value?: boolean 215 | }; 216 | export type defineOption1 = (( 217 | name: string, 218 | defaultValue: unknown, 219 | type: string, 220 | aliases?: string[]|undefined|null, 221 | callback?: optionCallback 222 | ) => void) 223 | export type defineOption2 = (( 224 | name: string, 225 | defaultValue: boolean|undefined|null, 226 | type: 'boolean', 227 | aliases?: string[]|undefined|null, 228 | callback?: booleanOptionCallback 229 | ) => void); 230 | 231 | 232 | export type ExFn = (cm: CodeMirrorV, params: ExParams)=> void; 233 | 234 | type allCommands = { 235 | keys: string, 236 | context?: string, 237 | interlaceInsertRepeat?: boolean, 238 | exitVisualBlock?: boolean, 239 | isEdit?: boolean, 240 | repeatOverride?: number, 241 | noremap?: boolean, 242 | } 243 | export type motionCommand = allCommands & { 244 | type: 'motion', 245 | motion: string, 246 | motionArgs?: MotionArgsPartial, 247 | repeatOverride?: number 248 | } 249 | export type operatorCommand = allCommands & { 250 | type: 'operator', 251 | operator: string, 252 | operatorArgs?: OperatorArgs 253 | } 254 | export type actionCommand = allCommands & { 255 | type: 'action', 256 | action: string, 257 | actionArgs?: ActionArgsPartial, 258 | motion?: string, 259 | operator?: string, 260 | interlaceInsertRepeat?: boolean 261 | } 262 | export type searchCommand = allCommands & { 263 | type: 'search', 264 | searchArgs: SearchArgs 265 | } 266 | export type operatorMotionCommand = allCommands & { 267 | type: 'operatorMotion', 268 | motion: string, 269 | operator: string, 270 | motionArgs?: MotionArgsPartial, 271 | operatorArgs?: OperatorArgs, 272 | operatorMotionArgs?: { 273 | visualLine?: boolean, 274 | }, 275 | } 276 | export type idleCommand = allCommands & { type: 'idle' } 277 | export type exCommand = allCommands & { type: 'ex' } 278 | export type keyToExCommand = allCommands & { type: 'keyToEx', exArgs: ExParams } 279 | export type keyToKeyCommand = allCommands & { toKeys: string, type: 'keyToKey' } 280 | 281 | export type vimKey = 282 | motionCommand 283 | | operatorCommand 284 | | actionCommand 285 | | searchCommand 286 | | operatorMotionCommand 287 | | idleCommand 288 | | exCommand 289 | | keyToExCommand 290 | | keyToKeyCommand; 291 | 292 | export type vimKeyMap = vimKey[]; 293 | 294 | export interface InputStateInterface { 295 | prefixRepeat: string[]; 296 | motionRepeat: string[]; 297 | operator: string| undefined | null; 298 | operatorArgs: OperatorArgs | undefined | null; 299 | motion: string | undefined | null; 300 | motionArgs: MotionArgs | null; 301 | keyBuffer: string[]; 302 | registerName?: string; 303 | changeQueue: null | { inserted: string, removed: string[]}; 304 | operatorShortcut?: string; 305 | selectedCharacter?: string; 306 | repeatOverride?: number; 307 | changeQueueList?: (InputStateInterface["changeQueue"])[]; 308 | pushRepeatDigit(n: string): void; 309 | getRepeat(): number; 310 | } 311 | export interface SearchStateInterface { 312 | setReversed(reversed: boolean): void; 313 | isReversed(): boolean|undefined; 314 | getQuery(): RegExp; 315 | setQuery(query: string|RegExp): void; 316 | highlightTimeout: number|undefined; 317 | getOverlay(): { 318 | query: RegExp, 319 | }; 320 | getScrollbarAnnotate(): any; 321 | setScrollbarAnnotate(query: RegExp| null): void; 322 | setOverlay(overlay: {query: RegExp}|null): void; 323 | } 324 | 325 | export type exCommandArgs = { 326 | callback?: (() => void) | undefined; 327 | input?: string | undefined; 328 | line?: string | undefined; 329 | commandName?: string | undefined; 330 | argString?: string; 331 | args?: string[]; 332 | }; 333 | 334 | export type vimExCommands = { 335 | colorscheme(cm: CodeMirrorV, params: vimExCommandsParams): void, 336 | map(cm: CodeMirrorV, params: vimExCommandsParams, ctx: string): void, 337 | imap(cm: CodeMirrorV, params: vimExCommandsParams): void, 338 | nmap(cm: CodeMirrorV, params: vimExCommandsParams): void, 339 | vmap(cm: CodeMirrorV, params: vimExCommandsParams): void, 340 | unmap(cm: CodeMirrorV, params: vimExCommandsParams, ctx: string): void, 341 | move(cm: CodeMirrorV, params: vimExCommandsParams): void, 342 | set(cm: CodeMirrorV, params: vimExCommandsParams): void, 343 | setlocal(cm: CodeMirrorV, params: vimExCommandsParams): void, 344 | setglobal(cm: CodeMirrorV, params: vimExCommandsParams): void, 345 | registers(cm: CodeMirrorV, params: vimExCommandsParams): void, 346 | sort(cm: CodeMirrorV, params: vimExCommandsParams): void, 347 | vglobal(cm: CodeMirrorV, params: vimExCommandsParams): void, 348 | global(cm: CodeMirrorV, params: vimExCommandsParams): void, 349 | substitute(cm: CodeMirrorV, params: vimExCommandsParams): void, 350 | redo(cm: CodeMirrorV): void, 351 | undo(cm: CodeMirrorV): void, 352 | write(cm: CodeMirrorV & {save?: Function}): void, 353 | nohlsearch(cm: CodeMirrorV): void, 354 | yank(cm: CodeMirrorV): void, 355 | delete(cm: CodeMirrorV, params: vimExCommandsParams): void, 356 | join(cm: CodeMirrorV, params: vimExCommandsParams): void, 357 | delmarks(cm: CodeMirrorV, params: vimExCommandsParams): void, 358 | [key: string]:(cm: CodeMirrorV, params: vimExCommandsParams, ctx: string)=> void, 359 | } 360 | 361 | type vimExCommandsParams = { 362 | args?: string[], 363 | input?: string, 364 | line?: number, 365 | setCfg?: {scope?: string}, 366 | argString?: string, 367 | lineEnd?: number, 368 | commandName?: string, 369 | callback?: () => any, 370 | selectionLine?: number, 371 | selectionLineEnd?: number 372 | } 373 | 374 | type InsertModeKey = InstanceType 375 | export type InsertModeChanges = { 376 | changes: (InsertModeKey|string|[string,number?])[]; 377 | expectCursorActivityForChange: boolean; 378 | visualBlock?: number, 379 | maybeReset?: boolean, 380 | ignoreCount?: number, 381 | repeatOverride?: number, 382 | } 383 | 384 | export type ExParams = { 385 | commandName: string, 386 | argString: string, 387 | input: string, 388 | args?: string[], 389 | 390 | line: number, 391 | lineEnd?: number, 392 | selectionLine: number, 393 | selectionLineEnd?: number, 394 | 395 | setCfg?: Object, 396 | callback?: () => void, 397 | } 398 | 399 | export type PromptOptions = { 400 | onClose?: Function; 401 | prefix: string|HTMLElement; 402 | desc?: string|HTMLElement; 403 | onKeyUp?: Function; 404 | onKeyDown: Function; 405 | value?: string; 406 | selectValueOnOpen?: boolean; 407 | } 408 | 409 | 410 | declare global { 411 | function isNaN(v: any): v is Exclude; 412 | interface String { 413 | trimStart(): string 414 | } 415 | } -------------------------------------------------------------------------------- /test/webtest-vim.js: -------------------------------------------------------------------------------- 1 | import { EditorView, basicSetup } from "codemirror"; 2 | import { CodeMirror, Vim, vim } from ".."; 3 | import { xml } from "@codemirror/lang-xml"; 4 | import { javascript } from "@codemirror/lang-javascript"; 5 | import {vimTests} from "./vim_test.js" 6 | import { indentUnit } from "@codemirror/language"; 7 | import { EditorState, Compartment } from "@codemirror/state"; 8 | import {indentWithTab} from "@codemirror/commands"; 9 | import { keymap, drawSelection } from "@codemirror/view"; 10 | 11 | import * as View from "@codemirror/view"; 12 | 13 | /**@type {any}*/ 14 | var disabled = { 15 | vim_ex_set_filetype: 1, 16 | vim_ex_set_filetype_null: 1, 17 | 18 | vim_zb_to_bottom: 1, 19 | vim_zt_to_top: 1, 20 | "vim_zb { 24 | /**@type {HTMLDivElement}*/ 25 | var root; 26 | var Pos = CodeMirror.Pos; 27 | function addRoot() { 28 | if (!root) { 29 | root = document.createElement("div"); 30 | root.id = "testground"; 31 | root.style.height = "300px"; 32 | root.style.position = "fixed"; 33 | root.style.top = "100px"; 34 | root.style.right = "100px"; 35 | root.style.width = "500px"; 36 | } 37 | document.body.appendChild(root); 38 | } 39 | addRoot(); 40 | /**@type {EditorView|null}*/ 41 | var lastView; 42 | function CM(place, options) { 43 | addRoot(); 44 | if (lastView) lastView.destroy(); 45 | 46 | var view = new EditorView({ 47 | doc: options.value, 48 | extensions: [ 49 | vim({}), 50 | basicSetup, 51 | options.mode == "xml" ? xml() : javascript(), 52 | EditorState.tabSize.of(options.tabSize || options.indentUnit || 4), 53 | indentUnit.of( 54 | options.indentWithTabs ? "\t" : " ".repeat(options.indentUnit || 2) 55 | ), 56 | options.lineWrapping && EditorView.lineWrapping, 57 | keymap.of([indentWithTab]), 58 | ].filter(Boolean), 59 | parent: root, 60 | }); 61 | lastView = view; 62 | window.view = view; 63 | 64 | view.cm.getInputField()._handleInputEventForTest = function (text) { 65 | view.cm.replaceSelection(text); 66 | }; 67 | 68 | view.dom.style.backgroundColor = "white"; 69 | view.cm.setSize(420, 300); 70 | // without calling refresh cursor movement commands of codemirror 6 do not work 71 | view.cm.refresh(); 72 | 73 | return view.cm; 74 | } 75 | 76 | Object.defineProperty(CM, "isMac", { 77 | get() { return CodeMirror.isMac }, 78 | set(value) { CodeMirror.isMac = value }, 79 | configurable: true, 80 | }); 81 | CM.defineMode = () => {}; 82 | CM.on = CodeMirror.on; 83 | CM.off = CodeMirror.off; 84 | CM.Vim = Vim; 85 | CM.Pos = function (a, b) { 86 | return new Pos(a, b); 87 | }; 88 | CM.commands = CodeMirror.commands; 89 | // workaround for cm6 not indenting after unclosed { 90 | CM.commands.newlineAndIndent = function (cm) { 91 | var oldCursor = cm.getCursor(); 92 | var oldLine = cm.getLine(oldCursor.line).slice(0, oldCursor.ch); 93 | var indent = /^\s*/.exec(oldLine)?.[0]; 94 | if (/[{[(]$/.test(oldLine)) { 95 | if (cm.getOption("indentWithTabs")) { 96 | indent += "\t"; 97 | } else { 98 | indent += " ".repeat(cm.getOption("indentUnit")); 99 | } 100 | } 101 | cm.replaceSelection("\n" + indent); 102 | }; 103 | var onlyType = /\bonly=(\w+)\b/.exec(location.search)?.[1]; 104 | /** 105 | * @param {string} name 106 | * @param {() => void} fn 107 | */ 108 | function transformTest(name, fn) { 109 | if (disabled[name]) { 110 | return it.skip(name, function () {}); 111 | } 112 | if (onlyType && localStorage[name] && localStorage[name] !== onlyType) 113 | return; 114 | return it(name, async function () { 115 | if (onlyType) localStorage[name] = "fail"; 116 | await fn(); 117 | if (onlyType) localStorage[name] = "pass"; 118 | if (lastView) { 119 | // TODO without calling destroy old cm instances throw errors and break the test runner 120 | lastView.destroy(); 121 | lastView = null; 122 | } 123 | }); 124 | } 125 | vimTests(CM, transformTest); 126 | 127 | // extra tests 128 | it("should update cursor blinkrate", function() { 129 | 130 | let compartement = new Compartment(); 131 | var view = new EditorView({ 132 | doc: "hello world", 133 | extensions: [ 134 | vim({ 135 | status: true 136 | }), 137 | basicSetup, 138 | compartement.of([ 139 | drawSelection({cursorBlinkRate: 100}) 140 | ]) 141 | ].filter(Boolean), 142 | parent: root, 143 | }); 144 | 145 | let vimCursorLayer = view.dom.querySelector(".cm-vimCursorLayer"); 146 | if (!View.getDrawSelectionConfig) { 147 | eq(vimCursorLayer.style.animationDuration, "1200ms"); 148 | return; 149 | } 150 | eq(vimCursorLayer.style.animationDuration, "100ms"); 151 | view.dispatch({ 152 | effects: compartement.reconfigure(drawSelection({cursorBlinkRate: 1000})) 153 | }); 154 | vimCursorLayer = view.dom.querySelector(".cm-vimCursorLayer"); 155 | eq(vimCursorLayer.style.animationDuration, "1000ms"); 156 | }) 157 | }); 158 | 159 | 160 | 161 | 162 | function eq(a, b, _reason) { 163 | if(a != b) 164 | throw failure("Expected " + a + " to be equal to " + b, eq); 165 | } 166 | function is(a) { 167 | if (!a) throw failure("Expected " + a + " to be truthy", is); 168 | } 169 | function failure(message, root) { 170 | var error = new Error(message); 171 | if (Error.captureStackTrace) 172 | Error.captureStackTrace(error, root); 173 | return error; 174 | } 175 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | // "module": "commonjs", 4 | "noImplicitAny": false, 5 | // "noEmit": true, 6 | "declaration": true, 7 | "emitDeclarationOnly": true, 8 | // "lib": ["es2019", "DOM"] 9 | "outDir": "./out", 10 | "allowJs": true, 11 | "checkJs": true, 12 | "lib": ["es6", "dom", "scripthost"], 13 | "types": ["mocha"], 14 | "stripInternal": true, 15 | "typeRoots": ["./node_modules/@types"], 16 | "noUnusedLocals": true, 17 | "strict": true, 18 | "target": "es6", 19 | "module": "es2020", 20 | "newLine": "lf", 21 | "moduleResolution": "node", 22 | }, 23 | "include": [ 24 | "src/*.ts", 25 | "src/*.js" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /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.26.2": 6 | version "7.26.2" 7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" 8 | integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== 9 | dependencies: 10 | "@babel/helper-validator-identifier" "^7.25.9" 11 | js-tokens "^4.0.0" 12 | picocolors "^1.0.0" 13 | 14 | "@babel/helper-validator-identifier@^7.25.9": 15 | version "7.25.9" 16 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" 17 | integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== 18 | 19 | "@bazel/runfiles@^6.3.1": 20 | version "6.3.1" 21 | resolved "https://registry.yarnpkg.com/@bazel/runfiles/-/runfiles-6.3.1.tgz#3f8824b2d82853377799d42354b4df78ab0ace0b" 22 | integrity sha512-1uLNT5NZsUVIGS4syuHwTzZ8HycMPyr6POA3FCE4GbMtc4rhoJk8aZKtNIRthJYfL+iioppi+rTfH3olMPr9nA== 23 | 24 | "@codemirror/autocomplete@^6.0.0": 25 | version "6.18.6" 26 | resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.18.6.tgz#de26e864a1ec8192a1b241eb86addbb612964ddb" 27 | integrity sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg== 28 | dependencies: 29 | "@codemirror/language" "^6.0.0" 30 | "@codemirror/state" "^6.0.0" 31 | "@codemirror/view" "^6.17.0" 32 | "@lezer/common" "^1.0.0" 33 | 34 | "@codemirror/buildhelper@^1.0.2": 35 | version "1.0.2" 36 | resolved "https://registry.yarnpkg.com/@codemirror/buildhelper/-/buildhelper-1.0.2.tgz#3dc00d647088af6a9191a44e3ea49ee64180d439" 37 | integrity sha512-aVewtDPZptq9dTvYqIjpu9HTEmMaKAE4VL22z5E1ycgY5e1LdAiRd5YYjqzQeqLjxpWsHy+emO3n5UUcxpUmSg== 38 | dependencies: 39 | "@lezer/generator" "^1.0.0" 40 | "@marijn/buildtool" "^1.0.0" 41 | "@marijn/testtool" "^0.1.3" 42 | 43 | "@codemirror/commands@^6.0.0": 44 | version "6.8.0" 45 | resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.8.0.tgz#92f200b66f852939bd6ebb90d48c2d9e9c813d64" 46 | integrity sha512-q8VPEFaEP4ikSlt6ZxjB3zW72+7osfAYW9i8Zu943uqbKuz6utc1+F170hyLUCUltXORjQXRyYQNfkckzA/bPQ== 47 | dependencies: 48 | "@codemirror/language" "^6.0.0" 49 | "@codemirror/state" "^6.4.0" 50 | "@codemirror/view" "^6.27.0" 51 | "@lezer/common" "^1.1.0" 52 | 53 | "@codemirror/lang-javascript@6.x.x": 54 | version "6.2.3" 55 | resolved "https://registry.yarnpkg.com/@codemirror/lang-javascript/-/lang-javascript-6.2.3.tgz#d705c359dc816afcd3bcdf120a559f83d31d4cda" 56 | integrity sha512-8PR3vIWg7pSu7ur8A07pGiYHgy3hHj+mRYRCSG8q+mPIrl0F02rgpGv+DsQTHRTc30rydOsf5PZ7yjKFg2Ackw== 57 | dependencies: 58 | "@codemirror/autocomplete" "^6.0.0" 59 | "@codemirror/language" "^6.6.0" 60 | "@codemirror/lint" "^6.0.0" 61 | "@codemirror/state" "^6.0.0" 62 | "@codemirror/view" "^6.17.0" 63 | "@lezer/common" "^1.0.0" 64 | "@lezer/javascript" "^1.0.0" 65 | 66 | "@codemirror/lang-xml@6.x.x": 67 | version "6.1.0" 68 | resolved "https://registry.yarnpkg.com/@codemirror/lang-xml/-/lang-xml-6.1.0.tgz#e3e786e1a89fdc9520efe75c1d6d3de1c40eb91c" 69 | integrity sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg== 70 | dependencies: 71 | "@codemirror/autocomplete" "^6.0.0" 72 | "@codemirror/language" "^6.4.0" 73 | "@codemirror/state" "^6.0.0" 74 | "@codemirror/view" "^6.0.0" 75 | "@lezer/common" "^1.0.0" 76 | "@lezer/xml" "^1.0.0" 77 | 78 | "@codemirror/language@6.x.x", "@codemirror/language@^6.0.0", "@codemirror/language@^6.4.0", "@codemirror/language@^6.6.0": 79 | version "6.11.0" 80 | resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.11.0.tgz#5ae90972601497f4575f30811519d720bf7232c9" 81 | integrity sha512-A7+f++LodNNc1wGgoRDTt78cOwWm9KVezApgjOMp1W4hM0898nsqBXwF+sbePE7ZRcjN7Sa1Z5m2oN27XkmEjQ== 82 | dependencies: 83 | "@codemirror/state" "^6.0.0" 84 | "@codemirror/view" "^6.23.0" 85 | "@lezer/common" "^1.1.0" 86 | "@lezer/highlight" "^1.0.0" 87 | "@lezer/lr" "^1.0.0" 88 | style-mod "^4.0.0" 89 | 90 | "@codemirror/lint@^6.0.0": 91 | version "6.8.4" 92 | resolved "https://registry.yarnpkg.com/@codemirror/lint/-/lint-6.8.4.tgz#7d8aa5d1a6dec89ffcc23ad45ddca2e12e90982d" 93 | integrity sha512-u4q7PnZlJUojeRe8FJa/njJcMctISGgPQ4PnWsd9268R4ZTtU+tfFYmwkBvgcrK2+QQ8tYFVALVb5fVJykKc5A== 94 | dependencies: 95 | "@codemirror/state" "^6.0.0" 96 | "@codemirror/view" "^6.35.0" 97 | crelt "^1.0.5" 98 | 99 | "@codemirror/search@^6.0.0": 100 | version "6.5.10" 101 | resolved "https://registry.yarnpkg.com/@codemirror/search/-/search-6.5.10.tgz#7367bfc88094d078b91c752bc74140fb565b55ee" 102 | integrity sha512-RMdPdmsrUf53pb2VwflKGHEe1XVM07hI7vV2ntgw1dmqhimpatSJKva4VA9h4TLUDOD4EIF02201oZurpnEFsg== 103 | dependencies: 104 | "@codemirror/state" "^6.0.0" 105 | "@codemirror/view" "^6.0.0" 106 | crelt "^1.0.5" 107 | 108 | "@codemirror/state@^6.0.0", "@codemirror/state@^6.4.0", "@codemirror/state@^6.5.0": 109 | version "6.5.2" 110 | resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.5.2.tgz#8eca3a64212a83367dc85475b7d78d5c9b7076c6" 111 | integrity sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA== 112 | dependencies: 113 | "@marijn/find-cluster-break" "^1.0.0" 114 | 115 | "@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0", "@codemirror/view@^6.27.0", "@codemirror/view@^6.35.0": 116 | version "6.36.4" 117 | resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.36.4.tgz#d47d38b92a22cc40647bfb9cc97944e13d44942d" 118 | integrity sha512-ZQ0V5ovw/miKEXTvjgzRyjnrk9TwriUB1k4R5p7uNnHR9Hus+D1SXHGdJshijEzPFjU25xea/7nhIeSqYFKdbA== 119 | dependencies: 120 | "@codemirror/state" "^6.5.0" 121 | style-mod "^4.1.0" 122 | w3c-keyname "^2.2.4" 123 | 124 | "@esbuild/aix-ppc64@0.25.1": 125 | version "0.25.1" 126 | resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz#c33cf6bbee34975626b01b80451cbb72b4c6c91d" 127 | integrity sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ== 128 | 129 | "@esbuild/android-arm64@0.25.1": 130 | version "0.25.1" 131 | resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz#ea766015c7d2655164f22100d33d7f0308a28d6d" 132 | integrity sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA== 133 | 134 | "@esbuild/android-arm@0.25.1": 135 | version "0.25.1" 136 | resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.1.tgz#e84d2bf2fe2e6177a0facda3a575b2139fd3cb9c" 137 | integrity sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q== 138 | 139 | "@esbuild/android-x64@0.25.1": 140 | version "0.25.1" 141 | resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.1.tgz#58337bee3bc6d78d10425e5500bd11370cfdfbed" 142 | integrity sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw== 143 | 144 | "@esbuild/darwin-arm64@0.25.1": 145 | version "0.25.1" 146 | resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz#a46805c1c585d451aa83be72500bd6e8495dd591" 147 | integrity sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ== 148 | 149 | "@esbuild/darwin-x64@0.25.1": 150 | version "0.25.1" 151 | resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz#0643e003bb238c63fc93ddbee7d26a003be3cd98" 152 | integrity sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA== 153 | 154 | "@esbuild/freebsd-arm64@0.25.1": 155 | version "0.25.1" 156 | resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz#cff18da5469c09986b93e87979de5d6872fe8f8e" 157 | integrity sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A== 158 | 159 | "@esbuild/freebsd-x64@0.25.1": 160 | version "0.25.1" 161 | resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz#362fc09c2de14987621c1878af19203c46365dde" 162 | integrity sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww== 163 | 164 | "@esbuild/linux-arm64@0.25.1": 165 | version "0.25.1" 166 | resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz#aa90d5b02efc97a271e124e6d1cea490634f7498" 167 | integrity sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ== 168 | 169 | "@esbuild/linux-arm@0.25.1": 170 | version "0.25.1" 171 | resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz#dfcefcbac60a20918b19569b4b657844d39db35a" 172 | integrity sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ== 173 | 174 | "@esbuild/linux-ia32@0.25.1": 175 | version "0.25.1" 176 | resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz#6f9527077ccb7953ed2af02e013d4bac69f13754" 177 | integrity sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ== 178 | 179 | "@esbuild/linux-loong64@0.25.1": 180 | version "0.25.1" 181 | resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz#287d2412a5456e5860c2839d42a4b51284d1697c" 182 | integrity sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg== 183 | 184 | "@esbuild/linux-mips64el@0.25.1": 185 | version "0.25.1" 186 | resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz#530574b9e1bc5d20f7a4f44c5f045e26f3783d57" 187 | integrity sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg== 188 | 189 | "@esbuild/linux-ppc64@0.25.1": 190 | version "0.25.1" 191 | resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz#5d7e6b283a0b321ea42c6bc0abeb9eb99c1f5589" 192 | integrity sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg== 193 | 194 | "@esbuild/linux-riscv64@0.25.1": 195 | version "0.25.1" 196 | resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz#14fa0cd073c26b4ee2465d18cd1e18eea7859fa8" 197 | integrity sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ== 198 | 199 | "@esbuild/linux-s390x@0.25.1": 200 | version "0.25.1" 201 | resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz#e677b4b9d1b384098752266ccaa0d52a420dc1aa" 202 | integrity sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ== 203 | 204 | "@esbuild/linux-x64@0.25.1": 205 | version "0.25.1" 206 | resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz#f1c796b78fff5ce393658313e8c58613198d9954" 207 | integrity sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA== 208 | 209 | "@esbuild/netbsd-arm64@0.25.1": 210 | version "0.25.1" 211 | resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz#0d280b7dfe3973f111b02d5fe9f3063b92796d29" 212 | integrity sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g== 213 | 214 | "@esbuild/netbsd-x64@0.25.1": 215 | version "0.25.1" 216 | resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz#be663893931a4bb3f3a009c5cc24fa9681cc71c0" 217 | integrity sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA== 218 | 219 | "@esbuild/openbsd-arm64@0.25.1": 220 | version "0.25.1" 221 | resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz#d9021b884233673a05dc1cc26de0bf325d824217" 222 | integrity sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg== 223 | 224 | "@esbuild/openbsd-x64@0.25.1": 225 | version "0.25.1" 226 | resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz#9f1dc1786ed2e2938c404b06bcc48be9a13250de" 227 | integrity sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw== 228 | 229 | "@esbuild/sunos-x64@0.25.1": 230 | version "0.25.1" 231 | resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz#89aac24a4b4115959b3f790192cf130396696c27" 232 | integrity sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg== 233 | 234 | "@esbuild/win32-arm64@0.25.1": 235 | version "0.25.1" 236 | resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz#354358647a6ea98ea6d243bf48bdd7a434999582" 237 | integrity sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ== 238 | 239 | "@esbuild/win32-ia32@0.25.1": 240 | version "0.25.1" 241 | resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz#8cea7340f2647eba951a041dc95651e3908cd4cb" 242 | integrity sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A== 243 | 244 | "@esbuild/win32-x64@0.25.1": 245 | version "0.25.1" 246 | resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz#7d79922cb2d88f9048f06393dbf62d2e4accb584" 247 | integrity sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg== 248 | 249 | "@jridgewell/sourcemap-codec@^1.5.0": 250 | version "1.5.0" 251 | resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" 252 | integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== 253 | 254 | "@lezer/common@^1.0.0", "@lezer/common@^1.1.0", "@lezer/common@^1.2.0": 255 | version "1.2.3" 256 | resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.2.3.tgz#138fcddab157d83da557554851017c6c1e5667fd" 257 | integrity sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA== 258 | 259 | "@lezer/generator@^1.0.0": 260 | version "1.7.2" 261 | resolved "https://registry.yarnpkg.com/@lezer/generator/-/generator-1.7.2.tgz#a491c91eb9f117ea803e748fa97574514156a2a3" 262 | integrity sha512-CwgULPOPPmH54tv4gki18bElLCdJ1+FBC+nGVSVD08vFWDsMjS7KEjNTph9JOypDnet90ujN3LzQiW3CyVODNQ== 263 | dependencies: 264 | "@lezer/common" "^1.1.0" 265 | "@lezer/lr" "^1.3.0" 266 | 267 | "@lezer/highlight@^1.0.0", "@lezer/highlight@^1.1.3": 268 | version "1.2.1" 269 | resolved "https://registry.yarnpkg.com/@lezer/highlight/-/highlight-1.2.1.tgz#596fa8f9aeb58a608be0a563e960c373cbf23f8b" 270 | integrity sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA== 271 | dependencies: 272 | "@lezer/common" "^1.0.0" 273 | 274 | "@lezer/javascript@^1.0.0": 275 | version "1.4.21" 276 | resolved "https://registry.yarnpkg.com/@lezer/javascript/-/javascript-1.4.21.tgz#8ebf7d1f891c70e3d00864f5a03ac42c75d19492" 277 | integrity sha512-lL+1fcuxWYPURMM/oFZLEDm0XuLN128QPV+VuGtKpeaOGdcl9F2LYC3nh1S9LkPqx9M0mndZFdXCipNAZpzIkQ== 278 | dependencies: 279 | "@lezer/common" "^1.2.0" 280 | "@lezer/highlight" "^1.1.3" 281 | "@lezer/lr" "^1.3.0" 282 | 283 | "@lezer/lr@^1.0.0", "@lezer/lr@^1.3.0": 284 | version "1.4.2" 285 | resolved "https://registry.yarnpkg.com/@lezer/lr/-/lr-1.4.2.tgz#931ea3dea8e9de84e90781001dae30dea9ff1727" 286 | integrity sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA== 287 | dependencies: 288 | "@lezer/common" "^1.0.0" 289 | 290 | "@lezer/xml@^1.0.0": 291 | version "1.0.6" 292 | resolved "https://registry.yarnpkg.com/@lezer/xml/-/xml-1.0.6.tgz#908c203923288f854eb8e2f4d9b06c437e8610b9" 293 | integrity sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww== 294 | dependencies: 295 | "@lezer/common" "^1.2.0" 296 | "@lezer/highlight" "^1.0.0" 297 | "@lezer/lr" "^1.0.0" 298 | 299 | "@marijn/buildtool@^1.0.0": 300 | version "1.1.0" 301 | resolved "https://registry.yarnpkg.com/@marijn/buildtool/-/buildtool-1.1.0.tgz#c0808b8c0fe48bb698bd5d2a9f4090f926e2d4d9" 302 | integrity sha512-4MplEHnyta/atrMFM8+Fn0fB5XVvM9umlUvqc9q9qwiV4uceGYW/nXIYMT2A27uxXxLoJX9Zb2rZdtGojvWpMw== 303 | dependencies: 304 | "@types/mocha" "^9.1.1" 305 | acorn "^8.10.0" 306 | acorn-walk "^8.2.0" 307 | rollup "^4.8.0" 308 | rollup-plugin-dts "^6.1.0" 309 | typescript "^5.3.3" 310 | 311 | "@marijn/find-cluster-break@^1.0.0": 312 | version "1.0.2" 313 | resolved "https://registry.yarnpkg.com/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz#775374306116d51c0c500b8c4face0f9a04752d8" 314 | integrity sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g== 315 | 316 | "@marijn/testtool@^0.1.3": 317 | version "0.1.3" 318 | resolved "https://registry.yarnpkg.com/@marijn/testtool/-/testtool-0.1.3.tgz#112e1d9788e3129797d81fc5b1723c26fecee101" 319 | integrity sha512-Rdi3amfFyTZoUXxMc95k9x9Ult+DtQSuOHsZwN5wtIKQ5JdXQaErgtWgGjW0Fpg4Rj0YrUCpWOj0VqsumAt5JA== 320 | dependencies: 321 | esmoduleserve "^0.2.0" 322 | ist "^1.1.7" 323 | mocha "^10.0.0" 324 | selenium-webdriver "^4.10.0" 325 | serve-static "^1.14.1" 326 | 327 | "@rollup/rollup-android-arm-eabi@4.36.0": 328 | version "4.36.0" 329 | resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.36.0.tgz#6229c36cddc172c468f53107f2b7aebe2585609b" 330 | integrity sha512-jgrXjjcEwN6XpZXL0HUeOVGfjXhPyxAbbhD0BlXUB+abTOpbPiN5Wb3kOT7yb+uEtATNYF5x5gIfwutmuBA26w== 331 | 332 | "@rollup/rollup-android-arm64@4.36.0": 333 | version "4.36.0" 334 | resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.36.0.tgz#d38163692d0729bd64a026c13749ecac06f847e8" 335 | integrity sha512-NyfuLvdPdNUfUNeYKUwPwKsE5SXa2J6bCt2LdB/N+AxShnkpiczi3tcLJrm5mA+eqpy0HmaIY9F6XCa32N5yzg== 336 | 337 | "@rollup/rollup-darwin-arm64@4.36.0": 338 | version "4.36.0" 339 | resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.36.0.tgz#82601b8ff81f3dbaef28017aa3d0e9709edc99c0" 340 | integrity sha512-JQ1Jk5G4bGrD4pWJQzWsD8I1n1mgPXq33+/vP4sk8j/z/C2siRuxZtaUA7yMTf71TCZTZl/4e1bfzwUmFb3+rw== 341 | 342 | "@rollup/rollup-darwin-x64@4.36.0": 343 | version "4.36.0" 344 | resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.36.0.tgz#0e961354fb2bf26d691810ca61dc861d9a1e94b2" 345 | integrity sha512-6c6wMZa1lrtiRsbDziCmjE53YbTkxMYhhnWnSW8R/yqsM7a6mSJ3uAVT0t8Y/DGt7gxUWYuFM4bwWk9XCJrFKA== 346 | 347 | "@rollup/rollup-freebsd-arm64@4.36.0": 348 | version "4.36.0" 349 | resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.36.0.tgz#6aee296cd6b8c39158d377c89b7e0cd0851dd7c7" 350 | integrity sha512-KXVsijKeJXOl8QzXTsA+sHVDsFOmMCdBRgFmBb+mfEb/7geR7+C8ypAml4fquUt14ZyVXaw2o1FWhqAfOvA4sg== 351 | 352 | "@rollup/rollup-freebsd-x64@4.36.0": 353 | version "4.36.0" 354 | resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.36.0.tgz#432e49d93942225ac1b4d98254a6fb6ca0afcd17" 355 | integrity sha512-dVeWq1ebbvByI+ndz4IJcD4a09RJgRYmLccwlQ8bPd4olz3Y213uf1iwvc7ZaxNn2ab7bjc08PrtBgMu6nb4pQ== 356 | 357 | "@rollup/rollup-linux-arm-gnueabihf@4.36.0": 358 | version "4.36.0" 359 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.36.0.tgz#a66910c6c63b46d45f239528ad5509097f8df885" 360 | integrity sha512-bvXVU42mOVcF4le6XSjscdXjqx8okv4n5vmwgzcmtvFdifQ5U4dXFYaCB87namDRKlUL9ybVtLQ9ztnawaSzvg== 361 | 362 | "@rollup/rollup-linux-arm-musleabihf@4.36.0": 363 | version "4.36.0" 364 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.36.0.tgz#1cfadc70d44501b0a58615a460cf1b6ec8cfddf3" 365 | integrity sha512-JFIQrDJYrxOnyDQGYkqnNBtjDwTgbasdbUiQvcU8JmGDfValfH1lNpng+4FWlhaVIR4KPkeddYjsVVbmJYvDcg== 366 | 367 | "@rollup/rollup-linux-arm64-gnu@4.36.0": 368 | version "4.36.0" 369 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.36.0.tgz#d32e42b25216472dfdc5cb7df6a37667766d3855" 370 | integrity sha512-KqjYVh3oM1bj//5X7k79PSCZ6CvaVzb7Qs7VMWS+SlWB5M8p3FqufLP9VNp4CazJ0CsPDLwVD9r3vX7Ci4J56A== 371 | 372 | "@rollup/rollup-linux-arm64-musl@4.36.0": 373 | version "4.36.0" 374 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.36.0.tgz#d742917d61880941be26ff8d3352d935139188b9" 375 | integrity sha512-QiGnhScND+mAAtfHqeT+cB1S9yFnNQ/EwCg5yE3MzoaZZnIV0RV9O5alJAoJKX/sBONVKeZdMfO8QSaWEygMhw== 376 | 377 | "@rollup/rollup-linux-loongarch64-gnu@4.36.0": 378 | version "4.36.0" 379 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.36.0.tgz#9ad12d1a5d3abf4ecb90fbe1a49249608cee8cbb" 380 | integrity sha512-1ZPyEDWF8phd4FQtTzMh8FQwqzvIjLsl6/84gzUxnMNFBtExBtpL51H67mV9xipuxl1AEAerRBgBwFNpkw8+Lg== 381 | 382 | "@rollup/rollup-linux-powerpc64le-gnu@4.36.0": 383 | version "4.36.0" 384 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.36.0.tgz#c3ca6f5ce4a8b785dd450113660d9529a75fdf2a" 385 | integrity sha512-VMPMEIUpPFKpPI9GZMhJrtu8rxnp6mJR3ZzQPykq4xc2GmdHj3Q4cA+7avMyegXy4n1v+Qynr9fR88BmyO74tg== 386 | 387 | "@rollup/rollup-linux-riscv64-gnu@4.36.0": 388 | version "4.36.0" 389 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.36.0.tgz#05eb5e71db5b5b1d1a3428265a63c5f6f8a1e4b8" 390 | integrity sha512-ttE6ayb/kHwNRJGYLpuAvB7SMtOeQnVXEIpMtAvx3kepFQeowVED0n1K9nAdraHUPJ5hydEMxBpIR7o4nrm8uA== 391 | 392 | "@rollup/rollup-linux-s390x-gnu@4.36.0": 393 | version "4.36.0" 394 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.36.0.tgz#6fa895f181fa6804bc6ca27c0e9a6823355436dd" 395 | integrity sha512-4a5gf2jpS0AIe7uBjxDeUMNcFmaRTbNv7NxI5xOCs4lhzsVyGR/0qBXduPnoWf6dGC365saTiwag8hP1imTgag== 396 | 397 | "@rollup/rollup-linux-x64-gnu@4.36.0": 398 | version "4.36.0" 399 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.36.0.tgz#d2e69f7598c71f03287b763fdbefce4163f07419" 400 | integrity sha512-5KtoW8UWmwFKQ96aQL3LlRXX16IMwyzMq/jSSVIIyAANiE1doaQsx/KRyhAvpHlPjPiSU/AYX/8m+lQ9VToxFQ== 401 | 402 | "@rollup/rollup-linux-x64-musl@4.36.0": 403 | version "4.36.0" 404 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.36.0.tgz#9eb0075deaabf5d88a9dc8b61bd7bd122ac64ef9" 405 | integrity sha512-sycrYZPrv2ag4OCvaN5js+f01eoZ2U+RmT5as8vhxiFz+kxwlHrsxOwKPSA8WyS+Wc6Epid9QeI/IkQ9NkgYyQ== 406 | 407 | "@rollup/rollup-win32-arm64-msvc@4.36.0": 408 | version "4.36.0" 409 | resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.36.0.tgz#bfda7178ed8cb8fa8786474a02eae9fc8649a74d" 410 | integrity sha512-qbqt4N7tokFwwSVlWDsjfoHgviS3n/vZ8LK0h1uLG9TYIRuUTJC88E1xb3LM2iqZ/WTqNQjYrtmtGmrmmawB6A== 411 | 412 | "@rollup/rollup-win32-ia32-msvc@4.36.0": 413 | version "4.36.0" 414 | resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.36.0.tgz#8e12739b9c43de8f0690b280c676af3de571cee0" 415 | integrity sha512-t+RY0JuRamIocMuQcfwYSOkmdX9dtkr1PbhKW42AMvaDQa+jOdpUYysroTF/nuPpAaQMWp7ye+ndlmmthieJrQ== 416 | 417 | "@rollup/rollup-win32-x64-msvc@4.36.0": 418 | version "4.36.0" 419 | resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.36.0.tgz#88b23fe29d28fa647030b36e912c1b5b50831b1d" 420 | integrity sha512-aRXd7tRZkWLqGbChgcMMDEHjOKudo1kChb1Jt1IfR8cY/KIpgNviLeJy5FUb9IpSuQj8dU2fAYNMPW/hLKOSTw== 421 | 422 | "@types/estree@1.0.6": 423 | version "1.0.6" 424 | resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" 425 | integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== 426 | 427 | "@types/mocha@^9.1.1": 428 | version "9.1.1" 429 | resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" 430 | integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== 431 | 432 | acorn-walk@^8.0.0, acorn-walk@^8.2.0: 433 | version "8.3.4" 434 | resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" 435 | integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== 436 | dependencies: 437 | acorn "^8.11.0" 438 | 439 | acorn@^8.0.4, acorn@^8.10.0, acorn@^8.11.0: 440 | version "8.14.1" 441 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" 442 | integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== 443 | 444 | ansi-colors@^4.1.3: 445 | version "4.1.3" 446 | resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" 447 | integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== 448 | 449 | ansi-regex@^5.0.1: 450 | version "5.0.1" 451 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 452 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 453 | 454 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 455 | version "4.3.0" 456 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 457 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 458 | dependencies: 459 | color-convert "^2.0.1" 460 | 461 | anymatch@~3.1.2: 462 | version "3.1.3" 463 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" 464 | integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== 465 | dependencies: 466 | normalize-path "^3.0.0" 467 | picomatch "^2.0.4" 468 | 469 | argparse@^2.0.1: 470 | version "2.0.1" 471 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" 472 | integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 473 | 474 | balanced-match@^1.0.0: 475 | version "1.0.2" 476 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 477 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 478 | 479 | binary-extensions@^2.0.0: 480 | version "2.3.0" 481 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" 482 | integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== 483 | 484 | brace-expansion@^2.0.1: 485 | version "2.0.1" 486 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" 487 | integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== 488 | dependencies: 489 | balanced-match "^1.0.0" 490 | 491 | braces@~3.0.2: 492 | version "3.0.3" 493 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" 494 | integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== 495 | dependencies: 496 | fill-range "^7.1.1" 497 | 498 | browser-stdout@^1.3.1: 499 | version "1.3.1" 500 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" 501 | integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== 502 | 503 | camelcase@^6.0.0: 504 | version "6.3.0" 505 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" 506 | integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== 507 | 508 | chalk@^4.1.0: 509 | version "4.1.2" 510 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 511 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 512 | dependencies: 513 | ansi-styles "^4.1.0" 514 | supports-color "^7.1.0" 515 | 516 | chokidar@^3.5.3: 517 | version "3.6.0" 518 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" 519 | integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== 520 | dependencies: 521 | anymatch "~3.1.2" 522 | braces "~3.0.2" 523 | glob-parent "~5.1.2" 524 | is-binary-path "~2.1.0" 525 | is-glob "~4.0.1" 526 | normalize-path "~3.0.0" 527 | readdirp "~3.6.0" 528 | optionalDependencies: 529 | fsevents "~2.3.2" 530 | 531 | cliui@^7.0.2: 532 | version "7.0.4" 533 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" 534 | integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== 535 | dependencies: 536 | string-width "^4.2.0" 537 | strip-ansi "^6.0.0" 538 | wrap-ansi "^7.0.0" 539 | 540 | cliui@^8.0.1: 541 | version "8.0.1" 542 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" 543 | integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== 544 | dependencies: 545 | string-width "^4.2.0" 546 | strip-ansi "^6.0.1" 547 | wrap-ansi "^7.0.0" 548 | 549 | codemirror@6.x.x: 550 | version "6.0.1" 551 | resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-6.0.1.tgz#62b91142d45904547ee3e0e0e4c1a79158035a29" 552 | integrity sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg== 553 | dependencies: 554 | "@codemirror/autocomplete" "^6.0.0" 555 | "@codemirror/commands" "^6.0.0" 556 | "@codemirror/language" "^6.0.0" 557 | "@codemirror/lint" "^6.0.0" 558 | "@codemirror/search" "^6.0.0" 559 | "@codemirror/state" "^6.0.0" 560 | "@codemirror/view" "^6.0.0" 561 | 562 | color-convert@^2.0.1: 563 | version "2.0.1" 564 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 565 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 566 | dependencies: 567 | color-name "~1.1.4" 568 | 569 | color-name@~1.1.4: 570 | version "1.1.4" 571 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 572 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 573 | 574 | core-util-is@~1.0.0: 575 | version "1.0.3" 576 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" 577 | integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== 578 | 579 | crelt@^1.0.5: 580 | version "1.0.6" 581 | resolved "https://registry.yarnpkg.com/crelt/-/crelt-1.0.6.tgz#7cc898ea74e190fb6ef9dae57f8f81cf7302df72" 582 | integrity sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g== 583 | 584 | debug@2.6.9: 585 | version "2.6.9" 586 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 587 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 588 | dependencies: 589 | ms "2.0.0" 590 | 591 | debug@^4.3.5: 592 | version "4.4.0" 593 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" 594 | integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== 595 | dependencies: 596 | ms "^2.1.3" 597 | 598 | decamelize@^4.0.0: 599 | version "4.0.0" 600 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" 601 | integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== 602 | 603 | depd@2.0.0: 604 | version "2.0.0" 605 | resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" 606 | integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== 607 | 608 | destroy@1.2.0: 609 | version "1.2.0" 610 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" 611 | integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== 612 | 613 | diff@^5.2.0: 614 | version "5.2.0" 615 | resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" 616 | integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== 617 | 618 | dts-bundle-generator@^9.5.1: 619 | version "9.5.1" 620 | resolved "https://registry.yarnpkg.com/dts-bundle-generator/-/dts-bundle-generator-9.5.1.tgz#7eac7f47a2d5b51bdaf581843e7f969b88bfc225" 621 | integrity sha512-DxpJOb2FNnEyOzMkG11sxO2dmxPjthoVWxfKqWYJ/bI/rT1rvTMktF5EKjAYrRZu6Z6t3NhOUZ0sZ5ZXevOfbA== 622 | dependencies: 623 | typescript ">=5.0.2" 624 | yargs "^17.6.0" 625 | 626 | ee-first@1.1.1: 627 | version "1.1.1" 628 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 629 | integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== 630 | 631 | emoji-regex@^8.0.0: 632 | version "8.0.0" 633 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 634 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 635 | 636 | encodeurl@~1.0.2: 637 | version "1.0.2" 638 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 639 | integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== 640 | 641 | encodeurl@~2.0.0: 642 | version "2.0.0" 643 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" 644 | integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== 645 | 646 | esbuild@^0.25.0: 647 | version "0.25.1" 648 | resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.1.tgz#a16b8d070b6ad4871935277bda6ccfe852e3fa2f" 649 | integrity sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ== 650 | optionalDependencies: 651 | "@esbuild/aix-ppc64" "0.25.1" 652 | "@esbuild/android-arm" "0.25.1" 653 | "@esbuild/android-arm64" "0.25.1" 654 | "@esbuild/android-x64" "0.25.1" 655 | "@esbuild/darwin-arm64" "0.25.1" 656 | "@esbuild/darwin-x64" "0.25.1" 657 | "@esbuild/freebsd-arm64" "0.25.1" 658 | "@esbuild/freebsd-x64" "0.25.1" 659 | "@esbuild/linux-arm" "0.25.1" 660 | "@esbuild/linux-arm64" "0.25.1" 661 | "@esbuild/linux-ia32" "0.25.1" 662 | "@esbuild/linux-loong64" "0.25.1" 663 | "@esbuild/linux-mips64el" "0.25.1" 664 | "@esbuild/linux-ppc64" "0.25.1" 665 | "@esbuild/linux-riscv64" "0.25.1" 666 | "@esbuild/linux-s390x" "0.25.1" 667 | "@esbuild/linux-x64" "0.25.1" 668 | "@esbuild/netbsd-arm64" "0.25.1" 669 | "@esbuild/netbsd-x64" "0.25.1" 670 | "@esbuild/openbsd-arm64" "0.25.1" 671 | "@esbuild/openbsd-x64" "0.25.1" 672 | "@esbuild/sunos-x64" "0.25.1" 673 | "@esbuild/win32-arm64" "0.25.1" 674 | "@esbuild/win32-ia32" "0.25.1" 675 | "@esbuild/win32-x64" "0.25.1" 676 | 677 | escalade@^3.1.1: 678 | version "3.2.0" 679 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" 680 | integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== 681 | 682 | escape-html@~1.0.3: 683 | version "1.0.3" 684 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 685 | integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== 686 | 687 | escape-string-regexp@^4.0.0: 688 | version "4.0.0" 689 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 690 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 691 | 692 | esmoduleserve@^0.2.0: 693 | version "0.2.1" 694 | resolved "https://registry.yarnpkg.com/esmoduleserve/-/esmoduleserve-0.2.1.tgz#4b012bda791469ed918b4456333c84a629f3e9e4" 695 | integrity sha512-LeuOiyyCSc2sG0Clx9A/tzApfP2gz2/YPE7IBSQwP2JPZKm8S0WZ1b1DfH9eCYXo469k81od3lFvFloYJNpTYA== 696 | dependencies: 697 | acorn "^8.0.4" 698 | acorn-walk "^8.0.0" 699 | resolve "^1.15.1" 700 | serve-static "^1.14.1" 701 | 702 | etag@~1.8.1: 703 | version "1.8.1" 704 | resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" 705 | integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== 706 | 707 | fill-range@^7.1.1: 708 | version "7.1.1" 709 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" 710 | integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== 711 | dependencies: 712 | to-regex-range "^5.0.1" 713 | 714 | find-up@^5.0.0: 715 | version "5.0.0" 716 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" 717 | integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 718 | dependencies: 719 | locate-path "^6.0.0" 720 | path-exists "^4.0.0" 721 | 722 | flat@^5.0.2: 723 | version "5.0.2" 724 | resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" 725 | integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== 726 | 727 | fresh@0.5.2: 728 | version "0.5.2" 729 | resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" 730 | integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== 731 | 732 | fs.realpath@^1.0.0: 733 | version "1.0.0" 734 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 735 | integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== 736 | 737 | fsevents@~2.3.2, fsevents@~2.3.3: 738 | version "2.3.3" 739 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" 740 | integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== 741 | 742 | function-bind@^1.1.2: 743 | version "1.1.2" 744 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" 745 | integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== 746 | 747 | get-caller-file@^2.0.5: 748 | version "2.0.5" 749 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 750 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 751 | 752 | glob-parent@~5.1.2: 753 | version "5.1.2" 754 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 755 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 756 | dependencies: 757 | is-glob "^4.0.1" 758 | 759 | glob@^8.1.0: 760 | version "8.1.0" 761 | resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" 762 | integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== 763 | dependencies: 764 | fs.realpath "^1.0.0" 765 | inflight "^1.0.4" 766 | inherits "2" 767 | minimatch "^5.0.1" 768 | once "^1.3.0" 769 | 770 | has-flag@^4.0.0: 771 | version "4.0.0" 772 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 773 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 774 | 775 | hasown@^2.0.2: 776 | version "2.0.2" 777 | resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" 778 | integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== 779 | dependencies: 780 | function-bind "^1.1.2" 781 | 782 | he@^1.2.0: 783 | version "1.2.0" 784 | resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" 785 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== 786 | 787 | http-errors@2.0.0: 788 | version "2.0.0" 789 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" 790 | integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== 791 | dependencies: 792 | depd "2.0.0" 793 | inherits "2.0.4" 794 | setprototypeof "1.2.0" 795 | statuses "2.0.1" 796 | toidentifier "1.0.1" 797 | 798 | immediate@~3.0.5: 799 | version "3.0.6" 800 | resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" 801 | integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== 802 | 803 | inflight@^1.0.4: 804 | version "1.0.6" 805 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 806 | integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== 807 | dependencies: 808 | once "^1.3.0" 809 | wrappy "1" 810 | 811 | inherits@2, inherits@2.0.4, inherits@~2.0.3: 812 | version "2.0.4" 813 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 814 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 815 | 816 | is-binary-path@~2.1.0: 817 | version "2.1.0" 818 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 819 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 820 | dependencies: 821 | binary-extensions "^2.0.0" 822 | 823 | is-core-module@^2.16.0: 824 | version "2.16.1" 825 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" 826 | integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== 827 | dependencies: 828 | hasown "^2.0.2" 829 | 830 | is-extglob@^2.1.1: 831 | version "2.1.1" 832 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 833 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 834 | 835 | is-fullwidth-code-point@^3.0.0: 836 | version "3.0.0" 837 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 838 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 839 | 840 | is-glob@^4.0.1, is-glob@~4.0.1: 841 | version "4.0.3" 842 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 843 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 844 | dependencies: 845 | is-extglob "^2.1.1" 846 | 847 | is-number@^7.0.0: 848 | version "7.0.0" 849 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 850 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 851 | 852 | is-plain-obj@^2.1.0: 853 | version "2.1.0" 854 | resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" 855 | integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== 856 | 857 | is-unicode-supported@^0.1.0: 858 | version "0.1.0" 859 | resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" 860 | integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== 861 | 862 | isarray@~1.0.0: 863 | version "1.0.0" 864 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 865 | integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== 866 | 867 | ist@^1.1.7: 868 | version "1.1.7" 869 | resolved "https://registry.yarnpkg.com/ist/-/ist-1.1.7.tgz#64161305bca42937d8e05394a2883c3431c5f7ff" 870 | integrity sha512-ex9JyqY+tCjBlxN1pXlqxEgtGGUGp1TG83ll1xpu8SfPgOhfAhEGCuepNHlB+d7Le+hLoBcfCu/G0ZQaFbi9hA== 871 | 872 | js-tokens@^4.0.0: 873 | version "4.0.0" 874 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 875 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 876 | 877 | js-yaml@^4.1.0: 878 | version "4.1.0" 879 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" 880 | integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== 881 | dependencies: 882 | argparse "^2.0.1" 883 | 884 | jszip@^3.10.1: 885 | version "3.10.1" 886 | resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2" 887 | integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g== 888 | dependencies: 889 | lie "~3.3.0" 890 | pako "~1.0.2" 891 | readable-stream "~2.3.6" 892 | setimmediate "^1.0.5" 893 | 894 | lie@~3.3.0: 895 | version "3.3.0" 896 | resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" 897 | integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== 898 | dependencies: 899 | immediate "~3.0.5" 900 | 901 | locate-path@^6.0.0: 902 | version "6.0.0" 903 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" 904 | integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== 905 | dependencies: 906 | p-locate "^5.0.0" 907 | 908 | log-symbols@^4.1.0: 909 | version "4.1.0" 910 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" 911 | integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== 912 | dependencies: 913 | chalk "^4.1.0" 914 | is-unicode-supported "^0.1.0" 915 | 916 | magic-string@^0.30.17: 917 | version "0.30.17" 918 | resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" 919 | integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== 920 | dependencies: 921 | "@jridgewell/sourcemap-codec" "^1.5.0" 922 | 923 | mime@1.6.0: 924 | version "1.6.0" 925 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" 926 | integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== 927 | 928 | minimatch@^5.0.1, minimatch@^5.1.6: 929 | version "5.1.6" 930 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" 931 | integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== 932 | dependencies: 933 | brace-expansion "^2.0.1" 934 | 935 | mocha@^10.0.0: 936 | version "10.8.2" 937 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.8.2.tgz#8d8342d016ed411b12a429eb731b825f961afb96" 938 | integrity sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg== 939 | dependencies: 940 | ansi-colors "^4.1.3" 941 | browser-stdout "^1.3.1" 942 | chokidar "^3.5.3" 943 | debug "^4.3.5" 944 | diff "^5.2.0" 945 | escape-string-regexp "^4.0.0" 946 | find-up "^5.0.0" 947 | glob "^8.1.0" 948 | he "^1.2.0" 949 | js-yaml "^4.1.0" 950 | log-symbols "^4.1.0" 951 | minimatch "^5.1.6" 952 | ms "^2.1.3" 953 | serialize-javascript "^6.0.2" 954 | strip-json-comments "^3.1.1" 955 | supports-color "^8.1.1" 956 | workerpool "^6.5.1" 957 | yargs "^16.2.0" 958 | yargs-parser "^20.2.9" 959 | yargs-unparser "^2.0.0" 960 | 961 | ms@2.0.0: 962 | version "2.0.0" 963 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 964 | integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== 965 | 966 | ms@2.1.3, ms@^2.1.3: 967 | version "2.1.3" 968 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 969 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 970 | 971 | nanoid@^3.3.8: 972 | version "3.3.11" 973 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" 974 | integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== 975 | 976 | normalize-path@^3.0.0, normalize-path@~3.0.0: 977 | version "3.0.0" 978 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 979 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 980 | 981 | on-finished@2.4.1: 982 | version "2.4.1" 983 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" 984 | integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== 985 | dependencies: 986 | ee-first "1.1.1" 987 | 988 | once@^1.3.0: 989 | version "1.4.0" 990 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 991 | integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== 992 | dependencies: 993 | wrappy "1" 994 | 995 | p-limit@^3.0.2: 996 | version "3.1.0" 997 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" 998 | integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 999 | dependencies: 1000 | yocto-queue "^0.1.0" 1001 | 1002 | p-locate@^5.0.0: 1003 | version "5.0.0" 1004 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" 1005 | integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== 1006 | dependencies: 1007 | p-limit "^3.0.2" 1008 | 1009 | pako@~1.0.2: 1010 | version "1.0.11" 1011 | resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" 1012 | integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== 1013 | 1014 | parseurl@~1.3.3: 1015 | version "1.3.3" 1016 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" 1017 | integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== 1018 | 1019 | path-exists@^4.0.0: 1020 | version "4.0.0" 1021 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 1022 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 1023 | 1024 | path-parse@^1.0.7: 1025 | version "1.0.7" 1026 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" 1027 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 1028 | 1029 | picocolors@^1.0.0, picocolors@^1.1.1: 1030 | version "1.1.1" 1031 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" 1032 | integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== 1033 | 1034 | picomatch@^2.0.4, picomatch@^2.2.1: 1035 | version "2.3.1" 1036 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 1037 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 1038 | 1039 | postcss@^8.5.3: 1040 | version "8.5.3" 1041 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.3.tgz#1463b6f1c7fb16fe258736cba29a2de35237eafb" 1042 | integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== 1043 | dependencies: 1044 | nanoid "^3.3.8" 1045 | picocolors "^1.1.1" 1046 | source-map-js "^1.2.1" 1047 | 1048 | process-nextick-args@~2.0.0: 1049 | version "2.0.1" 1050 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" 1051 | integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== 1052 | 1053 | randombytes@^2.1.0: 1054 | version "2.1.0" 1055 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" 1056 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== 1057 | dependencies: 1058 | safe-buffer "^5.1.0" 1059 | 1060 | range-parser@~1.2.1: 1061 | version "1.2.1" 1062 | resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" 1063 | integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== 1064 | 1065 | readable-stream@~2.3.6: 1066 | version "2.3.8" 1067 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" 1068 | integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== 1069 | dependencies: 1070 | core-util-is "~1.0.0" 1071 | inherits "~2.0.3" 1072 | isarray "~1.0.0" 1073 | process-nextick-args "~2.0.0" 1074 | safe-buffer "~5.1.1" 1075 | string_decoder "~1.1.1" 1076 | util-deprecate "~1.0.1" 1077 | 1078 | readdirp@~3.6.0: 1079 | version "3.6.0" 1080 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" 1081 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 1082 | dependencies: 1083 | picomatch "^2.2.1" 1084 | 1085 | require-directory@^2.1.1: 1086 | version "2.1.1" 1087 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 1088 | integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== 1089 | 1090 | resolve@^1.15.1: 1091 | version "1.22.10" 1092 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" 1093 | integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== 1094 | dependencies: 1095 | is-core-module "^2.16.0" 1096 | path-parse "^1.0.7" 1097 | supports-preserve-symlinks-flag "^1.0.0" 1098 | 1099 | rollup-plugin-dts@^6.1.0: 1100 | version "6.2.0" 1101 | resolved "https://registry.yarnpkg.com/rollup-plugin-dts/-/rollup-plugin-dts-6.2.0.tgz#d74239ba155a9354c08a97e9a5cda26404fc74f2" 1102 | integrity sha512-iciY+z46mUbN5nCxtJqVynwgrZZljM8of6k8Rg5rVAmu4VHDxexFPgoCa2wrJG5mMsHSGrJmjQPCM4vD0Oe3Lg== 1103 | dependencies: 1104 | magic-string "^0.30.17" 1105 | optionalDependencies: 1106 | "@babel/code-frame" "^7.26.2" 1107 | 1108 | rollup@^4.30.1, rollup@^4.8.0: 1109 | version "4.36.0" 1110 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.36.0.tgz#f40f4db47ba3b4f5846d32a47e580c0ed7cd8f02" 1111 | integrity sha512-zwATAXNQxUcd40zgtQG0ZafcRK4g004WtEl7kbuhTWPvf07PsfohXl39jVUvPF7jvNAIkKPQ2XrsDlWuxBd++Q== 1112 | dependencies: 1113 | "@types/estree" "1.0.6" 1114 | optionalDependencies: 1115 | "@rollup/rollup-android-arm-eabi" "4.36.0" 1116 | "@rollup/rollup-android-arm64" "4.36.0" 1117 | "@rollup/rollup-darwin-arm64" "4.36.0" 1118 | "@rollup/rollup-darwin-x64" "4.36.0" 1119 | "@rollup/rollup-freebsd-arm64" "4.36.0" 1120 | "@rollup/rollup-freebsd-x64" "4.36.0" 1121 | "@rollup/rollup-linux-arm-gnueabihf" "4.36.0" 1122 | "@rollup/rollup-linux-arm-musleabihf" "4.36.0" 1123 | "@rollup/rollup-linux-arm64-gnu" "4.36.0" 1124 | "@rollup/rollup-linux-arm64-musl" "4.36.0" 1125 | "@rollup/rollup-linux-loongarch64-gnu" "4.36.0" 1126 | "@rollup/rollup-linux-powerpc64le-gnu" "4.36.0" 1127 | "@rollup/rollup-linux-riscv64-gnu" "4.36.0" 1128 | "@rollup/rollup-linux-s390x-gnu" "4.36.0" 1129 | "@rollup/rollup-linux-x64-gnu" "4.36.0" 1130 | "@rollup/rollup-linux-x64-musl" "4.36.0" 1131 | "@rollup/rollup-win32-arm64-msvc" "4.36.0" 1132 | "@rollup/rollup-win32-ia32-msvc" "4.36.0" 1133 | "@rollup/rollup-win32-x64-msvc" "4.36.0" 1134 | fsevents "~2.3.2" 1135 | 1136 | safe-buffer@^5.1.0: 1137 | version "5.2.1" 1138 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 1139 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 1140 | 1141 | safe-buffer@~5.1.0, safe-buffer@~5.1.1: 1142 | version "5.1.2" 1143 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 1144 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 1145 | 1146 | selenium-webdriver@^4.10.0: 1147 | version "4.29.0" 1148 | resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.29.0.tgz#32d32fb60df488bbc399b9dd58728a5cd570210e" 1149 | integrity sha512-8XPGtDoji5xk7ZUCzFT1rqHmCp67DCzESsttId7DzmrJmlTRmRLF6X918rbwclcH89amcBNM4zB3lVPj404I0g== 1150 | dependencies: 1151 | "@bazel/runfiles" "^6.3.1" 1152 | jszip "^3.10.1" 1153 | tmp "^0.2.3" 1154 | ws "^8.18.0" 1155 | 1156 | send@0.19.0: 1157 | version "0.19.0" 1158 | resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" 1159 | integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== 1160 | dependencies: 1161 | debug "2.6.9" 1162 | depd "2.0.0" 1163 | destroy "1.2.0" 1164 | encodeurl "~1.0.2" 1165 | escape-html "~1.0.3" 1166 | etag "~1.8.1" 1167 | fresh "0.5.2" 1168 | http-errors "2.0.0" 1169 | mime "1.6.0" 1170 | ms "2.1.3" 1171 | on-finished "2.4.1" 1172 | range-parser "~1.2.1" 1173 | statuses "2.0.1" 1174 | 1175 | serialize-javascript@^6.0.2: 1176 | version "6.0.2" 1177 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" 1178 | integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== 1179 | dependencies: 1180 | randombytes "^2.1.0" 1181 | 1182 | serve-static@^1.14.1: 1183 | version "1.16.2" 1184 | resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" 1185 | integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw== 1186 | dependencies: 1187 | encodeurl "~2.0.0" 1188 | escape-html "~1.0.3" 1189 | parseurl "~1.3.3" 1190 | send "0.19.0" 1191 | 1192 | setimmediate@^1.0.5: 1193 | version "1.0.5" 1194 | resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" 1195 | integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== 1196 | 1197 | setprototypeof@1.2.0: 1198 | version "1.2.0" 1199 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" 1200 | integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== 1201 | 1202 | source-map-js@^1.2.1: 1203 | version "1.2.1" 1204 | resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" 1205 | integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== 1206 | 1207 | statuses@2.0.1: 1208 | version "2.0.1" 1209 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" 1210 | integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== 1211 | 1212 | string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: 1213 | version "4.2.3" 1214 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 1215 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 1216 | dependencies: 1217 | emoji-regex "^8.0.0" 1218 | is-fullwidth-code-point "^3.0.0" 1219 | strip-ansi "^6.0.1" 1220 | 1221 | string_decoder@~1.1.1: 1222 | version "1.1.1" 1223 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" 1224 | integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== 1225 | dependencies: 1226 | safe-buffer "~5.1.0" 1227 | 1228 | strip-ansi@^6.0.0, strip-ansi@^6.0.1: 1229 | version "6.0.1" 1230 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 1231 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 1232 | dependencies: 1233 | ansi-regex "^5.0.1" 1234 | 1235 | strip-json-comments@^3.1.1: 1236 | version "3.1.1" 1237 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" 1238 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 1239 | 1240 | style-mod@^4.0.0, style-mod@^4.1.0: 1241 | version "4.1.2" 1242 | resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.1.2.tgz#ca238a1ad4786520f7515a8539d5a63691d7bf67" 1243 | integrity sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw== 1244 | 1245 | supports-color@^7.1.0: 1246 | version "7.2.0" 1247 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 1248 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 1249 | dependencies: 1250 | has-flag "^4.0.0" 1251 | 1252 | supports-color@^8.1.1: 1253 | version "8.1.1" 1254 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" 1255 | integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== 1256 | dependencies: 1257 | has-flag "^4.0.0" 1258 | 1259 | supports-preserve-symlinks-flag@^1.0.0: 1260 | version "1.0.0" 1261 | resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" 1262 | integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== 1263 | 1264 | tmp@^0.2.3: 1265 | version "0.2.3" 1266 | resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" 1267 | integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== 1268 | 1269 | to-regex-range@^5.0.1: 1270 | version "5.0.1" 1271 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 1272 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1273 | dependencies: 1274 | is-number "^7.0.0" 1275 | 1276 | toidentifier@1.0.1: 1277 | version "1.0.1" 1278 | resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" 1279 | integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== 1280 | 1281 | typescript@>=5.0.2, typescript@^5.3.3, typescript@^5.8.2: 1282 | version "5.8.2" 1283 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.2.tgz#8170b3702f74b79db2e5a96207c15e65807999e4" 1284 | integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ== 1285 | 1286 | util-deprecate@~1.0.1: 1287 | version "1.0.2" 1288 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 1289 | integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== 1290 | 1291 | vite@^6.2.2: 1292 | version "6.2.2" 1293 | resolved "https://registry.yarnpkg.com/vite/-/vite-6.2.2.tgz#8098b12a6bfd95abe39399aa7d5faa56545d7a1a" 1294 | integrity sha512-yW7PeMM+LkDzc7CgJuRLMW2Jz0FxMOsVJ8Lv3gpgW9WLcb9cTW+121UEr1hvmfR7w3SegR5ItvYyzVz1vxNJgQ== 1295 | dependencies: 1296 | esbuild "^0.25.0" 1297 | postcss "^8.5.3" 1298 | rollup "^4.30.1" 1299 | optionalDependencies: 1300 | fsevents "~2.3.3" 1301 | 1302 | w3c-keyname@^2.2.4: 1303 | version "2.2.8" 1304 | resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz#7b17c8c6883d4e8b86ac8aba79d39e880f8869c5" 1305 | integrity sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ== 1306 | 1307 | workerpool@^6.5.1: 1308 | version "6.5.1" 1309 | resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" 1310 | integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== 1311 | 1312 | wrap-ansi@^7.0.0: 1313 | version "7.0.0" 1314 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 1315 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 1316 | dependencies: 1317 | ansi-styles "^4.0.0" 1318 | string-width "^4.1.0" 1319 | strip-ansi "^6.0.0" 1320 | 1321 | wrappy@1: 1322 | version "1.0.2" 1323 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1324 | integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== 1325 | 1326 | ws@^8.18.0: 1327 | version "8.18.1" 1328 | resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.1.tgz#ea131d3784e1dfdff91adb0a4a116b127515e3cb" 1329 | integrity sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w== 1330 | 1331 | y18n@^5.0.5: 1332 | version "5.0.8" 1333 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" 1334 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== 1335 | 1336 | yargs-parser@^20.2.2, yargs-parser@^20.2.9: 1337 | version "20.2.9" 1338 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" 1339 | integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== 1340 | 1341 | yargs-parser@^21.1.1: 1342 | version "21.1.1" 1343 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" 1344 | integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== 1345 | 1346 | yargs-unparser@^2.0.0: 1347 | version "2.0.0" 1348 | resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" 1349 | integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== 1350 | dependencies: 1351 | camelcase "^6.0.0" 1352 | decamelize "^4.0.0" 1353 | flat "^5.0.2" 1354 | is-plain-obj "^2.1.0" 1355 | 1356 | yargs@^16.2.0: 1357 | version "16.2.0" 1358 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" 1359 | integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== 1360 | dependencies: 1361 | cliui "^7.0.2" 1362 | escalade "^3.1.1" 1363 | get-caller-file "^2.0.5" 1364 | require-directory "^2.1.1" 1365 | string-width "^4.2.0" 1366 | y18n "^5.0.5" 1367 | yargs-parser "^20.2.2" 1368 | 1369 | yargs@^17.6.0: 1370 | version "17.7.2" 1371 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" 1372 | integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== 1373 | dependencies: 1374 | cliui "^8.0.1" 1375 | escalade "^3.1.1" 1376 | get-caller-file "^2.0.5" 1377 | require-directory "^2.1.1" 1378 | string-width "^4.2.3" 1379 | y18n "^5.0.5" 1380 | yargs-parser "^21.1.1" 1381 | 1382 | yocto-queue@^0.1.0: 1383 | version "0.1.0" 1384 | resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" 1385 | integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== 1386 | --------------------------------------------------------------------------------