Files
bobbie-pkm/.obsidian/plugins/css-editor/main.js
2026-03-02 17:06:32 +00:00

13647 lines
445 KiB
JavaScript

/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/main.ts
var main_exports = {};
__export(main_exports, {
DEFAULT_SETTINGS: () => DEFAULT_SETTINGS,
default: () => CssEditorPlugin
});
module.exports = __toCommonJS(main_exports);
var import_obsidian11 = require("obsidian");
// src/views/CssEditorView.ts
var import_obsidian7 = require("obsidian");
var import_view8 = require("@codemirror/view");
// node_modules/@replit/codemirror-vim/dist/index.js
var import_state = require("@codemirror/state");
var import_language = require("@codemirror/language");
var View = __toESM(require("@codemirror/view"), 1);
var import_view = require("@codemirror/view");
var import_search = require("@codemirror/search");
var import_commands = require("@codemirror/commands");
function initVim(CM) {
var Pos2 = CM.Pos;
function updateSelectionForSurrogateCharacters(cm, curStart, curEnd) {
if (curStart.line === curEnd.line && curStart.ch >= curEnd.ch - 1) {
var text = cm.getLine(curStart.line);
var charCode = text.charCodeAt(curStart.ch);
if (55296 <= charCode && charCode <= 55551) {
curEnd.ch += 1;
}
}
return { start: curStart, end: curEnd };
}
var defaultKeymap2 = [
// Key to key mapping. This goes first to make it possible to override
// existing mappings.
{ keys: "<Left>", type: "keyToKey", toKeys: "h" },
{ keys: "<Right>", type: "keyToKey", toKeys: "l" },
{ keys: "<Up>", type: "keyToKey", toKeys: "k" },
{ keys: "<Down>", type: "keyToKey", toKeys: "j" },
{ keys: "g<Up>", type: "keyToKey", toKeys: "gk" },
{ keys: "g<Down>", type: "keyToKey", toKeys: "gj" },
{ keys: "<Space>", type: "keyToKey", toKeys: "l" },
{ keys: "<BS>", type: "keyToKey", toKeys: "h" },
{ keys: "<Del>", type: "keyToKey", toKeys: "x" },
{ keys: "<C-Space>", type: "keyToKey", toKeys: "W" },
{ keys: "<C-BS>", type: "keyToKey", toKeys: "B" },
{ keys: "<S-Space>", type: "keyToKey", toKeys: "w" },
{ keys: "<S-BS>", type: "keyToKey", toKeys: "b" },
{ keys: "<C-n>", type: "keyToKey", toKeys: "j" },
{ keys: "<C-p>", type: "keyToKey", toKeys: "k" },
{ keys: "<C-[>", type: "keyToKey", toKeys: "<Esc>" },
{ keys: "<C-c>", type: "keyToKey", toKeys: "<Esc>" },
{ keys: "<C-[>", type: "keyToKey", toKeys: "<Esc>", context: "insert" },
{ keys: "<C-c>", type: "keyToKey", toKeys: "<Esc>", context: "insert" },
{ keys: "<C-Esc>", type: "keyToKey", toKeys: "<Esc>" },
// ipad keyboard sends C-Esc instead of C-[
{ keys: "<C-Esc>", type: "keyToKey", toKeys: "<Esc>", context: "insert" },
{ keys: "s", type: "keyToKey", toKeys: "cl", context: "normal" },
{ keys: "s", type: "keyToKey", toKeys: "c", context: "visual" },
{ keys: "S", type: "keyToKey", toKeys: "cc", context: "normal" },
{ keys: "S", type: "keyToKey", toKeys: "VdO", context: "visual" },
{ keys: "<Home>", type: "keyToKey", toKeys: "0" },
{ keys: "<End>", type: "keyToKey", toKeys: "$" },
{ keys: "<PageUp>", type: "keyToKey", toKeys: "<C-b>" },
{ keys: "<PageDown>", type: "keyToKey", toKeys: "<C-f>" },
{ keys: "<CR>", type: "keyToKey", toKeys: "j^", context: "normal" },
{ keys: "<Ins>", type: "keyToKey", toKeys: "i", context: "normal" },
{ keys: "<Ins>", type: "action", action: "toggleOverwrite", context: "insert" },
// Motions
{ keys: "H", type: "motion", motion: "moveToTopLine", motionArgs: { linewise: true, toJumplist: true } },
{ keys: "M", type: "motion", motion: "moveToMiddleLine", motionArgs: { linewise: true, toJumplist: true } },
{ keys: "L", type: "motion", motion: "moveToBottomLine", motionArgs: { linewise: true, toJumplist: true } },
{ keys: "h", type: "motion", motion: "moveByCharacters", motionArgs: { forward: false } },
{ keys: "l", type: "motion", motion: "moveByCharacters", motionArgs: { forward: true } },
{ keys: "j", type: "motion", motion: "moveByLines", motionArgs: { forward: true, linewise: true } },
{ keys: "k", type: "motion", motion: "moveByLines", motionArgs: { forward: false, linewise: true } },
{ keys: "gj", type: "motion", motion: "moveByDisplayLines", motionArgs: { forward: true } },
{ keys: "gk", type: "motion", motion: "moveByDisplayLines", motionArgs: { forward: false } },
{ keys: "w", type: "motion", motion: "moveByWords", motionArgs: { forward: true, wordEnd: false } },
{ keys: "W", type: "motion", motion: "moveByWords", motionArgs: { forward: true, wordEnd: false, bigWord: true } },
{ keys: "e", type: "motion", motion: "moveByWords", motionArgs: { forward: true, wordEnd: true, inclusive: true } },
{ keys: "E", type: "motion", motion: "moveByWords", motionArgs: { forward: true, wordEnd: true, bigWord: true, inclusive: true } },
{ keys: "b", type: "motion", motion: "moveByWords", motionArgs: { forward: false, wordEnd: false } },
{ keys: "B", type: "motion", motion: "moveByWords", motionArgs: { forward: false, wordEnd: false, bigWord: true } },
{ keys: "ge", type: "motion", motion: "moveByWords", motionArgs: { forward: false, wordEnd: true, inclusive: true } },
{ keys: "gE", type: "motion", motion: "moveByWords", motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true } },
{ keys: "{", type: "motion", motion: "moveByParagraph", motionArgs: { forward: false, toJumplist: true } },
{ keys: "}", type: "motion", motion: "moveByParagraph", motionArgs: { forward: true, toJumplist: true } },
{ keys: "(", type: "motion", motion: "moveBySentence", motionArgs: { forward: false } },
{ keys: ")", type: "motion", motion: "moveBySentence", motionArgs: { forward: true } },
{ keys: "<C-f>", type: "motion", motion: "moveByPage", motionArgs: { forward: true } },
{ keys: "<C-b>", type: "motion", motion: "moveByPage", motionArgs: { forward: false } },
{ keys: "<C-d>", type: "motion", motion: "moveByScroll", motionArgs: { forward: true, explicitRepeat: true } },
{ keys: "<C-u>", type: "motion", motion: "moveByScroll", motionArgs: { forward: false, explicitRepeat: true } },
{ keys: "gg", type: "motion", motion: "moveToLineOrEdgeOfDocument", motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true } },
{ keys: "G", type: "motion", motion: "moveToLineOrEdgeOfDocument", motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true } },
{ keys: "g$", type: "motion", motion: "moveToEndOfDisplayLine" },
{ keys: "g^", type: "motion", motion: "moveToStartOfDisplayLine" },
{ keys: "g0", type: "motion", motion: "moveToStartOfDisplayLine" },
{ keys: "0", type: "motion", motion: "moveToStartOfLine" },
{ keys: "^", type: "motion", motion: "moveToFirstNonWhiteSpaceCharacter" },
{ keys: "+", type: "motion", motion: "moveByLines", motionArgs: { forward: true, toFirstChar: true } },
{ keys: "-", type: "motion", motion: "moveByLines", motionArgs: { forward: false, toFirstChar: true } },
{ keys: "_", type: "motion", motion: "moveByLines", motionArgs: { forward: true, toFirstChar: true, repeatOffset: -1 } },
{ keys: "$", type: "motion", motion: "moveToEol", motionArgs: { inclusive: true } },
{ keys: "%", type: "motion", motion: "moveToMatchedSymbol", motionArgs: { inclusive: true, toJumplist: true } },
{ keys: "f<character>", type: "motion", motion: "moveToCharacter", motionArgs: { forward: true, inclusive: true } },
{ keys: "F<character>", type: "motion", motion: "moveToCharacter", motionArgs: { forward: false } },
{ keys: "t<character>", type: "motion", motion: "moveTillCharacter", motionArgs: { forward: true, inclusive: true } },
{ keys: "T<character>", type: "motion", motion: "moveTillCharacter", motionArgs: { forward: false } },
{ keys: ";", type: "motion", motion: "repeatLastCharacterSearch", motionArgs: { forward: true } },
{ keys: ",", type: "motion", motion: "repeatLastCharacterSearch", motionArgs: { forward: false } },
{ keys: "'<register>", type: "motion", motion: "goToMark", motionArgs: { toJumplist: true, linewise: true } },
{ keys: "`<register>", type: "motion", motion: "goToMark", motionArgs: { toJumplist: true } },
{ keys: "]`", type: "motion", motion: "jumpToMark", motionArgs: { forward: true } },
{ keys: "[`", type: "motion", motion: "jumpToMark", motionArgs: { forward: false } },
{ keys: "]'", type: "motion", motion: "jumpToMark", motionArgs: { forward: true, linewise: true } },
{ keys: "['", type: "motion", motion: "jumpToMark", motionArgs: { forward: false, linewise: true } },
// the next two aren't motions but must come before more general motion declarations
{ keys: "]p", type: "action", action: "paste", isEdit: true, actionArgs: { after: true, isEdit: true, matchIndent: true } },
{ keys: "[p", type: "action", action: "paste", isEdit: true, actionArgs: { after: false, isEdit: true, matchIndent: true } },
{ keys: "]<character>", type: "motion", motion: "moveToSymbol", motionArgs: { forward: true, toJumplist: true } },
{ keys: "[<character>", type: "motion", motion: "moveToSymbol", motionArgs: { forward: false, toJumplist: true } },
{ keys: "|", type: "motion", motion: "moveToColumn" },
{ keys: "o", type: "motion", motion: "moveToOtherHighlightedEnd", context: "visual" },
{ keys: "O", type: "motion", motion: "moveToOtherHighlightedEnd", motionArgs: { sameLine: true }, context: "visual" },
// Operators
{ keys: "d", type: "operator", operator: "delete" },
{ keys: "y", type: "operator", operator: "yank" },
{ keys: "c", type: "operator", operator: "change" },
{ keys: "=", type: "operator", operator: "indentAuto" },
{ keys: ">", type: "operator", operator: "indent", operatorArgs: { indentRight: true } },
{ keys: "<", type: "operator", operator: "indent", operatorArgs: { indentRight: false } },
{ keys: "g~", type: "operator", operator: "changeCase" },
{ keys: "gu", type: "operator", operator: "changeCase", operatorArgs: { toLower: true }, isEdit: true },
{ keys: "gU", type: "operator", operator: "changeCase", operatorArgs: { toLower: false }, isEdit: true },
{ keys: "n", type: "motion", motion: "findNext", motionArgs: { forward: true, toJumplist: true } },
{ keys: "N", type: "motion", motion: "findNext", motionArgs: { forward: false, toJumplist: true } },
{ keys: "gn", type: "motion", motion: "findAndSelectNextInclusive", motionArgs: { forward: true } },
{ keys: "gN", type: "motion", motion: "findAndSelectNextInclusive", motionArgs: { forward: false } },
{ keys: "gq", type: "operator", operator: "hardWrap" },
{ keys: "gw", type: "operator", operator: "hardWrap", operatorArgs: { keepCursor: true } },
{ keys: "g?", type: "operator", operator: "rot13" },
// Operator-Motion dual commands
{ keys: "x", type: "operatorMotion", operator: "delete", motion: "moveByCharacters", motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false } },
{ keys: "X", type: "operatorMotion", operator: "delete", motion: "moveByCharacters", motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true } },
{ keys: "D", type: "operatorMotion", operator: "delete", motion: "moveToEol", motionArgs: { inclusive: true }, context: "normal" },
{ keys: "D", type: "operator", operator: "delete", operatorArgs: { linewise: true }, context: "visual" },
{ keys: "Y", type: "operatorMotion", operator: "yank", motion: "expandToLine", motionArgs: { linewise: true }, context: "normal" },
{ keys: "Y", type: "operator", operator: "yank", operatorArgs: { linewise: true }, context: "visual" },
{ keys: "C", type: "operatorMotion", operator: "change", motion: "moveToEol", motionArgs: { inclusive: true }, context: "normal" },
{ keys: "C", type: "operator", operator: "change", operatorArgs: { linewise: true }, context: "visual" },
{ keys: "~", type: "operatorMotion", operator: "changeCase", motion: "moveByCharacters", motionArgs: { forward: true }, operatorArgs: { shouldMoveCursor: true }, context: "normal" },
{ keys: "~", type: "operator", operator: "changeCase", context: "visual" },
{ keys: "<C-u>", type: "operatorMotion", operator: "delete", motion: "moveToStartOfLine", context: "insert" },
{ keys: "<C-w>", type: "operatorMotion", operator: "delete", motion: "moveByWords", motionArgs: { forward: false, wordEnd: false }, context: "insert" },
//ignore C-w in normal mode
{ keys: "<C-w>", type: "idle", context: "normal" },
// Actions
{ keys: "<C-i>", type: "action", action: "jumpListWalk", actionArgs: { forward: true } },
{ keys: "<C-o>", type: "action", action: "jumpListWalk", actionArgs: { forward: false } },
{ keys: "<C-e>", type: "action", action: "scroll", actionArgs: { forward: true, linewise: true } },
{ keys: "<C-y>", type: "action", action: "scroll", actionArgs: { forward: false, linewise: true } },
{ keys: "a", type: "action", action: "enterInsertMode", isEdit: true, actionArgs: { insertAt: "charAfter" }, context: "normal" },
{ keys: "A", type: "action", action: "enterInsertMode", isEdit: true, actionArgs: { insertAt: "eol" }, context: "normal" },
{ keys: "A", type: "action", action: "enterInsertMode", isEdit: true, actionArgs: { insertAt: "endOfSelectedArea" }, context: "visual" },
{ keys: "i", type: "action", action: "enterInsertMode", isEdit: true, actionArgs: { insertAt: "inplace" }, context: "normal" },
{ keys: "gi", type: "action", action: "enterInsertMode", isEdit: true, actionArgs: { insertAt: "lastEdit" }, context: "normal" },
{ keys: "I", type: "action", action: "enterInsertMode", isEdit: true, actionArgs: { insertAt: "firstNonBlank" }, context: "normal" },
{ keys: "gI", type: "action", action: "enterInsertMode", isEdit: true, actionArgs: { insertAt: "bol" }, context: "normal" },
{ keys: "I", type: "action", action: "enterInsertMode", isEdit: true, actionArgs: { insertAt: "startOfSelectedArea" }, context: "visual" },
{ keys: "o", type: "action", action: "newLineAndEnterInsertMode", isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: "normal" },
{ keys: "O", type: "action", action: "newLineAndEnterInsertMode", isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: "normal" },
{ keys: "v", type: "action", action: "toggleVisualMode" },
{ keys: "V", type: "action", action: "toggleVisualMode", actionArgs: { linewise: true } },
{ keys: "<C-v>", type: "action", action: "toggleVisualMode", actionArgs: { blockwise: true } },
{ keys: "<C-q>", type: "action", action: "toggleVisualMode", actionArgs: { blockwise: true } },
{ keys: "gv", type: "action", action: "reselectLastSelection" },
{ keys: "J", type: "action", action: "joinLines", isEdit: true },
{ keys: "gJ", type: "action", action: "joinLines", actionArgs: { keepSpaces: true }, isEdit: true },
{ keys: "p", type: "action", action: "paste", isEdit: true, actionArgs: { after: true, isEdit: true } },
{ keys: "P", type: "action", action: "paste", isEdit: true, actionArgs: { after: false, isEdit: true } },
{ keys: "r<character>", type: "action", action: "replace", isEdit: true },
{ keys: "@<register>", type: "action", action: "replayMacro" },
{ keys: "q<register>", type: "action", action: "enterMacroRecordMode" },
// Handle Replace-mode as a special case of insert mode.
{ keys: "R", type: "action", action: "enterInsertMode", isEdit: true, actionArgs: { replace: true }, context: "normal" },
{ keys: "R", type: "operator", operator: "change", operatorArgs: { linewise: true, fullLine: true }, context: "visual", exitVisualBlock: true },
{ keys: "u", type: "action", action: "undo", context: "normal" },
{ keys: "u", type: "operator", operator: "changeCase", operatorArgs: { toLower: true }, context: "visual", isEdit: true },
{ keys: "U", type: "operator", operator: "changeCase", operatorArgs: { toLower: false }, context: "visual", isEdit: true },
{ keys: "<C-r>", type: "action", action: "redo" },
{ keys: "m<register>", type: "action", action: "setMark" },
{ keys: '"<register>', type: "action", action: "setRegister" },
{ keys: "<C-r><register>", type: "action", action: "insertRegister", context: "insert", isEdit: true },
{ keys: "<C-o>", type: "action", action: "oneNormalCommand", context: "insert" },
{ keys: "zz", type: "action", action: "scrollToCursor", actionArgs: { position: "center" } },
{ keys: "z.", type: "action", action: "scrollToCursor", actionArgs: { position: "center" }, motion: "moveToFirstNonWhiteSpaceCharacter" },
{ keys: "zt", type: "action", action: "scrollToCursor", actionArgs: { position: "top" } },
{ keys: "z<CR>", type: "action", action: "scrollToCursor", actionArgs: { position: "top" }, motion: "moveToFirstNonWhiteSpaceCharacter" },
{ keys: "zb", type: "action", action: "scrollToCursor", actionArgs: { position: "bottom" } },
{ keys: "z-", type: "action", action: "scrollToCursor", actionArgs: { position: "bottom" }, motion: "moveToFirstNonWhiteSpaceCharacter" },
{ keys: ".", type: "action", action: "repeatLastEdit" },
{ keys: "<C-a>", type: "action", action: "incrementNumberToken", isEdit: true, actionArgs: { increase: true, backtrack: false } },
{ keys: "<C-x>", type: "action", action: "incrementNumberToken", isEdit: true, actionArgs: { increase: false, backtrack: false } },
{ keys: "<C-t>", type: "action", action: "indent", actionArgs: { indentRight: true }, context: "insert" },
{ keys: "<C-d>", type: "action", action: "indent", actionArgs: { indentRight: false }, context: "insert" },
// Text object motions
{ keys: "a<register>", type: "motion", motion: "textObjectManipulation" },
{ keys: "i<register>", type: "motion", motion: "textObjectManipulation", motionArgs: { textObjectInner: true } },
// Search
{ keys: "/", type: "search", searchArgs: { forward: true, querySrc: "prompt", toJumplist: true } },
{ keys: "?", type: "search", searchArgs: { forward: false, querySrc: "prompt", toJumplist: true } },
{ keys: "*", type: "search", searchArgs: { forward: true, querySrc: "wordUnderCursor", wholeWordOnly: true, toJumplist: true } },
{ keys: "#", type: "search", searchArgs: { forward: false, querySrc: "wordUnderCursor", wholeWordOnly: true, toJumplist: true } },
{ keys: "g*", type: "search", searchArgs: { forward: true, querySrc: "wordUnderCursor", toJumplist: true } },
{ keys: "g#", type: "search", searchArgs: { forward: false, querySrc: "wordUnderCursor", toJumplist: true } },
// Ex command
{ keys: ":", type: "ex" }
];
var usedKeys = /* @__PURE__ */ Object.create(null);
var defaultKeymapLength = defaultKeymap2.length;
var defaultExCommandMap = [
{ name: "colorscheme", shortName: "colo" },
{ name: "map" },
{ name: "imap", shortName: "im" },
{ name: "nmap", shortName: "nm" },
{ name: "vmap", shortName: "vm" },
{ name: "omap", shortName: "om" },
{ name: "noremap", shortName: "no" },
{ name: "nnoremap", shortName: "nn" },
{ name: "vnoremap", shortName: "vn" },
{ name: "inoremap", shortName: "ino" },
{ name: "onoremap", shortName: "ono" },
{ name: "unmap" },
{ name: "mapclear", shortName: "mapc" },
{ name: "nmapclear", shortName: "nmapc" },
{ name: "vmapclear", shortName: "vmapc" },
{ name: "imapclear", shortName: "imapc" },
{ name: "omapclear", shortName: "omapc" },
{ name: "write", shortName: "w" },
{ name: "undo", shortName: "u" },
{ name: "redo", shortName: "red" },
{ name: "set", shortName: "se" },
{ name: "setlocal", shortName: "setl" },
{ name: "setglobal", shortName: "setg" },
{ name: "sort", shortName: "sor" },
{ name: "substitute", shortName: "s", possiblyAsync: true },
{ name: "startinsert", shortName: "start" },
{ name: "nohlsearch", shortName: "noh" },
{ name: "yank", shortName: "y" },
{ name: "delmarks", shortName: "delm" },
{ name: "marks", excludeFromCommandHistory: true },
{ name: "registers", shortName: "reg", excludeFromCommandHistory: true },
{ name: "vglobal", shortName: "v" },
{ name: "delete", shortName: "d" },
{ name: "join", shortName: "j" },
{ name: "normal", shortName: "norm" },
{ name: "global", shortName: "g" }
];
var langmap = parseLangmap("");
function enterVimMode(cm) {
cm.setOption("disableInput", true);
cm.setOption("showCursorWhenSelecting", false);
CM.signal(cm, "vim-mode-change", { mode: "normal" });
cm.on("cursorActivity", onCursorActivity);
maybeInitVimState(cm);
CM.on(cm.getInputField(), "paste", getOnPasteFn(cm));
}
function leaveVimMode(cm) {
cm.setOption("disableInput", false);
cm.off("cursorActivity", onCursorActivity);
CM.off(cm.getInputField(), "paste", getOnPasteFn(cm));
cm.state.vim = null;
if (highlightTimeout) clearTimeout(highlightTimeout);
}
function getOnPasteFn(cm) {
var vim2 = cm.state.vim;
if (!vim2.onPasteFn) {
vim2.onPasteFn = function() {
if (!vim2.insertMode) {
cm.setCursor(offsetCursor(cm.getCursor(), 0, 1));
actions.enterInsertMode(cm, {}, vim2);
}
};
}
return vim2.onPasteFn;
}
var numberRegex = /[\d]/;
var wordCharTest = [CM.isWordChar, function(ch) {
return ch && !CM.isWordChar(ch) && !/\s/.test(ch);
}], bigWordCharTest = [function(ch) {
return /\S/.test(ch);
}];
var validMarks = ["<", ">"];
var validRegisters = ["-", '"', ".", ":", "_", "/", "+"];
var latinCharRegex = /^\w$/;
var upperCaseChars = /^[A-Z]$/;
try {
upperCaseChars = new RegExp("^[\\p{Lu}]$", "u");
} catch (_) {
}
function isLine(cm, line) {
return line >= cm.firstLine() && line <= cm.lastLine();
}
function isLowerCase(k) {
return /^[a-z]$/.test(k);
}
function isMatchableSymbol(k) {
return "()[]{}".indexOf(k) != -1;
}
function isNumber(k) {
return numberRegex.test(k);
}
function isUpperCase(k) {
return upperCaseChars.test(k);
}
function isWhiteSpaceString(k) {
return /^\s*$/.test(k);
}
function isEndOfSentenceSymbol(k) {
return ".?!".indexOf(k) != -1;
}
function inArray(val, arr) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] == val) {
return true;
}
}
return false;
}
var options = {};
function defineOption(name, defaultValue, type, aliases, callback) {
if (defaultValue === void 0 && !callback) {
throw Error("defaultValue is required unless callback is provided");
}
if (!type) {
type = "string";
}
options[name] = {
type,
defaultValue,
callback
};
if (aliases) {
for (var i = 0; i < aliases.length; i++) {
options[aliases[i]] = options[name];
}
}
if (defaultValue) {
setOption(name, defaultValue);
}
}
function setOption(name, value, cm, cfg) {
var option = options[name];
cfg = cfg || {};
var scope = cfg.scope;
if (!option) {
return new Error("Unknown option: " + name);
}
if (option.type == "boolean") {
if (value && value !== true) {
return new Error("Invalid argument: " + name + "=" + value);
} else if (value !== false) {
value = true;
}
}
if (option.callback) {
if (scope !== "local") {
option.callback(value, void 0);
}
if (scope !== "global" && cm) {
option.callback(value, cm);
}
} else {
if (scope !== "local") {
option.value = option.type == "boolean" ? !!value : value;
}
if (scope !== "global" && cm) {
cm.state.vim.options[name] = { value };
}
}
}
function getOption(name, cm, cfg) {
var option = options[name];
cfg = cfg || {};
var scope = cfg.scope;
if (!option) {
return new Error("Unknown option: " + name);
}
if (option.callback) {
let local = cm && option.callback(void 0, cm);
if (scope !== "global" && local !== void 0) {
return local;
}
if (scope !== "local") {
return option.callback();
}
return;
} else {
let local = scope !== "global" && (cm && cm.state.vim.options[name]);
return (local || scope !== "local" && option || {}).value;
}
}
defineOption("filetype", void 0, "string", ["ft"], function(name, cm) {
if (cm === void 0) {
return;
}
if (name === void 0) {
let mode = cm.getOption("mode");
return mode == "null" ? "" : mode;
} else {
let mode = name == "" ? "null" : name;
cm.setOption("mode", mode);
}
});
defineOption("textwidth", 80, "number", ["tw"], function(width, cm) {
if (cm === void 0) {
return;
}
if (width === void 0) {
var value = cm.getOption("textwidth");
return value;
} else {
var column = Math.round(width);
if (column > 1) {
cm.setOption("textwidth", column);
}
}
});
var createCircularJumpList = function() {
var size = 100;
var pointer = -1;
var head = 0;
var tail = 0;
var buffer = (
/**@type {(Marker|undefined)[]} */
new Array(size)
);
function add(cm, oldCur, newCur) {
var current = pointer % size;
var curMark = buffer[current];
function useNextSlot(cursor) {
var next = ++pointer % size;
var trashMark = buffer[next];
if (trashMark) {
trashMark.clear();
}
buffer[next] = cm.setBookmark(cursor);
}
if (curMark) {
var markPos = curMark.find();
if (markPos && !cursorEqual(markPos, oldCur)) {
useNextSlot(oldCur);
}
} else {
useNextSlot(oldCur);
}
useNextSlot(newCur);
head = pointer;
tail = pointer - size + 1;
if (tail < 0) {
tail = 0;
}
}
function move(cm, offset) {
pointer += offset;
if (pointer > head) {
pointer = head;
} else if (pointer < tail) {
pointer = tail;
}
var mark = buffer[(size + pointer) % size];
if (mark && !mark.find()) {
var inc = offset > 0 ? 1 : -1;
var newCur;
var oldCur = cm.getCursor();
do {
pointer += inc;
mark = buffer[(size + pointer) % size];
if (mark && (newCur = mark.find()) && !cursorEqual(oldCur, newCur)) {
break;
}
} while (pointer < head && pointer > tail);
}
return mark;
}
function find(cm, offset) {
var oldPointer = pointer;
var mark = move(cm, offset);
pointer = oldPointer;
return mark && mark.find();
}
return {
/**@type{Pos|undefined} */
cachedCursor: void 0,
//used for # and * jumps
add,
find,
move
};
};
var createInsertModeChanges = function(c) {
if (c) {
return {
changes: c.changes,
expectCursorActivityForChange: c.expectCursorActivityForChange
};
}
return {
// Change list
changes: [],
// Set to true on change, false on cursorActivity.
expectCursorActivityForChange: false
};
};
class MacroModeState {
constructor() {
this.latestRegister = void 0;
this.isPlaying = false;
this.isRecording = false;
this.replaySearchQueries = [];
this.onRecordingDone = void 0;
this.lastInsertModeChanges = createInsertModeChanges();
}
exitMacroRecordMode() {
var macroModeState = vimGlobalState.macroModeState;
if (macroModeState.onRecordingDone) {
macroModeState.onRecordingDone();
}
macroModeState.onRecordingDone = void 0;
macroModeState.isRecording = false;
}
/**
* @arg {CodeMirror} cm
* @arg {string} registerName
*/
enterMacroRecordMode(cm, registerName) {
var register = vimGlobalState.registerController.getRegister(registerName);
if (register) {
register.clear();
this.latestRegister = registerName;
if (cm.openDialog) {
var template = dom("span", { class: "cm-vim-message" }, "recording @" + registerName);
this.onRecordingDone = cm.openDialog(template, function() {
}, { bottom: true });
}
this.isRecording = true;
}
}
}
function maybeInitVimState(cm) {
if (!cm.state.vim) {
cm.state.vim = {
inputState: new InputState(),
// Vim's input state that triggered the last edit, used to repeat
// motions and operators with '.'.
lastEditInputState: void 0,
// Vim's action command before the last edit, used to repeat actions
// with '.' and insert mode repeat.
lastEditActionCommand: void 0,
// When using jk for navigation, if you move from a longer line to a
// shorter line, the cursor may clip to the end of the shorter line.
// If j is pressed again and cursor goes to the next line, the
// cursor should go back to its horizontal position on the longer
// line if it can. This is to keep track of the horizontal position.
lastHPos: -1,
// Doing the same with screen-position for gj/gk
lastHSPos: -1,
// The last motion command run. Cleared if a non-motion command gets
// executed in between.
lastMotion: null,
marks: {},
insertMode: false,
insertModeReturn: false,
// Repeat count for changes made in insert mode, triggered by key
// sequences like 3,i. Only exists when insertMode is true.
insertModeRepeat: void 0,
visualMode: false,
// If we are in visual line mode. No effect if visualMode is false.
visualLine: false,
visualBlock: false,
lastSelection: (
/**@type{vimState["lastSelection"]}*/
/**@type{unknown}*/
null
),
lastPastedText: void 0,
sel: { anchor: new Pos2(0, 0), head: new Pos2(0, 0) },
// Buffer-local/window-local values of vim options.
options: {},
// Whether the next character should be interpreted literally
// Necassary for correct implementation of f<character>, r<character> etc.
// in terms of langmaps.
expectLiteralNext: false,
status: ""
};
}
return cm.state.vim;
}
var vimGlobalState;
function resetVimGlobalState() {
vimGlobalState = {
// The current search query.
searchQuery: null,
// Whether we are searching backwards.
searchIsReversed: false,
// Replace part of the last substituted pattern
lastSubstituteReplacePart: void 0,
jumpList: createCircularJumpList(),
macroModeState: new MacroModeState(),
// Recording latest f, t, F or T motion command.
lastCharacterSearch: { increment: 0, forward: true, selectedCharacter: "" },
registerController: new RegisterController({}),
// search history buffer
searchHistoryController: new HistoryController(),
// ex Command history buffer
exCommandHistoryController: new HistoryController()
};
for (var optionName in options) {
var option = options[optionName];
option.value = option.defaultValue;
}
}
class InsertModeKey {
/**
* Wrapper for special keys pressed in insert mode
* @arg {string} keyName
* @arg {KeyboardEvent} e
* @returns
*/
constructor(keyName, e) {
this.keyName = keyName;
this.key = e.key;
this.ctrlKey = e.ctrlKey;
this.altKey = e.altKey;
this.metaKey = e.metaKey;
this.shiftKey = e.shiftKey;
}
}
var lastInsertModeKeyTimer;
var vimApi = {
enterVimMode,
leaveVimMode,
buildKeyMap: function() {
},
// Testing hook, though it might be useful to expose the register
// controller anyway.
getRegisterController: function() {
return vimGlobalState.registerController;
},
// Testing hook.
resetVimGlobalState_: resetVimGlobalState,
// Testing hook.
getVimGlobalState_: function() {
return vimGlobalState;
},
// Testing hook.
maybeInitVimState_: maybeInitVimState,
suppressErrorLogging: false,
InsertModeKey,
/**@type {(lhs: string, rhs: string, ctx: string) => void} */
map: function(lhs, rhs, ctx) {
exCommandDispatcher.map(lhs, rhs, ctx);
},
/**@type {(lhs: string, ctx: string) => any} */
unmap: function(lhs, ctx) {
return exCommandDispatcher.unmap(lhs, ctx);
},
// Non-recursive map function.
// NOTE: This will not create mappings to key maps that aren't present
// in the default key map. See TODO at bottom of function.
/**@type {(lhs: string, rhs: string, ctx: string) => void} */
noremap: function(lhs, rhs, ctx) {
exCommandDispatcher.map(lhs, rhs, ctx, true);
},
// Remove all user-defined mappings for the provided context.
/**@arg {string} [ctx]} */
mapclear: function(ctx) {
var actualLength = defaultKeymap2.length, origLength = defaultKeymapLength;
var userKeymap = defaultKeymap2.slice(0, actualLength - origLength);
defaultKeymap2 = defaultKeymap2.slice(actualLength - origLength);
if (ctx) {
for (var i = userKeymap.length - 1; i >= 0; i--) {
var mapping = userKeymap[i];
if (ctx !== mapping.context) {
if (mapping.context) {
this._mapCommand(mapping);
} else {
var contexts = ["normal", "insert", "visual"];
for (var j in contexts) {
if (contexts[j] !== ctx) {
var newMapping = Object.assign({}, mapping);
newMapping.context = contexts[j];
this._mapCommand(newMapping);
}
}
}
}
}
}
},
langmap: updateLangmap,
vimKeyFromEvent,
// TODO: Expose setOption and getOption as instance methods. Need to decide how to namespace
// them, or somehow make them work with the existing CodeMirror setOption/getOption API.
setOption,
getOption,
defineOption,
/**@type {(name: string, prefix: string|undefined, func: ExFn) => void} */
defineEx: function(name, prefix, func) {
if (!prefix) {
prefix = name;
} else if (name.indexOf(prefix) !== 0) {
throw new Error('(Vim.defineEx) "' + prefix + '" is not a prefix of "' + name + '", command not registered');
}
exCommands[name] = func;
exCommandDispatcher.commandMap_[prefix] = { name, shortName: prefix, type: "api" };
},
/**@type {(cm: CodeMirror, key: string, origin: string) => undefined | boolean} */
handleKey: function(cm, key, origin) {
var command = this.findKey(cm, key, origin);
if (typeof command === "function") {
return command();
}
},
multiSelectHandleKey,
/**
* This is the outermost function called by CodeMirror, after keys have
* been mapped to their Vim equivalents.
*
* Finds a command based on the key (and cached keys if there is a
* multi-key sequence). Returns `undefined` if no key is matched, a noop
* function if a partial match is found (multi-key), and a function to
* execute the bound command if a a key is matched. The function always
* returns true.
*/
/**@type {(cm_: CodeMirror, key: string, origin?: string| undefined) => (() => boolean|undefined) | undefined} */
findKey: function(cm_, key, origin) {
var vim2 = maybeInitVimState(cm_);
var cm = (
/**@type {CodeMirrorV}*/
cm_
);
function handleMacroRecording() {
var macroModeState = vimGlobalState.macroModeState;
if (macroModeState.isRecording) {
if (key == "q") {
macroModeState.exitMacroRecordMode();
clearInputState(cm);
return true;
}
if (origin != "mapping") {
logKey(macroModeState, key);
}
}
}
function handleEsc() {
if (key == "<Esc>") {
if (vim2.visualMode) {
exitVisualMode(cm);
} else if (vim2.insertMode) {
exitInsertMode(cm);
} else {
return;
}
clearInputState(cm);
return true;
}
}
function handleKeyInsertMode() {
if (handleEsc()) {
return true;
}
vim2.inputState.keyBuffer.push(key);
var keys2 = vim2.inputState.keyBuffer.join("");
var keysAreChars = key.length == 1;
var match = commandDispatcher.matchCommand(keys2, defaultKeymap2, vim2.inputState, "insert");
var changeQueue = vim2.inputState.changeQueue;
if (match.type == "none") {
clearInputState(cm);
return false;
} else if (match.type == "partial") {
if (match.expectLiteralNext) vim2.expectLiteralNext = true;
if (lastInsertModeKeyTimer) {
window.clearTimeout(lastInsertModeKeyTimer);
}
lastInsertModeKeyTimer = keysAreChars && window.setTimeout(
function() {
if (vim2.insertMode && vim2.inputState.keyBuffer.length) {
clearInputState(cm);
}
},
getOption("insertModeEscKeysTimeout")
);
if (keysAreChars) {
var selections = cm.listSelections();
if (!changeQueue || changeQueue.removed.length != selections.length)
changeQueue = vim2.inputState.changeQueue = new ChangeQueue();
changeQueue.inserted += key;
for (var i = 0; i < selections.length; i++) {
var from = cursorMin(selections[i].anchor, selections[i].head);
var to = cursorMax(selections[i].anchor, selections[i].head);
var text = cm.getRange(from, cm.state.overwrite ? offsetCursor(to, 0, 1) : to);
changeQueue.removed[i] = (changeQueue.removed[i] || "") + text;
}
}
return !keysAreChars;
} else if (match.type == "full") {
vim2.inputState.keyBuffer.length = 0;
}
vim2.expectLiteralNext = false;
if (lastInsertModeKeyTimer) {
window.clearTimeout(lastInsertModeKeyTimer);
}
if (match.command && changeQueue) {
var selections = cm.listSelections();
for (var i = 0; i < selections.length; i++) {
var here = selections[i].head;
cm.replaceRange(
changeQueue.removed[i] || "",
offsetCursor(here, 0, -changeQueue.inserted.length),
here,
"+input"
);
}
vimGlobalState.macroModeState.lastInsertModeChanges.changes.pop();
}
if (!match.command) clearInputState(cm);
return match.command;
}
function handleKeyNonInsertMode() {
if (handleMacroRecording() || handleEsc()) {
return true;
}
vim2.inputState.keyBuffer.push(key);
var keys2 = vim2.inputState.keyBuffer.join("");
if (/^[1-9]\d*$/.test(keys2)) {
return true;
}
var keysMatcher = /^(\d*)(.*)$/.exec(keys2);
if (!keysMatcher) {
clearInputState(cm);
return false;
}
var context = vim2.visualMode ? "visual" : "normal";
var mainKey = keysMatcher[2] || keysMatcher[1];
if (vim2.inputState.operatorShortcut && vim2.inputState.operatorShortcut.slice(-1) == mainKey) {
mainKey = vim2.inputState.operatorShortcut;
}
var match = commandDispatcher.matchCommand(mainKey, defaultKeymap2, vim2.inputState, context);
if (match.type == "none") {
clearInputState(cm);
return false;
} else if (match.type == "partial") {
if (match.expectLiteralNext) vim2.expectLiteralNext = true;
return true;
} else if (match.type == "clear") {
clearInputState(cm);
return true;
}
vim2.expectLiteralNext = false;
vim2.inputState.keyBuffer.length = 0;
keysMatcher = /^(\d*)(.*)$/.exec(keys2);
if (keysMatcher && keysMatcher[1] && keysMatcher[1] != "0") {
vim2.inputState.pushRepeatDigit(keysMatcher[1]);
}
return match.command;
}
var command = vim2.insertMode ? handleKeyInsertMode() : handleKeyNonInsertMode();
if (command === false) {
return !vim2.insertMode && (key.length === 1 || CM.isMac && /<A-.>/.test(key)) ? function() {
return true;
} : void 0;
} else if (command === true) {
return function() {
return true;
};
} else if (command) {
return function() {
return cm.operation(function() {
cm.curOp.isVimOp = true;
try {
if (typeof command != "object") return;
if (command.type == "keyToKey") {
doKeyToKey(cm, command.toKeys, command);
} else {
commandDispatcher.processCommand(cm, vim2, command);
}
} catch (e) {
cm.state.vim = void 0;
maybeInitVimState(cm);
if (!vimApi.suppressErrorLogging) {
console["log"](e);
}
throw e;
}
return true;
});
};
}
},
/**@type {(cm: CodeMirrorV, input: string)=>void} */
handleEx: function(cm, input) {
exCommandDispatcher.processCommand(cm, input);
},
defineMotion,
defineAction,
defineOperator,
mapCommand,
_mapCommand,
defineRegister,
exitVisualMode,
exitInsertMode
};
var keyToKeyStack = [];
var noremap = false;
var virtualPrompt;
function sendKeyToPrompt(key) {
if (!virtualPrompt) throw new Error("No prompt to send key to");
if (key[0] == "<") {
var lowerKey = key.toLowerCase().slice(1, -1);
var parts = lowerKey.split("-");
lowerKey = parts.pop() || "";
if (lowerKey == "lt") key = "<";
else if (lowerKey == "space") key = " ";
else if (lowerKey == "cr") key = "\n";
else if (vimToCmKeyMap[lowerKey]) {
var value = virtualPrompt.value || "";
var event = {
key: vimToCmKeyMap[lowerKey],
target: {
value,
selectionEnd: value.length,
selectionStart: value.length
}
};
if (virtualPrompt.onKeyDown) {
virtualPrompt.onKeyDown(event, virtualPrompt.value, close);
}
if (virtualPrompt && virtualPrompt.onKeyUp) {
virtualPrompt.onKeyUp(event, virtualPrompt.value, close);
}
return;
}
}
if (key == "\n") {
var prompt2 = virtualPrompt;
virtualPrompt = null;
prompt2.onClose && prompt2.onClose(prompt2.value);
} else {
virtualPrompt.value = (virtualPrompt.value || "") + key;
}
function close(value2) {
if (!virtualPrompt) return;
if (typeof value2 == "string") {
virtualPrompt.value = value2;
} else {
virtualPrompt = null;
}
}
}
function doKeyToKey(cm, keys2, fromKey) {
var noremapBefore = noremap;
if (fromKey) {
if (keyToKeyStack.indexOf(fromKey) != -1) return;
keyToKeyStack.push(fromKey);
noremap = fromKey.noremap != false;
}
try {
var vim2 = maybeInitVimState(cm);
var keyRe = /<(?:[CSMA]-)*\w+>|./gi;
var match;
while (match = keyRe.exec(keys2)) {
var key = match[0];
var wasInsert = vim2.insertMode;
if (virtualPrompt) {
sendKeyToPrompt(key);
continue;
}
var result = vimApi.handleKey(cm, key, "mapping");
if (!result && wasInsert && vim2.insertMode) {
if (key[0] == "<") {
var lowerKey = key.toLowerCase().slice(1, -1);
var parts = lowerKey.split("-");
lowerKey = parts.pop() || "";
if (lowerKey == "lt") key = "<";
else if (lowerKey == "space") key = " ";
else if (lowerKey == "cr") key = "\n";
else if (vimToCmKeyMap.hasOwnProperty(lowerKey)) {
key = vimToCmKeyMap[lowerKey];
sendCmKey(cm, key);
continue;
} else {
key = key[0];
keyRe.lastIndex = match.index + 1;
}
}
cm.replaceSelection(key);
}
}
} finally {
keyToKeyStack.pop();
noremap = keyToKeyStack.length ? noremapBefore : false;
if (!keyToKeyStack.length && virtualPrompt) {
var promptOptions = virtualPrompt;
virtualPrompt = null;
showPrompt(cm, promptOptions);
}
}
}
var specialKey = {
Return: "CR",
Backspace: "BS",
"Delete": "Del",
Escape: "Esc",
Insert: "Ins",
ArrowLeft: "Left",
ArrowRight: "Right",
ArrowUp: "Up",
ArrowDown: "Down",
Enter: "CR",
" ": "Space"
};
var ignoredKeys = {
Shift: 1,
Alt: 1,
Command: 1,
Control: 1,
CapsLock: 1,
AltGraph: 1,
Dead: 1,
Unidentified: 1
};
var vimToCmKeyMap = {};
"Left|Right|Up|Down|End|Home".split("|").concat(Object.keys(specialKey)).forEach(function(x) {
vimToCmKeyMap[(specialKey[x] || "").toLowerCase()] = vimToCmKeyMap[x.toLowerCase()] = x;
});
function vimKeyFromEvent(e, vim2) {
var _a;
var key = e.key;
if (ignoredKeys[key]) return;
if (key.length > 1 && key[0] == "n") {
key = key.replace("Numpad", "");
}
key = specialKey[key] || key;
var name = "";
if (e.ctrlKey) {
name += "C-";
}
if (e.altKey) {
name += "A-";
}
if (e.metaKey) {
name += "M-";
}
if (CM.isMac && name == "A-" && key.length == 1) {
name = name.slice(2);
}
if ((name || key.length > 1) && e.shiftKey) {
name += "S-";
}
if (vim2 && !vim2.expectLiteralNext && key.length == 1) {
if (langmap.keymap && key in langmap.keymap) {
if (langmap.remapCtrl != false || !name)
key = langmap.keymap[key];
} else if (key.charCodeAt(0) > 128) {
if (!usedKeys[key]) {
var code = ((_a = e.code) == null ? void 0 : _a.slice(-1)) || "";
if (!e.shiftKey) code = code.toLowerCase();
if (code) {
key = code;
if (!name && e.altKey) name = "A-";
}
}
}
}
name += key;
if (name.length > 1) {
name = "<" + name + ">";
}
return name;
}
function updateLangmap(langmapString, remapCtrl) {
if (langmap.string !== langmapString) {
langmap = parseLangmap(langmapString);
}
langmap.remapCtrl = remapCtrl;
}
function parseLangmap(langmapString) {
let keymap3 = {};
if (!langmapString) return { keymap: keymap3, string: "" };
function getEscaped(list) {
return list.split(/\\?(.)/).filter(Boolean);
}
langmapString.split(/((?:[^\\,]|\\.)+),/).map((part) => {
if (!part) return;
const semicolon = part.split(/((?:[^\\;]|\\.)+);/);
if (semicolon.length == 3) {
const from = getEscaped(semicolon[1]);
const to = getEscaped(semicolon[2]);
if (from.length !== to.length) return;
for (let i = 0; i < from.length; ++i) keymap3[from[i]] = to[i];
} else if (semicolon.length == 1) {
const pairs = getEscaped(part);
if (pairs.length % 2 !== 0) return;
for (let i = 0; i < pairs.length; i += 2) keymap3[pairs[i]] = pairs[i + 1];
}
});
return { keymap: keymap3, string: langmapString };
}
defineOption("langmap", void 0, "string", ["lmap"], function(name, cm) {
if (name === void 0) {
return langmap.string;
} else {
updateLangmap(name);
}
});
class InputState {
constructor() {
this.prefixRepeat = [];
this.motionRepeat = [];
this.operator = null;
this.operatorArgs = null;
this.motion = null;
this.motionArgs = null;
this.keyBuffer = [];
this.registerName = void 0;
this.changeQueue = null;
}
/** @param {string} n */
pushRepeatDigit(n) {
if (!this.operator) {
this.prefixRepeat = this.prefixRepeat.concat(n);
} else {
this.motionRepeat = this.motionRepeat.concat(n);
}
}
getRepeat() {
var repeat = 0;
if (this.prefixRepeat.length > 0 || this.motionRepeat.length > 0) {
repeat = 1;
if (this.prefixRepeat.length > 0) {
repeat *= parseInt(this.prefixRepeat.join(""), 10);
}
if (this.motionRepeat.length > 0) {
repeat *= parseInt(this.motionRepeat.join(""), 10);
}
}
return repeat;
}
}
function clearInputState(cm, reason) {
cm.state.vim.inputState = new InputState();
cm.state.vim.expectLiteralNext = false;
CM.signal(cm, "vim-command-done", reason);
}
function ChangeQueue() {
this.removed = [];
this.inserted = "";
}
class Register {
/** @arg {string} [text] @arg {boolean} [linewise] @arg {boolean } [blockwise] */
constructor(text, linewise, blockwise) {
this.clear();
this.keyBuffer = [text || ""];
this.insertModeChanges = [];
this.searchQueries = [];
this.linewise = !!linewise;
this.blockwise = !!blockwise;
}
/** @arg {string} [text] @arg {boolean} [linewise] @arg {boolean } [blockwise] */
setText(text, linewise, blockwise) {
this.keyBuffer = [text || ""];
this.linewise = !!linewise;
this.blockwise = !!blockwise;
}
/** @arg {string} text @arg {boolean} [linewise] */
pushText(text, linewise) {
if (linewise) {
if (!this.linewise) {
this.keyBuffer.push("\n");
}
this.linewise = true;
}
this.keyBuffer.push(text);
}
/** @arg {InsertModeChanges} changes */
pushInsertModeChanges(changes) {
this.insertModeChanges.push(createInsertModeChanges(changes));
}
/** @arg {string} query */
pushSearchQuery(query) {
this.searchQueries.push(query);
}
clear() {
this.keyBuffer = [];
this.insertModeChanges = [];
this.searchQueries = [];
this.linewise = false;
}
toString() {
return this.keyBuffer.join("");
}
}
function defineRegister(name, register) {
var registers = vimGlobalState.registerController.registers;
if (!name || name.length != 1) {
throw Error("Register name must be 1 character");
}
if (registers[name]) {
throw Error("Register already defined " + name);
}
registers[name] = register;
validRegisters.push(name);
}
class RegisterController {
/** @arg {Object<string, Register>} registers */
constructor(registers) {
this.registers = registers;
this.unnamedRegister = registers['"'] = new Register();
registers["."] = new Register();
registers[":"] = new Register();
registers["/"] = new Register();
registers["+"] = new Register();
}
/**
* @param {string | null | undefined} registerName
* @param {string} operator
* @param {string} text
* @param {boolean} [linewise]
* @param {boolean} [blockwise]
*/
pushText(registerName, operator, text, linewise, blockwise) {
if (registerName === "_") return;
if (linewise && text.charAt(text.length - 1) !== "\n") {
text += "\n";
}
var register = this.isValidRegister(registerName) ? this.getRegister(registerName) : null;
if (!register || !registerName) {
switch (operator) {
case "yank":
this.registers["0"] = new Register(text, linewise, blockwise);
break;
case "delete":
case "change":
if (text.indexOf("\n") == -1) {
this.registers["-"] = new Register(text, linewise);
} else {
this.shiftNumericRegisters_();
this.registers["1"] = new Register(text, linewise);
}
break;
}
this.unnamedRegister.setText(text, linewise, blockwise);
return;
}
var append = isUpperCase(registerName);
if (append) {
register.pushText(text, linewise);
} else {
register.setText(text, linewise, blockwise);
}
if (registerName === "+") {
navigator.clipboard.writeText(text);
}
this.unnamedRegister.setText(register.toString(), linewise);
}
/**
* Gets the register named @name. If one of @name doesn't already exist,
* create it. If @name is invalid, return the unnamedRegister.
* @arg {string} [name]
*/
getRegister(name) {
if (!this.isValidRegister(name)) {
return this.unnamedRegister;
}
name = name.toLowerCase();
if (!this.registers[name]) {
this.registers[name] = new Register();
}
return this.registers[name];
}
/**@type {{(name: any): name is string}} */
isValidRegister(name) {
return name && (inArray(name, validRegisters) || latinCharRegex.test(name));
}
shiftNumericRegisters_() {
for (var i = 9; i >= 2; i--) {
this.registers[i] = this.getRegister("" + (i - 1));
}
}
}
class HistoryController {
constructor() {
this.historyBuffer = [];
this.iterator = 0;
this.initialPrefix = null;
}
/**
* the input argument here acts a user entered prefix for a small time
* until we start autocompletion in which case it is the autocompleted.
* @arg {string} input
* @arg {boolean} up
*/
nextMatch(input, up) {
var historyBuffer = this.historyBuffer;
var dir = up ? -1 : 1;
if (this.initialPrefix === null) this.initialPrefix = input;
for (var i = this.iterator + dir; up ? i >= 0 : i < historyBuffer.length; i += dir) {
var element = historyBuffer[i];
for (var j = 0; j <= element.length; j++) {
if (this.initialPrefix == element.substring(0, j)) {
this.iterator = i;
return element;
}
}
}
if (i >= historyBuffer.length) {
this.iterator = historyBuffer.length;
return this.initialPrefix;
}
if (i < 0) return input;
}
/** @arg {string} input */
pushInput(input) {
var index = this.historyBuffer.indexOf(input);
if (index > -1) this.historyBuffer.splice(index, 1);
if (input.length) this.historyBuffer.push(input);
}
reset() {
this.initialPrefix = null;
this.iterator = this.historyBuffer.length;
}
}
var commandDispatcher = {
/**
* @param {string} keys
* @param {vimKey[]} keyMap
* @param {InputStateInterface} inputState
* @param {string} context
*/
matchCommand: function(keys2, keyMap, inputState, context) {
var matches = commandMatches(keys2, keyMap, context, inputState);
var bestMatch = matches.full[0];
if (!bestMatch) {
if (matches.partial.length) {
return {
type: "partial",
expectLiteralNext: matches.partial.length == 1 && matches.partial[0].keys.slice(-11) == "<character>"
// langmap literal logic
};
}
return { type: "none" };
}
if (bestMatch.keys.slice(-11) == "<character>" || bestMatch.keys.slice(-10) == "<register>") {
var character = lastChar(keys2);
if (!character || character.length > 1) return { type: "clear" };
inputState.selectedCharacter = character;
}
return { type: "full", command: bestMatch };
},
/**
* @arg {CodeMirrorV} cm
* @arg {vimState} vim
* @arg {vimKey} command
*/
processCommand: function(cm, vim2, command) {
vim2.inputState.repeatOverride = command.repeatOverride;
switch (command.type) {
case "motion":
this.processMotion(cm, vim2, command);
break;
case "operator":
this.processOperator(cm, vim2, command);
break;
case "operatorMotion":
this.processOperatorMotion(cm, vim2, command);
break;
case "action":
this.processAction(cm, vim2, command);
break;
case "search":
this.processSearch(cm, vim2, command);
break;
case "ex":
case "keyToEx":
this.processEx(cm, vim2, command);
break;
}
},
/**
* @arg {CodeMirrorV} cm
* @arg {vimState} vim
* @arg {import("./types").motionCommand|import("./types").operatorMotionCommand} command
*/
processMotion: function(cm, vim2, command) {
vim2.inputState.motion = command.motion;
vim2.inputState.motionArgs = /**@type {MotionArgs}*/
copyArgs(command.motionArgs);
this.evalInput(cm, vim2);
},
/**
* @arg {CodeMirrorV} cm
* @arg {vimState} vim
* @arg {import("./types").operatorCommand|import("./types").operatorMotionCommand} command
*/
processOperator: function(cm, vim2, command) {
var inputState = vim2.inputState;
if (inputState.operator) {
if (inputState.operator == command.operator) {
inputState.motion = "expandToLine";
inputState.motionArgs = { linewise: true, repeat: 1 };
this.evalInput(cm, vim2);
return;
} else {
clearInputState(cm);
}
}
inputState.operator = command.operator;
inputState.operatorArgs = copyArgs(command.operatorArgs);
if (command.keys.length > 1) {
inputState.operatorShortcut = command.keys;
}
if (command.exitVisualBlock) {
vim2.visualBlock = false;
updateCmSelection(cm);
}
if (vim2.visualMode) {
this.evalInput(cm, vim2);
}
},
/**
* @arg {CodeMirrorV} cm
* @arg {vimState} vim
* @arg {import("./types").operatorMotionCommand} command
*/
processOperatorMotion: function(cm, vim2, command) {
var visualMode = vim2.visualMode;
var operatorMotionArgs = copyArgs(command.operatorMotionArgs);
if (operatorMotionArgs) {
if (visualMode && operatorMotionArgs.visualLine) {
vim2.visualLine = true;
}
}
this.processOperator(cm, vim2, command);
if (!visualMode) {
this.processMotion(cm, vim2, command);
}
},
/**
* @arg {CodeMirrorV} cm
* @arg {vimState} vim
* @arg {import("./types").actionCommand} command
*/
processAction: function(cm, vim2, command) {
var inputState = vim2.inputState;
var repeat = inputState.getRepeat();
var repeatIsExplicit = !!repeat;
var actionArgs = (
/**@type {ActionArgs}*/
copyArgs(command.actionArgs) || { repeat: 1 }
);
if (inputState.selectedCharacter) {
actionArgs.selectedCharacter = inputState.selectedCharacter;
}
if (command.operator) {
this.processOperator(cm, vim2, command);
}
if (command.motion) {
this.processMotion(cm, vim2, command);
}
if (command.motion || command.operator) {
this.evalInput(cm, vim2);
}
actionArgs.repeat = repeat || 1;
actionArgs.repeatIsExplicit = repeatIsExplicit;
actionArgs.registerName = inputState.registerName;
clearInputState(cm);
vim2.lastMotion = null;
if (command.isEdit) {
this.recordLastEdit(vim2, inputState, command);
}
actions[command.action](cm, actionArgs, vim2);
},
/** @arg {CodeMirrorV} cm @arg {vimState} vim @arg {import("./types").searchCommand} command*/
processSearch: function(cm, vim2, command) {
if (!cm.getSearchCursor) {
return;
}
var forward = command.searchArgs.forward;
var wholeWordOnly = command.searchArgs.wholeWordOnly;
getSearchState(cm).setReversed(!forward);
var promptPrefix = forward ? "/" : "?";
var originalQuery = getSearchState(cm).getQuery();
var originalScrollPos = cm.getScrollInfo();
var lastQuery = "";
function handleQuery(query, ignoreCase, smartCase) {
vimGlobalState.searchHistoryController.pushInput(query);
vimGlobalState.searchHistoryController.reset();
try {
updateSearchQuery(cm, query, ignoreCase, smartCase);
} catch (e) {
showConfirm(cm, "Invalid regex: " + query);
clearInputState(cm);
return;
}
commandDispatcher.processMotion(cm, vim2, {
keys: "",
type: "motion",
motion: "findNext",
motionArgs: { forward: true, toJumplist: command.searchArgs.toJumplist }
});
}
function onPromptClose(query) {
cm.scrollTo(originalScrollPos.left, originalScrollPos.top);
handleQuery(
query,
true,
true
/** smartCase */
);
var macroModeState2 = vimGlobalState.macroModeState;
if (macroModeState2.isRecording) {
logSearchQuery(macroModeState2, query);
}
}
function pcreLabel() {
return getOption("pcre") ? "(JavaScript regexp: set pcre)" : "(Vim regexp: set nopcre)";
}
function onPromptKeyUp(e, query, close) {
var keyName = vimKeyFromEvent(e), up, offset;
if (keyName == "<Up>" || keyName == "<Down>") {
up = keyName == "<Up>" ? true : false;
offset = e.target ? e.target.selectionEnd : 0;
query = vimGlobalState.searchHistoryController.nextMatch(query, up) || "";
close(query);
if (offset && e.target) e.target.selectionEnd = e.target.selectionStart = Math.min(offset, e.target.value.length);
} else if (keyName && keyName != "<Left>" && keyName != "<Right>") {
vimGlobalState.searchHistoryController.reset();
}
lastQuery = query;
onChange2();
}
function onChange2() {
var parsedQuery;
try {
parsedQuery = updateSearchQuery(
cm,
lastQuery,
true,
true
/** smartCase */
);
} catch (e) {
}
if (parsedQuery) {
cm.scrollIntoView(findNext(cm, !forward, parsedQuery), 30);
} else {
clearSearchHighlight(cm);
cm.scrollTo(originalScrollPos.left, originalScrollPos.top);
}
}
function onPromptKeyDown(e, query, close) {
var keyName = vimKeyFromEvent(e);
if (keyName == "<Esc>" || keyName == "<C-c>" || keyName == "<C-[>" || keyName == "<BS>" && query == "") {
vimGlobalState.searchHistoryController.pushInput(query);
vimGlobalState.searchHistoryController.reset();
updateSearchQuery(cm, (originalQuery == null ? void 0 : originalQuery.source) || "");
clearSearchHighlight(cm);
cm.scrollTo(originalScrollPos.left, originalScrollPos.top);
CM.e_stop(e);
clearInputState(cm);
close();
cm.focus();
} else if (keyName == "<Up>" || keyName == "<Down>") {
CM.e_stop(e);
} else if (keyName == "<C-u>") {
CM.e_stop(e);
close("");
}
}
switch (command.searchArgs.querySrc) {
case "prompt":
var macroModeState = vimGlobalState.macroModeState;
if (macroModeState.isPlaying) {
let query2 = macroModeState.replaySearchQueries.shift();
handleQuery(
query2 || "",
true,
false
/** smartCase */
);
} else {
showPrompt(cm, {
onClose: onPromptClose,
prefix: promptPrefix,
desc: dom(
"span",
{
$cursor: "pointer",
onmousedown: function(e) {
e.preventDefault();
setOption("pcre", !getOption("pcre"));
this.textContent = pcreLabel();
onChange2();
}
},
pcreLabel()
),
onKeyUp: onPromptKeyUp,
onKeyDown: onPromptKeyDown
});
}
break;
case "wordUnderCursor":
var word = expandWordUnderCursor(cm, { noSymbol: true });
var isKeyword = true;
if (!word) {
word = expandWordUnderCursor(cm, { noSymbol: false });
isKeyword = false;
}
if (!word) {
showConfirm(cm, "No word under cursor");
clearInputState(cm);
return;
}
let query = cm.getLine(word.start.line).substring(
word.start.ch,
word.end.ch
);
if (isKeyword && wholeWordOnly) {
query = "\\b" + query + "\\b";
} else {
query = escapeRegex(query);
}
vimGlobalState.jumpList.cachedCursor = cm.getCursor();
cm.setCursor(word.start);
handleQuery(
query,
true,
false
/** smartCase */
);
break;
}
},
/**
* @arg {CodeMirrorV} cm
* @arg {vimState} vim
* @arg {import("./types").exCommand | import("./types").keyToExCommand} command
*/
processEx: function(cm, vim2, command) {
function onPromptClose(input) {
vimGlobalState.exCommandHistoryController.pushInput(input);
vimGlobalState.exCommandHistoryController.reset();
exCommandDispatcher.processCommand(cm, input);
if (cm.state.vim) clearInputState(cm);
clearSearchHighlight(cm);
}
function onPromptKeyDown(e, input, close) {
var keyName = vimKeyFromEvent(e), up, offset;
if (keyName == "<Esc>" || keyName == "<C-c>" || keyName == "<C-[>" || keyName == "<BS>" && input == "") {
vimGlobalState.exCommandHistoryController.pushInput(input);
vimGlobalState.exCommandHistoryController.reset();
CM.e_stop(e);
clearInputState(cm);
clearSearchHighlight(cm);
close();
cm.focus();
}
if (keyName == "<Up>" || keyName == "<Down>") {
CM.e_stop(e);
up = keyName == "<Up>" ? true : false;
offset = e.target ? e.target.selectionEnd : 0;
input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || "";
close(input);
if (offset && e.target) e.target.selectionEnd = e.target.selectionStart = Math.min(offset, e.target.value.length);
} else if (keyName == "<C-u>") {
CM.e_stop(e);
close("");
} else if (keyName && keyName != "<Left>" && keyName != "<Right>") {
vimGlobalState.exCommandHistoryController.reset();
}
}
function onPromptKeyUp(e, query) {
var inputStream = new CM.StringStream(query);
var params = (
/**@type{import("./types").exCommandArgs}*/
{}
);
try {
exCommandDispatcher.parseInput_(cm, inputStream, params);
if (params.commandName != "s") {
clearSearchHighlight(cm);
return;
}
var command2 = exCommandDispatcher.matchCommand_(params.commandName);
if (!command2) return;
exCommandDispatcher.parseCommandArgs_(inputStream, params, command2);
if (!params.argString) return;
var regex = parseQuery(params.argString.slice(1), true, true);
if (regex) highlightSearchMatches(cm, regex);
} catch (e2) {
}
}
if (command.type == "keyToEx") {
exCommandDispatcher.processCommand(cm, command.exArgs.input);
} else {
var promptOptions = {
onClose: onPromptClose,
onKeyDown: onPromptKeyDown,
onKeyUp: onPromptKeyUp,
prefix: ":"
};
if (vim2.visualMode) {
promptOptions.value = "'<,'>";
promptOptions.selectValueOnOpen = false;
}
showPrompt(cm, promptOptions);
}
},
/**@arg {CodeMirrorV} cm @arg {vimState} vim */
evalInput: function(cm, vim2) {
var inputState = vim2.inputState;
var motion = inputState.motion;
var motionArgs = inputState.motionArgs || { repeat: 1 };
var operator = inputState.operator;
var operatorArgs = inputState.operatorArgs || {};
var registerName = inputState.registerName;
var sel = vim2.sel;
var origHead = copyCursor(vim2.visualMode ? clipCursorToContent(cm, sel.head) : cm.getCursor("head"));
var origAnchor = copyCursor(vim2.visualMode ? clipCursorToContent(cm, sel.anchor) : cm.getCursor("anchor"));
var oldHead = copyCursor(origHead);
var oldAnchor = copyCursor(origAnchor);
var newHead, newAnchor;
var repeat;
if (operator) {
this.recordLastEdit(vim2, inputState);
}
if (inputState.repeatOverride !== void 0) {
repeat = inputState.repeatOverride;
} else {
repeat = inputState.getRepeat();
}
if (repeat > 0 && motionArgs.explicitRepeat) {
motionArgs.repeatIsExplicit = true;
} else if (motionArgs.noRepeat || !motionArgs.explicitRepeat && repeat === 0) {
repeat = 1;
motionArgs.repeatIsExplicit = false;
}
if (inputState.selectedCharacter) {
motionArgs.selectedCharacter = operatorArgs.selectedCharacter = inputState.selectedCharacter;
}
motionArgs.repeat = repeat;
clearInputState(cm);
if (motion) {
var motionResult = motions[motion](cm, origHead, motionArgs, vim2, inputState);
vim2.lastMotion = motions[motion];
if (!motionResult) {
return;
}
if (motionArgs.toJumplist) {
var jumpList = vimGlobalState.jumpList;
var cachedCursor = jumpList.cachedCursor;
if (cachedCursor) {
recordJumpPosition(cm, cachedCursor, motionResult);
delete jumpList.cachedCursor;
} else {
recordJumpPosition(cm, origHead, motionResult);
}
}
if (motionResult instanceof Array) {
newAnchor = motionResult[0];
newHead = motionResult[1];
} else {
newHead = motionResult;
}
if (!newHead) {
newHead = copyCursor(origHead);
}
if (vim2.visualMode) {
if (!(vim2.visualBlock && newHead.ch === Infinity)) {
newHead = clipCursorToContent(cm, newHead, oldHead);
}
if (newAnchor) {
newAnchor = clipCursorToContent(cm, newAnchor);
}
newAnchor = newAnchor || oldAnchor;
sel.anchor = newAnchor;
sel.head = newHead;
updateCmSelection(cm);
updateMark(
cm,
vim2,
"<",
cursorIsBefore(newAnchor, newHead) ? newAnchor : newHead
);
updateMark(
cm,
vim2,
">",
cursorIsBefore(newAnchor, newHead) ? newHead : newAnchor
);
} else if (!operator) {
newHead = clipCursorToContent(cm, newHead, oldHead);
cm.setCursor(newHead.line, newHead.ch);
}
}
if (operator) {
if (operatorArgs.lastSel) {
newAnchor = oldAnchor;
var lastSel = operatorArgs.lastSel;
var lineOffset = Math.abs(lastSel.head.line - lastSel.anchor.line);
var chOffset = Math.abs(lastSel.head.ch - lastSel.anchor.ch);
if (lastSel.visualLine) {
newHead = new Pos2(oldAnchor.line + lineOffset, oldAnchor.ch);
} else if (lastSel.visualBlock) {
newHead = new Pos2(oldAnchor.line + lineOffset, oldAnchor.ch + chOffset);
} else if (lastSel.head.line == lastSel.anchor.line) {
newHead = new Pos2(oldAnchor.line, oldAnchor.ch + chOffset);
} else {
newHead = new Pos2(oldAnchor.line + lineOffset, oldAnchor.ch);
}
vim2.visualMode = true;
vim2.visualLine = lastSel.visualLine;
vim2.visualBlock = lastSel.visualBlock;
sel = vim2.sel = {
anchor: newAnchor,
head: newHead
};
updateCmSelection(cm);
} else if (vim2.visualMode) {
operatorArgs.lastSel = {
anchor: copyCursor(sel.anchor),
head: copyCursor(sel.head),
visualBlock: vim2.visualBlock,
visualLine: vim2.visualLine
};
}
var curStart, curEnd, linewise;
var mode;
var cmSel;
if (vim2.visualMode) {
curStart = cursorMin(sel.head, sel.anchor);
curEnd = cursorMax(sel.head, sel.anchor);
linewise = vim2.visualLine || operatorArgs.linewise;
mode = vim2.visualBlock ? "block" : linewise ? "line" : "char";
var newPositions = updateSelectionForSurrogateCharacters(cm, curStart, curEnd);
cmSel = makeCmSelection(cm, {
anchor: newPositions.start,
head: newPositions.end
}, mode);
if (linewise) {
var ranges = cmSel.ranges;
if (mode == "block") {
for (var i = 0; i < ranges.length; i++) {
ranges[i].head.ch = lineLength(cm, ranges[i].head.line);
}
} else if (mode == "line") {
ranges[0].head = new Pos2(ranges[0].head.line + 1, 0);
}
}
} else {
curStart = copyCursor(newAnchor || oldAnchor);
curEnd = copyCursor(newHead || oldHead);
if (cursorIsBefore(curEnd, curStart)) {
var tmp = curStart;
curStart = curEnd;
curEnd = tmp;
}
linewise = motionArgs.linewise || operatorArgs.linewise;
if (linewise) {
expandSelectionToLine(cm, curStart, curEnd);
} else if (motionArgs.forward) {
clipToLine(cm, curStart, curEnd);
}
mode = "char";
var exclusive = !motionArgs.inclusive || linewise;
var newPositions = updateSelectionForSurrogateCharacters(cm, curStart, curEnd);
cmSel = makeCmSelection(cm, {
anchor: newPositions.start,
head: newPositions.end
}, mode, exclusive);
}
cm.setSelections(cmSel.ranges, cmSel.primary);
vim2.lastMotion = null;
operatorArgs.repeat = repeat;
operatorArgs.registerName = registerName;
operatorArgs.linewise = linewise;
var operatorMoveTo = operators[operator](
cm,
operatorArgs,
cmSel.ranges,
oldAnchor,
newHead
);
if (vim2.visualMode) {
exitVisualMode(cm, operatorMoveTo != null);
}
if (operatorMoveTo) {
cm.setCursor(operatorMoveTo);
}
}
},
/**@arg {vimState} vim @arg {InputStateInterface} inputState, @arg {import("./types").actionCommand} [actionCommand] */
recordLastEdit: function(vim2, inputState, actionCommand) {
var macroModeState = vimGlobalState.macroModeState;
if (macroModeState.isPlaying) {
return;
}
vim2.lastEditInputState = inputState;
vim2.lastEditActionCommand = actionCommand;
macroModeState.lastInsertModeChanges.changes = [];
macroModeState.lastInsertModeChanges.expectCursorActivityForChange = false;
macroModeState.lastInsertModeChanges.visualBlock = vim2.visualBlock ? vim2.sel.head.line - vim2.sel.anchor.line : 0;
}
};
var motions = {
moveToTopLine: function(cm, _head, motionArgs) {
var line = getUserVisibleLines(cm).top + motionArgs.repeat - 1;
return new Pos2(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)));
},
moveToMiddleLine: function(cm) {
var range = getUserVisibleLines(cm);
var line = Math.floor((range.top + range.bottom) * 0.5);
return new Pos2(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)));
},
moveToBottomLine: function(cm, _head, motionArgs) {
var line = getUserVisibleLines(cm).bottom - motionArgs.repeat + 1;
return new Pos2(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)));
},
expandToLine: function(_cm, head, motionArgs) {
var cur2 = head;
return new Pos2(cur2.line + motionArgs.repeat - 1, Infinity);
},
findNext: function(cm, _head, motionArgs) {
var state = getSearchState(cm);
var query = state.getQuery();
if (!query) {
return;
}
var prev = !motionArgs.forward;
prev = state.isReversed() ? !prev : prev;
highlightSearchMatches(cm, query);
var result = findNext(cm, prev, query, motionArgs.repeat);
if (!result) {
showConfirm(cm, "No match found " + query + (getOption("pcre") ? " (set nopcre to use Vim regexps)" : ""));
}
return result;
},
/**
* Find and select the next occurrence of the search query. If the cursor is currently
* within a match, then find and select the current match. Otherwise, find the next occurrence in the
* appropriate direction.
*
* This differs from `findNext` in the following ways:
*
* 1. Instead of only returning the "from", this returns a "from", "to" range.
* 2. If the cursor is currently inside a search match, this selects the current match
* instead of the next match.
* 3. If there is no associated operator, this will turn on visual mode.
*/
findAndSelectNextInclusive: function(cm, _head, motionArgs, vim2, prevInputState) {
var state = getSearchState(cm);
var query = state.getQuery();
if (!query) {
return;
}
var prev = !motionArgs.forward;
prev = state.isReversed() ? !prev : prev;
var next = findNextFromAndToInclusive(cm, prev, query, motionArgs.repeat, vim2);
if (!next) {
return;
}
if (prevInputState.operator) {
return next;
}
var from = next[0];
var to = new Pos2(next[1].line, next[1].ch - 1);
if (vim2.visualMode) {
if (vim2.visualLine || vim2.visualBlock) {
vim2.visualLine = false;
vim2.visualBlock = false;
CM.signal(cm, "vim-mode-change", { mode: "visual", subMode: "" });
}
var anchor = vim2.sel.anchor;
if (anchor) {
if (state.isReversed()) {
if (motionArgs.forward) {
return [anchor, from];
}
return [anchor, to];
} else {
if (motionArgs.forward) {
return [anchor, to];
}
return [anchor, from];
}
}
} else {
vim2.visualMode = true;
vim2.visualLine = false;
vim2.visualBlock = false;
CM.signal(cm, "vim-mode-change", { mode: "visual", subMode: "" });
}
return prev ? [to, from] : [from, to];
},
goToMark: function(cm, _head, motionArgs, vim2) {
var pos = getMarkPos(cm, vim2, motionArgs.selectedCharacter || "");
if (pos) {
return motionArgs.linewise ? { line: pos.line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) } : pos;
}
return null;
},
moveToOtherHighlightedEnd: function(cm, _head, motionArgs, vim2) {
var sel = vim2.sel;
if (vim2.visualBlock && motionArgs.sameLine) {
return [
clipCursorToContent(cm, new Pos2(sel.anchor.line, sel.head.ch)),
clipCursorToContent(cm, new Pos2(sel.head.line, sel.anchor.ch))
];
} else {
return [sel.head, sel.anchor];
}
},
jumpToMark: function(cm, head, motionArgs, vim2) {
var best = head;
for (var i = 0; i < motionArgs.repeat; i++) {
var cursor = best;
for (var key in vim2.marks) {
if (!isLowerCase(key)) {
continue;
}
var mark = vim2.marks[key].find();
var isWrongDirection = motionArgs.forward ? (
// @ts-ignore
cursorIsBefore(mark, cursor)
) : cursorIsBefore(cursor, mark);
if (isWrongDirection) {
continue;
}
if (motionArgs.linewise && mark.line == cursor.line) {
continue;
}
var equal = cursorEqual(cursor, best);
var between = motionArgs.forward ? (
// @ts-ignore
cursorIsBetween(cursor, mark, best)
) : (
// @ts-ignore
cursorIsBetween(best, mark, cursor)
);
if (equal || between) {
best = mark;
}
}
}
if (motionArgs.linewise) {
best = new Pos2(best.line, findFirstNonWhiteSpaceCharacter(cm.getLine(best.line)));
}
return best;
},
moveByCharacters: function(_cm, head, motionArgs) {
var cur2 = head;
var repeat = motionArgs.repeat;
var ch = motionArgs.forward ? cur2.ch + repeat : cur2.ch - repeat;
return new Pos2(cur2.line, ch);
},
moveByLines: function(cm, head, motionArgs, vim2) {
var cur2 = head;
var endCh = cur2.ch;
switch (vim2.lastMotion) {
case this.moveByLines:
case this.moveByDisplayLines:
case this.moveByScroll:
case this.moveToColumn:
case this.moveToEol:
endCh = vim2.lastHPos;
break;
default:
vim2.lastHPos = endCh;
}
var repeat = motionArgs.repeat + (motionArgs.repeatOffset || 0);
var line = motionArgs.forward ? cur2.line + repeat : cur2.line - repeat;
var first = cm.firstLine();
var last = cm.lastLine();
var posV = cm.findPosV(cur2, motionArgs.forward ? repeat : -repeat, "line", vim2.lastHSPos);
var hasMarkedText = motionArgs.forward ? posV.line > line : posV.line < line;
if (hasMarkedText) {
line = posV.line;
endCh = posV.ch;
}
if (line < first && cur2.line == first) {
return this.moveToStartOfLine(cm, head, motionArgs, vim2);
} else if (line > last && cur2.line == last) {
return moveToEol(cm, head, motionArgs, vim2, true);
}
if (motionArgs.toFirstChar) {
endCh = findFirstNonWhiteSpaceCharacter(cm.getLine(line));
vim2.lastHPos = endCh;
}
vim2.lastHSPos = cm.charCoords(new Pos2(line, endCh), "div").left;
return new Pos2(line, endCh);
},
moveByDisplayLines: function(cm, head, motionArgs, vim2) {
var cur2 = head;
switch (vim2.lastMotion) {
case this.moveByDisplayLines:
case this.moveByScroll:
case this.moveByLines:
case this.moveToColumn:
case this.moveToEol:
break;
default:
vim2.lastHSPos = cm.charCoords(cur2, "div").left;
}
var repeat = motionArgs.repeat;
var res = cm.findPosV(cur2, motionArgs.forward ? repeat : -repeat, "line", vim2.lastHSPos);
if (res.hitSide) {
if (motionArgs.forward) {
var lastCharCoords = cm.charCoords(res, "div");
var goalCoords = { top: lastCharCoords.top + 8, left: vim2.lastHSPos };
res = cm.coordsChar(goalCoords, "div");
} else {
var resCoords = cm.charCoords(new Pos2(cm.firstLine(), 0), "div");
resCoords.left = vim2.lastHSPos;
res = cm.coordsChar(resCoords, "div");
}
}
vim2.lastHPos = res.ch;
return res;
},
moveByPage: function(cm, head, motionArgs) {
var curStart = head;
var repeat = motionArgs.repeat;
return cm.findPosV(curStart, motionArgs.forward ? repeat : -repeat, "page");
},
moveByParagraph: function(cm, head, motionArgs) {
var dir = motionArgs.forward ? 1 : -1;
return findParagraph(cm, head, motionArgs.repeat, dir).start;
},
moveBySentence: function(cm, head, motionArgs) {
var dir = motionArgs.forward ? 1 : -1;
return findSentence(cm, head, motionArgs.repeat, dir);
},
moveByScroll: function(cm, head, motionArgs, vim2) {
var scrollbox = cm.getScrollInfo();
var curEnd = null;
var repeat = motionArgs.repeat;
if (!repeat) {
repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight());
}
var orig = cm.charCoords(head, "local");
motionArgs.repeat = repeat;
curEnd = motions.moveByDisplayLines(cm, head, motionArgs, vim2);
if (!curEnd) {
return null;
}
var dest = cm.charCoords(curEnd, "local");
cm.scrollTo(null, scrollbox.top + dest.top - orig.top);
return curEnd;
},
moveByWords: function(cm, head, motionArgs) {
return moveToWord(
cm,
head,
motionArgs.repeat,
!!motionArgs.forward,
!!motionArgs.wordEnd,
!!motionArgs.bigWord
);
},
moveTillCharacter: function(cm, head, motionArgs) {
var repeat = motionArgs.repeat;
var curEnd = moveToCharacter(
cm,
repeat,
motionArgs.forward,
motionArgs.selectedCharacter,
head
);
var increment = motionArgs.forward ? -1 : 1;
recordLastCharacterSearch(increment, motionArgs);
if (!curEnd) return null;
curEnd.ch += increment;
return curEnd;
},
moveToCharacter: function(cm, head, motionArgs) {
var repeat = motionArgs.repeat;
recordLastCharacterSearch(0, motionArgs);
return moveToCharacter(
cm,
repeat,
motionArgs.forward,
motionArgs.selectedCharacter,
head
) || head;
},
moveToSymbol: function(cm, head, motionArgs) {
var repeat = motionArgs.repeat;
return motionArgs.selectedCharacter && findSymbol(
cm,
repeat,
motionArgs.forward,
motionArgs.selectedCharacter
) || head;
},
moveToColumn: function(cm, head, motionArgs, vim2) {
var repeat = motionArgs.repeat;
vim2.lastHPos = repeat - 1;
vim2.lastHSPos = cm.charCoords(head, "div").left;
return moveToColumn(cm, repeat);
},
moveToEol: function(cm, head, motionArgs, vim2) {
return moveToEol(cm, head, motionArgs, vim2, false);
},
moveToFirstNonWhiteSpaceCharacter: function(cm, head) {
var cursor = head;
return new Pos2(
cursor.line,
findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line))
);
},
moveToMatchedSymbol: function(cm, head) {
var cursor = head;
var line = cursor.line;
var ch = cursor.ch;
var lineText = cm.getLine(line);
var symbol;
for (; ch < lineText.length; ch++) {
symbol = lineText.charAt(ch);
if (symbol && isMatchableSymbol(symbol)) {
var style = cm.getTokenTypeAt(new Pos2(line, ch + 1));
if (style !== "string" && style !== "comment") {
break;
}
}
}
if (ch < lineText.length) {
var re = symbol === "<" || symbol === ">" ? /[(){}[\]<>]/ : /[(){}[\]]/;
var matched = cm.findMatchingBracket(new Pos2(line, ch), { bracketRegex: re });
return matched.to;
} else {
return cursor;
}
},
moveToStartOfLine: function(_cm, head) {
return new Pos2(head.line, 0);
},
moveToLineOrEdgeOfDocument: function(cm, _head, motionArgs) {
var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine();
if (motionArgs.repeatIsExplicit) {
lineNum = motionArgs.repeat - cm.getOption("firstLineNumber");
}
return new Pos2(
lineNum,
findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum))
);
},
moveToStartOfDisplayLine: function(cm) {
cm.execCommand("goLineLeft");
return cm.getCursor();
},
moveToEndOfDisplayLine: function(cm) {
cm.execCommand("goLineRight");
var head = cm.getCursor();
if (head.sticky == "before") head.ch--;
return head;
},
textObjectManipulation: function(cm, head, motionArgs, vim2) {
var mirroredPairs = {
"(": ")",
")": "(",
"{": "}",
"}": "{",
"[": "]",
"]": "[",
"<": ">",
">": "<"
};
var selfPaired = { "'": true, '"': true, "`": true };
var character = motionArgs.selectedCharacter || "";
if (character == "b") {
character = "(";
} else if (character == "B") {
character = "{";
}
var inclusive = !motionArgs.textObjectInner;
var tmp, move;
if (mirroredPairs[character]) {
move = true;
tmp = selectCompanionObject(cm, head, character, inclusive);
if (!tmp) {
var sc = cm.getSearchCursor(new RegExp("\\" + character, "g"), head);
if (sc.find()) {
tmp = selectCompanionObject(cm, sc.from(), character, inclusive);
}
}
} else if (selfPaired[character]) {
move = true;
tmp = findBeginningAndEnd(cm, head, character, inclusive);
} else if (character === "W" || character === "w") {
var repeat = motionArgs.repeat || 1;
while (repeat-- > 0) {
var repeated = expandWordUnderCursor(cm, {
inclusive,
innerWord: !inclusive,
bigWord: character === "W",
noSymbol: character === "W",
multiline: true
}, tmp && tmp.end);
if (repeated) {
if (!tmp) tmp = repeated;
tmp.end = repeated.end;
}
}
} else if (character === "p") {
tmp = findParagraph(cm, head, motionArgs.repeat, 0, inclusive);
motionArgs.linewise = true;
if (vim2.visualMode) {
if (!vim2.visualLine) {
vim2.visualLine = true;
}
} else {
var operatorArgs = vim2.inputState.operatorArgs;
if (operatorArgs) {
operatorArgs.linewise = true;
}
tmp.end.line--;
}
} else if (character === "t") {
tmp = expandTagUnderCursor(cm, head, inclusive);
} else if (character === "s") {
var content = cm.getLine(head.line);
if (head.ch > 0 && isEndOfSentenceSymbol(content[head.ch])) {
head.ch -= 1;
}
var end = getSentence(cm, head, motionArgs.repeat, 1, inclusive);
var start = getSentence(cm, head, motionArgs.repeat, -1, inclusive);
if (isWhiteSpaceString(cm.getLine(start.line)[start.ch]) && isWhiteSpaceString(cm.getLine(end.line)[end.ch - 1])) {
start = { line: start.line, ch: start.ch + 1 };
}
tmp = { start, end };
}
if (!tmp) {
return null;
}
if (!cm.state.vim.visualMode) {
return [tmp.start, tmp.end];
} else {
return expandSelection(cm, tmp.start, tmp.end, move);
}
},
repeatLastCharacterSearch: function(cm, head, motionArgs) {
var lastSearch = vimGlobalState.lastCharacterSearch;
var repeat = motionArgs.repeat;
var forward = motionArgs.forward === lastSearch.forward;
var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1);
cm.moveH(-increment, "char");
motionArgs.inclusive = forward ? true : false;
var curEnd = moveToCharacter(cm, repeat, forward, lastSearch.selectedCharacter);
if (!curEnd) {
cm.moveH(increment, "char");
return head;
}
curEnd.ch += increment;
return curEnd;
}
};
function defineMotion(name, fn) {
motions[name] = fn;
}
function fillArray(val, times) {
var arr = [];
for (var i = 0; i < times; i++) {
arr.push(val);
}
return arr;
}
var operators = {
change: function(cm, args, ranges) {
var finalHead, text;
var vim2 = cm.state.vim;
var anchor = ranges[0].anchor, head = ranges[0].head;
if (!vim2.visualMode) {
text = cm.getRange(anchor, head);
var lastState = vim2.lastEditInputState;
if ((lastState == null ? void 0 : lastState.motion) == "moveByWords" && !isWhiteSpaceString(text)) {
var match = /\s+$/.exec(text);
if (match && lastState.motionArgs && lastState.motionArgs.forward) {
head = offsetCursor(head, 0, -match[0].length);
text = text.slice(0, -match[0].length);
}
}
if (args.linewise) {
anchor = new Pos2(anchor.line, findFirstNonWhiteSpaceCharacter(cm.getLine(anchor.line)));
if (head.line > anchor.line) {
head = new Pos2(head.line - 1, Number.MAX_VALUE);
}
}
cm.replaceRange("", anchor, head);
finalHead = anchor;
} else if (args.fullLine) {
head.ch = Number.MAX_VALUE;
head.line--;
cm.setSelection(anchor, head);
text = cm.getSelection();
cm.replaceSelection("");
finalHead = anchor;
} else {
text = cm.getSelection();
var replacement = fillArray("", ranges.length);
cm.replaceSelections(replacement);
finalHead = cursorMin(ranges[0].head, ranges[0].anchor);
}
vimGlobalState.registerController.pushText(
args.registerName,
"change",
text,
args.linewise,
ranges.length > 1
);
actions.enterInsertMode(cm, { head: finalHead }, cm.state.vim);
},
delete: function(cm, args, ranges) {
var finalHead, text;
var vim2 = cm.state.vim;
if (!vim2.visualBlock) {
var anchor = ranges[0].anchor, head = ranges[0].head;
if (args.linewise && head.line != cm.firstLine() && anchor.line == cm.lastLine() && anchor.line == head.line - 1) {
if (anchor.line == cm.firstLine()) {
anchor.ch = 0;
} else {
anchor = new Pos2(anchor.line - 1, lineLength(cm, anchor.line - 1));
}
}
text = cm.getRange(anchor, head);
cm.replaceRange("", anchor, head);
finalHead = anchor;
if (args.linewise) {
finalHead = motions.moveToFirstNonWhiteSpaceCharacter(cm, anchor);
}
} else {
text = cm.getSelection();
var replacement = fillArray("", ranges.length);
cm.replaceSelections(replacement);
finalHead = cursorMin(ranges[0].head, ranges[0].anchor);
}
vimGlobalState.registerController.pushText(
args.registerName,
"delete",
text,
args.linewise,
vim2.visualBlock
);
return clipCursorToContent(cm, finalHead);
},
indent: function(cm, args, ranges) {
var vim2 = cm.state.vim;
var repeat = vim2.visualMode ? args.repeat || 1 : 1;
if (vim2.visualBlock) {
var tabSize = cm.getOption("tabSize");
var indent = cm.getOption("indentWithTabs") ? " " : " ".repeat(tabSize);
var cursor;
for (var i = ranges.length - 1; i >= 0; i--) {
cursor = cursorMin(ranges[i].anchor, ranges[i].head);
if (args.indentRight) {
cm.replaceRange(indent.repeat(repeat), cursor, cursor);
} else {
var text = cm.getLine(cursor.line);
var end = 0;
for (var j = 0; j < repeat; j++) {
var ch = text[cursor.ch + end];
if (ch == " ") {
end++;
} else if (ch == " ") {
end++;
for (var k = 1; k < indent.length; k++) {
ch = text[cursor.ch + end];
if (ch !== " ") break;
end++;
}
} else {
break;
}
}
cm.replaceRange("", cursor, offsetCursor(cursor, 0, end));
}
}
return cursor;
} else if (cm.indentMore) {
for (var j = 0; j < repeat; j++) {
if (args.indentRight) cm.indentMore();
else cm.indentLess();
}
} else {
var startLine = ranges[0].anchor.line;
var endLine = vim2.visualBlock ? ranges[ranges.length - 1].anchor.line : ranges[0].head.line;
if (args.linewise) {
endLine--;
}
for (var i = startLine; i <= endLine; i++) {
for (var j = 0; j < repeat; j++) {
cm.indentLine(i, args.indentRight);
}
}
}
return motions.moveToFirstNonWhiteSpaceCharacter(cm, ranges[0].anchor);
},
indentAuto: function(cm, _args, ranges) {
cm.execCommand("indentAuto");
return motions.moveToFirstNonWhiteSpaceCharacter(cm, ranges[0].anchor);
},
hardWrap: function(cm, operatorArgs, ranges, oldAnchor) {
if (!cm.hardWrap) return;
var from = ranges[0].anchor.line;
var to = ranges[0].head.line;
if (operatorArgs.linewise) to--;
var endRow = cm.hardWrap({ from, to });
if (endRow > from && operatorArgs.linewise) endRow--;
return operatorArgs.keepCursor ? oldAnchor : new Pos2(endRow, 0);
},
changeCase: function(cm, args, ranges, oldAnchor, newHead) {
var selections = cm.getSelections();
var swapped = [];
var toLower = args.toLower;
for (var j = 0; j < selections.length; j++) {
var toSwap = selections[j];
var text = "";
if (toLower === true) {
text = toSwap.toLowerCase();
} else if (toLower === false) {
text = toSwap.toUpperCase();
} else {
for (var i = 0; i < toSwap.length; i++) {
var character = toSwap.charAt(i);
text += isUpperCase(character) ? character.toLowerCase() : character.toUpperCase();
}
}
swapped.push(text);
}
cm.replaceSelections(swapped);
if (args.shouldMoveCursor) {
return newHead;
} else if (!cm.state.vim.visualMode && args.linewise && ranges[0].anchor.line + 1 == ranges[0].head.line) {
return motions.moveToFirstNonWhiteSpaceCharacter(cm, oldAnchor);
} else if (args.linewise) {
return oldAnchor;
} else {
return cursorMin(ranges[0].anchor, ranges[0].head);
}
},
yank: function(cm, args, ranges, oldAnchor) {
var vim2 = cm.state.vim;
var text = cm.getSelection();
var endPos = vim2.visualMode ? cursorMin(vim2.sel.anchor, vim2.sel.head, ranges[0].head, ranges[0].anchor) : oldAnchor;
vimGlobalState.registerController.pushText(
args.registerName,
"yank",
text,
args.linewise,
vim2.visualBlock
);
return endPos;
},
rot13: function(cm, args, ranges, oldAnchor, newHead) {
var selections = cm.getSelections();
var swapped = [];
for (var j = 0; j < selections.length; j++) {
const replacement = selections[j].split("").map((x) => {
const code = x.charCodeAt(0);
if (code >= 65 && code <= 90) {
return String.fromCharCode(65 + (code - 65 + 13) % 26);
} else if (code >= 97 && code <= 122) {
return String.fromCharCode(97 + (code - 97 + 13) % 26);
} else {
return x;
}
}).join("");
swapped.push(replacement);
}
cm.replaceSelections(swapped);
if (args.shouldMoveCursor) {
return newHead;
} else if (!cm.state.vim.visualMode && args.linewise && ranges[0].anchor.line + 1 == ranges[0].head.line) {
return motions.moveToFirstNonWhiteSpaceCharacter(cm, oldAnchor);
} else if (args.linewise) {
return oldAnchor;
} else {
return cursorMin(ranges[0].anchor, ranges[0].head);
}
}
};
function defineOperator(name, fn) {
operators[name] = fn;
}
var actions = {
jumpListWalk: function(cm, actionArgs, vim2) {
if (vim2.visualMode) {
return;
}
var repeat = actionArgs.repeat || 1;
var forward = actionArgs.forward;
var jumpList = vimGlobalState.jumpList;
var mark = jumpList.move(cm, forward ? repeat : -repeat);
var markPos = mark ? mark.find() : void 0;
markPos = markPos ? markPos : cm.getCursor();
cm.setCursor(markPos);
},
scroll: function(cm, actionArgs, vim2) {
if (vim2.visualMode) {
return;
}
var repeat = actionArgs.repeat || 1;
var lineHeight = cm.defaultTextHeight();
var top = cm.getScrollInfo().top;
var delta = lineHeight * repeat;
var newPos = actionArgs.forward ? top + delta : top - delta;
var cursor = copyCursor(cm.getCursor());
var cursorCoords = cm.charCoords(cursor, "local");
if (actionArgs.forward) {
if (newPos > cursorCoords.top) {
cursor.line += (newPos - cursorCoords.top) / lineHeight;
cursor.line = Math.ceil(cursor.line);
cm.setCursor(cursor);
cursorCoords = cm.charCoords(cursor, "local");
cm.scrollTo(null, cursorCoords.top);
} else {
cm.scrollTo(null, newPos);
}
} else {
var newBottom = newPos + cm.getScrollInfo().clientHeight;
if (newBottom < cursorCoords.bottom) {
cursor.line -= (cursorCoords.bottom - newBottom) / lineHeight;
cursor.line = Math.floor(cursor.line);
cm.setCursor(cursor);
cursorCoords = cm.charCoords(cursor, "local");
cm.scrollTo(
null,
cursorCoords.bottom - cm.getScrollInfo().clientHeight
);
} else {
cm.scrollTo(null, newPos);
}
}
},
scrollToCursor: function(cm, actionArgs) {
var lineNum = cm.getCursor().line;
var charCoords = cm.charCoords(new Pos2(lineNum, 0), "local");
var height = cm.getScrollInfo().clientHeight;
var y = charCoords.top;
switch (actionArgs.position) {
case "center":
y = charCoords.bottom - height / 2;
break;
case "bottom":
var lineLastCharPos = new Pos2(lineNum, cm.getLine(lineNum).length - 1);
var lineLastCharCoords = cm.charCoords(lineLastCharPos, "local");
var lineHeight = lineLastCharCoords.bottom - y;
y = y - height + lineHeight;
break;
}
cm.scrollTo(null, y);
},
replayMacro: function(cm, actionArgs, vim2) {
var registerName = actionArgs.selectedCharacter || "";
var repeat = actionArgs.repeat || 1;
var macroModeState = vimGlobalState.macroModeState;
if (registerName == "@") {
registerName = macroModeState.latestRegister || "";
} else {
macroModeState.latestRegister = registerName;
}
while (repeat--) {
executeMacroRegister(cm, vim2, macroModeState, registerName);
}
},
enterMacroRecordMode: function(cm, actionArgs) {
var macroModeState = vimGlobalState.macroModeState;
var registerName = actionArgs.selectedCharacter;
if (vimGlobalState.registerController.isValidRegister(registerName)) {
macroModeState.enterMacroRecordMode(cm, registerName);
}
},
toggleOverwrite: function(cm) {
if (!cm.state.overwrite) {
cm.toggleOverwrite(true);
cm.setOption("keyMap", "vim-replace");
CM.signal(cm, "vim-mode-change", { mode: "replace" });
} else {
cm.toggleOverwrite(false);
cm.setOption("keyMap", "vim-insert");
CM.signal(cm, "vim-mode-change", { mode: "insert" });
}
},
enterInsertMode: function(cm, actionArgs, vim2) {
if (cm.getOption("readOnly")) {
return;
}
vim2.insertMode = true;
vim2.insertModeRepeat = actionArgs && actionArgs.repeat || 1;
var insertAt = actionArgs ? actionArgs.insertAt : null;
var sel = vim2.sel;
var head = actionArgs.head || cm.getCursor("head");
var height = cm.listSelections().length;
if (insertAt == "eol") {
head = new Pos2(head.line, lineLength(cm, head.line));
} else if (insertAt == "bol") {
head = new Pos2(head.line, 0);
} else if (insertAt == "charAfter") {
var newPosition = updateSelectionForSurrogateCharacters(cm, head, offsetCursor(head, 0, 1));
head = newPosition.end;
} else if (insertAt == "firstNonBlank") {
var newPosition = updateSelectionForSurrogateCharacters(cm, head, motions.moveToFirstNonWhiteSpaceCharacter(cm, head));
head = newPosition.end;
} else if (insertAt == "startOfSelectedArea") {
if (!vim2.visualMode)
return;
if (!vim2.visualBlock) {
if (sel.head.line < sel.anchor.line) {
head = sel.head;
} else {
head = new Pos2(sel.anchor.line, 0);
}
} else {
head = new Pos2(
Math.min(sel.head.line, sel.anchor.line),
Math.min(sel.head.ch, sel.anchor.ch)
);
height = Math.abs(sel.head.line - sel.anchor.line) + 1;
}
} else if (insertAt == "endOfSelectedArea") {
if (!vim2.visualMode)
return;
if (!vim2.visualBlock) {
if (sel.head.line >= sel.anchor.line) {
head = offsetCursor(sel.head, 0, 1);
} else {
head = new Pos2(sel.anchor.line, 0);
}
} else {
head = new Pos2(
Math.min(sel.head.line, sel.anchor.line),
Math.max(sel.head.ch, sel.anchor.ch) + 1
);
height = Math.abs(sel.head.line - sel.anchor.line) + 1;
}
} else if (insertAt == "inplace") {
if (vim2.visualMode) {
return;
}
} else if (insertAt == "lastEdit") {
head = getLastEditPos(cm) || head;
}
cm.setOption("disableInput", false);
if (actionArgs && actionArgs.replace) {
cm.toggleOverwrite(true);
cm.setOption("keyMap", "vim-replace");
CM.signal(cm, "vim-mode-change", { mode: "replace" });
} else {
cm.toggleOverwrite(false);
cm.setOption("keyMap", "vim-insert");
CM.signal(cm, "vim-mode-change", { mode: "insert" });
}
if (!vimGlobalState.macroModeState.isPlaying) {
cm.on("change", onChange);
if (vim2.insertEnd) vim2.insertEnd.clear();
vim2.insertEnd = cm.setBookmark(head, { insertLeft: true });
CM.on(cm.getInputField(), "keydown", onKeyEventTargetKeyDown);
}
if (vim2.visualMode) {
exitVisualMode(cm);
}
selectForInsert(cm, head, height);
},
toggleVisualMode: function(cm, actionArgs, vim2) {
var repeat = actionArgs.repeat;
var anchor = cm.getCursor();
var head;
if (!vim2.visualMode) {
vim2.visualMode = true;
vim2.visualLine = !!actionArgs.linewise;
vim2.visualBlock = !!actionArgs.blockwise;
head = clipCursorToContent(
cm,
new Pos2(anchor.line, anchor.ch + repeat - 1)
);
var newPosition = updateSelectionForSurrogateCharacters(cm, anchor, head);
vim2.sel = {
anchor: newPosition.start,
head: newPosition.end
};
CM.signal(cm, "vim-mode-change", { mode: "visual", subMode: vim2.visualLine ? "linewise" : vim2.visualBlock ? "blockwise" : "" });
updateCmSelection(cm);
updateMark(cm, vim2, "<", cursorMin(anchor, head));
updateMark(cm, vim2, ">", cursorMax(anchor, head));
} else if (vim2.visualLine != !!actionArgs.linewise || vim2.visualBlock != !!actionArgs.blockwise) {
vim2.visualLine = !!actionArgs.linewise;
vim2.visualBlock = !!actionArgs.blockwise;
CM.signal(cm, "vim-mode-change", { mode: "visual", subMode: vim2.visualLine ? "linewise" : vim2.visualBlock ? "blockwise" : "" });
updateCmSelection(cm);
} else {
exitVisualMode(cm);
}
},
reselectLastSelection: function(cm, _actionArgs, vim2) {
var lastSelection = vim2.lastSelection;
if (vim2.visualMode) {
updateLastSelection(cm, vim2);
}
if (lastSelection) {
var anchor = lastSelection.anchorMark.find();
var head = lastSelection.headMark.find();
if (!anchor || !head) {
return;
}
vim2.sel = {
anchor,
head
};
vim2.visualMode = true;
vim2.visualLine = lastSelection.visualLine;
vim2.visualBlock = lastSelection.visualBlock;
updateCmSelection(cm);
updateMark(cm, vim2, "<", cursorMin(anchor, head));
updateMark(cm, vim2, ">", cursorMax(anchor, head));
CM.signal(cm, "vim-mode-change", {
mode: "visual",
subMode: vim2.visualLine ? "linewise" : vim2.visualBlock ? "blockwise" : ""
});
}
},
joinLines: function(cm, actionArgs, vim2) {
var curStart, curEnd;
if (vim2.visualMode) {
curStart = cm.getCursor("anchor");
curEnd = cm.getCursor("head");
if (cursorIsBefore(curEnd, curStart)) {
var tmp = curEnd;
curEnd = curStart;
curStart = tmp;
}
curEnd.ch = lineLength(cm, curEnd.line) - 1;
} else {
var repeat = Math.max(actionArgs.repeat, 2);
curStart = cm.getCursor();
curEnd = clipCursorToContent(cm, new Pos2(
curStart.line + repeat - 1,
Infinity
));
}
var finalCh = 0;
for (var i = curStart.line; i < curEnd.line; i++) {
finalCh = lineLength(cm, curStart.line);
var text = "";
var nextStartCh = 0;
if (!actionArgs.keepSpaces) {
var nextLine = cm.getLine(curStart.line + 1);
nextStartCh = nextLine.search(/\S/);
if (nextStartCh == -1) {
nextStartCh = nextLine.length;
} else {
text = " ";
}
}
cm.replaceRange(
text,
new Pos2(curStart.line, finalCh),
new Pos2(curStart.line + 1, nextStartCh)
);
}
var curFinalPos = clipCursorToContent(cm, new Pos2(curStart.line, finalCh));
if (vim2.visualMode) {
exitVisualMode(cm, false);
}
cm.setCursor(curFinalPos);
},
newLineAndEnterInsertMode: function(cm, actionArgs, vim2) {
vim2.insertMode = true;
var insertAt = copyCursor(cm.getCursor());
if (insertAt.line === cm.firstLine() && !actionArgs.after) {
cm.replaceRange("\n", new Pos2(cm.firstLine(), 0));
cm.setCursor(cm.firstLine(), 0);
} else {
insertAt.line = actionArgs.after ? insertAt.line : insertAt.line - 1;
insertAt.ch = lineLength(cm, insertAt.line);
cm.setCursor(insertAt);
var newlineFn = CM.commands.newlineAndIndentContinueComment || CM.commands.newlineAndIndent;
newlineFn(cm);
}
this.enterInsertMode(cm, { repeat: actionArgs.repeat }, vim2);
},
paste: function(cm, actionArgs, vim2) {
var register = vimGlobalState.registerController.getRegister(
actionArgs.registerName
);
if (actionArgs.registerName === "+") {
navigator.clipboard.readText().then((value) => {
this.continuePaste(cm, actionArgs, vim2, value, register);
});
} else {
var text = register.toString();
this.continuePaste(cm, actionArgs, vim2, text, register);
}
},
continuePaste: function(cm, actionArgs, vim2, text, register) {
var cur2 = copyCursor(cm.getCursor());
if (!text) {
return;
}
if (actionArgs.matchIndent) {
var tabSize = cm.getOption("tabSize");
var whitespaceLength = function(str) {
var tabs = str.split(" ").length - 1;
var spaces = str.split(" ").length - 1;
return tabs * tabSize + spaces * 1;
};
var currentLine = cm.getLine(cm.getCursor().line);
var indent = whitespaceLength(currentLine.match(/^\s*/)[0]);
var chompedText = text.replace(/\n$/, "");
var wasChomped = text !== chompedText;
var firstIndent = whitespaceLength(text.match(/^\s*/)[0]);
var text = chompedText.replace(/^\s*/gm, function(wspace) {
var newIndent = indent + (whitespaceLength(wspace) - firstIndent);
if (newIndent < 0) {
return "";
} else if (cm.getOption("indentWithTabs")) {
var quotient = Math.floor(newIndent / tabSize);
return Array(quotient + 1).join(" ");
} else {
return Array(newIndent + 1).join(" ");
}
});
text += wasChomped ? "\n" : "";
}
if (actionArgs.repeat > 1) {
text = Array(actionArgs.repeat + 1).join(text);
}
var linewise = register.linewise;
var blockwise = register.blockwise;
var textLines = blockwise ? text.split("\n") : void 0;
if (textLines) {
if (linewise) {
textLines.pop();
}
for (var i = 0; i < textLines.length; i++) {
textLines[i] = textLines[i] == "" ? " " : textLines[i];
}
cur2.ch += actionArgs.after ? 1 : 0;
cur2.ch = Math.min(lineLength(cm, cur2.line), cur2.ch);
} else if (linewise) {
if (vim2.visualMode) {
text = vim2.visualLine ? text.slice(0, -1) : "\n" + text.slice(0, text.length - 1) + "\n";
} else if (actionArgs.after) {
text = "\n" + text.slice(0, text.length - 1);
cur2.ch = lineLength(cm, cur2.line);
} else {
cur2.ch = 0;
}
} else {
cur2.ch += actionArgs.after ? 1 : 0;
}
var curPosFinal;
if (vim2.visualMode) {
vim2.lastPastedText = text;
var lastSelectionCurEnd;
var selectedArea = getSelectedAreaRange(cm);
var selectionStart = selectedArea[0];
var selectionEnd = selectedArea[1];
var selectedText = cm.getSelection();
var selections = cm.listSelections();
var emptyStrings = new Array(selections.length).join("1").split("1");
if (vim2.lastSelection) {
lastSelectionCurEnd = vim2.lastSelection.headMark.find();
}
vimGlobalState.registerController.unnamedRegister.setText(selectedText);
if (blockwise) {
cm.replaceSelections(emptyStrings);
selectionEnd = new Pos2(selectionStart.line + text.length - 1, selectionStart.ch);
cm.setCursor(selectionStart);
selectBlock(cm, selectionEnd);
cm.replaceSelections(text);
curPosFinal = selectionStart;
} else if (vim2.visualBlock) {
cm.replaceSelections(emptyStrings);
cm.setCursor(selectionStart);
cm.replaceRange(text, selectionStart, selectionStart);
curPosFinal = selectionStart;
} else {
cm.replaceRange(text, selectionStart, selectionEnd);
curPosFinal = cm.posFromIndex(cm.indexFromPos(selectionStart) + text.length - 1);
}
if (lastSelectionCurEnd) {
vim2.lastSelection.headMark = cm.setBookmark(lastSelectionCurEnd);
}
if (linewise) {
curPosFinal.ch = 0;
}
} else {
if (blockwise && textLines) {
cm.setCursor(cur2);
for (var i = 0; i < textLines.length; i++) {
var line = cur2.line + i;
if (line > cm.lastLine()) {
cm.replaceRange("\n", new Pos2(line, 0));
}
var lastCh = lineLength(cm, line);
if (lastCh < cur2.ch) {
extendLineToColumn(cm, line, cur2.ch);
}
}
cm.setCursor(cur2);
selectBlock(cm, new Pos2(cur2.line + textLines.length - 1, cur2.ch));
cm.replaceSelections(textLines);
curPosFinal = cur2;
} else {
cm.replaceRange(text, cur2);
if (linewise) {
var line = actionArgs.after ? cur2.line + 1 : cur2.line;
curPosFinal = new Pos2(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)));
} else {
curPosFinal = copyCursor(cur2);
if (!/\n/.test(text)) {
curPosFinal.ch += text.length - (actionArgs.after ? 1 : 0);
}
}
}
}
if (vim2.visualMode) {
exitVisualMode(cm, false);
}
cm.setCursor(curPosFinal);
},
undo: function(cm, actionArgs) {
cm.operation(function() {
repeatFn(cm, CM.commands.undo, actionArgs.repeat)();
cm.setCursor(clipCursorToContent(cm, cm.getCursor("start")));
});
},
redo: function(cm, actionArgs) {
repeatFn(cm, CM.commands.redo, actionArgs.repeat)();
},
setRegister: function(_cm, actionArgs, vim2) {
vim2.inputState.registerName = actionArgs.selectedCharacter;
},
insertRegister: function(cm, actionArgs, vim2) {
var registerName = actionArgs.selectedCharacter;
var register = vimGlobalState.registerController.getRegister(registerName);
var text = register && register.toString();
if (text) {
cm.replaceSelection(text);
}
},
oneNormalCommand: function(cm, actionArgs, vim2) {
exitInsertMode(cm, true);
vim2.insertModeReturn = true;
CM.on(cm, "vim-command-done", function handler() {
if (vim2.visualMode) return;
if (vim2.insertModeReturn) {
vim2.insertModeReturn = false;
if (!vim2.insertMode) {
actions.enterInsertMode(cm, {}, vim2);
}
}
CM.off(cm, "vim-command-done", handler);
});
},
setMark: function(cm, actionArgs, vim2) {
var markName = actionArgs.selectedCharacter;
if (markName) updateMark(cm, vim2, markName, cm.getCursor());
},
replace: function(cm, actionArgs, vim2) {
var replaceWith = actionArgs.selectedCharacter || "";
var curStart = cm.getCursor();
var replaceTo;
var curEnd;
var selections = cm.listSelections();
if (vim2.visualMode) {
curStart = cm.getCursor("start");
curEnd = cm.getCursor("end");
} else {
var line = cm.getLine(curStart.line);
replaceTo = curStart.ch + actionArgs.repeat;
if (replaceTo > line.length) {
replaceTo = line.length;
}
curEnd = new Pos2(curStart.line, replaceTo);
}
var newPositions = updateSelectionForSurrogateCharacters(cm, curStart, curEnd);
curStart = newPositions.start;
curEnd = newPositions.end;
if (replaceWith == "\n") {
if (!vim2.visualMode) cm.replaceRange("", curStart, curEnd);
(CM.commands.newlineAndIndentContinueComment || CM.commands.newlineAndIndent)(cm);
} else {
var replaceWithStr = cm.getRange(curStart, curEnd);
replaceWithStr = replaceWithStr.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, replaceWith);
replaceWithStr = replaceWithStr.replace(/[^\n]/g, replaceWith);
if (vim2.visualBlock) {
var spaces = new Array(cm.getOption("tabSize") + 1).join(" ");
replaceWithStr = cm.getSelection();
replaceWithStr = replaceWithStr.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, replaceWith);
var replaceWithStrings = replaceWithStr.replace(/\t/g, spaces).replace(/[^\n]/g, replaceWith).split("\n");
cm.replaceSelections(replaceWithStrings);
} else {
cm.replaceRange(replaceWithStr, curStart, curEnd);
}
if (vim2.visualMode) {
curStart = cursorIsBefore(selections[0].anchor, selections[0].head) ? selections[0].anchor : selections[0].head;
cm.setCursor(curStart);
exitVisualMode(cm, false);
} else {
cm.setCursor(offsetCursor(curEnd, 0, -1));
}
}
},
incrementNumberToken: function(cm, actionArgs) {
var cur2 = cm.getCursor();
var lineStr = cm.getLine(cur2.line);
var re = /(-?)(?:(0x)([\da-f]+)|(0b|0|)(\d+))/gi;
var match;
var start;
var end;
var numberStr;
while ((match = re.exec(lineStr)) !== null) {
start = match.index;
end = start + match[0].length;
if (cur2.ch < end) break;
}
if (!actionArgs.backtrack && end <= cur2.ch) return;
if (match) {
var baseStr = match[2] || match[4];
var digits = match[3] || match[5];
var increment = actionArgs.increase ? 1 : -1;
var base = { "0b": 2, "0": 8, "": 10, "0x": 16 }[baseStr.toLowerCase()];
var number = parseInt(match[1] + digits, base) + increment * actionArgs.repeat;
numberStr = number.toString(base);
var zeroPadding = baseStr ? new Array(digits.length - numberStr.length + 1 + match[1].length).join("0") : "";
if (numberStr.charAt(0) === "-") {
numberStr = "-" + baseStr + zeroPadding + numberStr.substr(1);
} else {
numberStr = baseStr + zeroPadding + numberStr;
}
var from = new Pos2(cur2.line, start);
var to = new Pos2(cur2.line, end);
cm.replaceRange(numberStr, from, to);
} else {
return;
}
cm.setCursor(new Pos2(cur2.line, start + numberStr.length - 1));
},
repeatLastEdit: function(cm, actionArgs, vim2) {
var lastEditInputState = vim2.lastEditInputState;
if (!lastEditInputState) {
return;
}
var repeat = actionArgs.repeat;
if (repeat && actionArgs.repeatIsExplicit) {
lastEditInputState.repeatOverride = repeat;
} else {
repeat = lastEditInputState.repeatOverride || repeat;
}
repeatLastEdit(
cm,
vim2,
repeat,
false
/** repeatForInsert */
);
},
indent: function(cm, actionArgs) {
cm.indentLine(cm.getCursor().line, actionArgs.indentRight);
},
exitInsertMode: function(cm, actionArgs) {
exitInsertMode(cm);
}
};
function defineAction(name, fn) {
actions[name] = fn;
}
function clipCursorToContent(cm, cur2, oldCur) {
var vim2 = cm.state.vim;
var includeLineBreak = vim2.insertMode || vim2.visualMode;
var line = Math.min(Math.max(cm.firstLine(), cur2.line), cm.lastLine());
var text = cm.getLine(line);
var maxCh = text.length - 1 + Number(!!includeLineBreak);
var ch = Math.min(Math.max(0, cur2.ch), maxCh);
var charCode = text.charCodeAt(ch);
if (56320 <= charCode && charCode <= 57343) {
var direction = 1;
if (oldCur && oldCur.line == line && oldCur.ch > ch) {
direction = -1;
}
ch += direction;
if (ch > maxCh) ch -= 2;
}
return new Pos2(line, ch);
}
function copyArgs(args) {
var ret = (
/**@type{typeof args}*/
{}
);
for (var prop in args) {
if (Object.prototype.hasOwnProperty.call(args, prop)) {
ret[prop] = args[prop];
}
}
return (
/**@type{typeof args}*/
ret
);
}
function offsetCursor(cur2, offsetLine, offsetCh) {
if (typeof offsetLine === "object") {
offsetCh = offsetLine.ch;
offsetLine = offsetLine.line;
}
return new Pos2(cur2.line + offsetLine, cur2.ch + offsetCh);
}
function commandMatches(keys2, keyMap, context, inputState) {
if (inputState.operator) context = "operatorPending";
var match, partial = [], full = [];
var startIndex = noremap ? keyMap.length - defaultKeymapLength : 0;
for (var i = startIndex; i < keyMap.length; i++) {
var command = keyMap[i];
if (context == "insert" && command.context != "insert" || command.context && command.context != context || inputState.operator && command.type == "action" || !(match = commandMatch(keys2, command.keys))) {
continue;
}
if (match == "partial") {
partial.push(command);
}
if (match == "full") {
full.push(command);
}
}
return {
partial,
full
};
}
function commandMatch(pressed, mapped) {
const isLastCharacter = mapped.slice(-11) == "<character>";
const isLastRegister = mapped.slice(-10) == "<register>";
if (isLastCharacter || isLastRegister) {
var prefixLen = mapped.length - (isLastCharacter ? 11 : 10);
var pressedPrefix = pressed.slice(0, prefixLen);
var mappedPrefix = mapped.slice(0, prefixLen);
return pressedPrefix == mappedPrefix && pressed.length > prefixLen ? "full" : mappedPrefix.indexOf(pressedPrefix) == 0 ? "partial" : false;
} else {
return pressed == mapped ? "full" : mapped.indexOf(pressed) == 0 ? "partial" : false;
}
}
function lastChar(keys2) {
var match = /^.*(<[^>]+>)$/.exec(keys2);
var selectedCharacter = match ? match[1] : keys2.slice(-1);
if (selectedCharacter.length > 1) {
switch (selectedCharacter) {
case "<CR>":
case "<S-CR>":
selectedCharacter = "\n";
break;
case "<Space>":
case "<S-Space>":
selectedCharacter = " ";
break;
default:
selectedCharacter = "";
break;
}
}
return selectedCharacter;
}
function repeatFn(cm, fn, repeat) {
return function() {
for (var i = 0; i < repeat; i++) {
fn(cm);
}
};
}
function copyCursor(cur2) {
return new Pos2(cur2.line, cur2.ch);
}
function cursorEqual(cur1, cur2) {
return cur1.ch == cur2.ch && cur1.line == cur2.line;
}
function cursorIsBefore(cur1, cur2) {
if (cur1.line < cur2.line) {
return true;
}
if (cur1.line == cur2.line && cur1.ch < cur2.ch) {
return true;
}
return false;
}
function cursorMin(cur1, cur2) {
if (arguments.length > 2) {
cur2 = cursorMin.apply(void 0, Array.prototype.slice.call(arguments, 1));
}
return cursorIsBefore(cur1, cur2) ? cur1 : cur2;
}
function cursorMax(cur1, cur2) {
if (arguments.length > 2) {
cur2 = cursorMax.apply(void 0, Array.prototype.slice.call(arguments, 1));
}
return cursorIsBefore(cur1, cur2) ? cur2 : cur1;
}
function cursorIsBetween(cur1, cur2, cur3) {
var cur1before2 = cursorIsBefore(cur1, cur2);
var cur2before3 = cursorIsBefore(cur2, cur3);
return cur1before2 && cur2before3;
}
function lineLength(cm, lineNum) {
return cm.getLine(lineNum).length;
}
function trim(s) {
if (s.trim) {
return s.trim();
}
return s.replace(/^\s+|\s+$/g, "");
}
function escapeRegex(s) {
return s.replace(/([.?*+$\[\]\/\\(){}|\-])/g, "\\$1");
}
function extendLineToColumn(cm, lineNum, column) {
var endCh = lineLength(cm, lineNum);
var spaces = new Array(column - endCh + 1).join(" ");
cm.setCursor(new Pos2(lineNum, endCh));
cm.replaceRange(spaces, cm.getCursor());
}
function selectBlock(cm, selectionEnd) {
var selections = [], ranges = cm.listSelections();
var head = copyCursor(cm.clipPos(selectionEnd));
var isClipped = !cursorEqual(selectionEnd, head);
var curHead = cm.getCursor("head");
var primIndex = getIndex(ranges, curHead);
var wasClipped = cursorEqual(ranges[primIndex].head, ranges[primIndex].anchor);
var max = ranges.length - 1;
var index = max - primIndex > primIndex ? max : 0;
var base = ranges[index].anchor;
var firstLine = Math.min(base.line, head.line);
var lastLine = Math.max(base.line, head.line);
var baseCh = base.ch, headCh = head.ch;
var dir = ranges[index].head.ch - baseCh;
var newDir = headCh - baseCh;
if (dir > 0 && newDir <= 0) {
baseCh++;
if (!isClipped) {
headCh--;
}
} else if (dir < 0 && newDir >= 0) {
baseCh--;
if (!wasClipped) {
headCh++;
}
} else if (dir < 0 && newDir == -1) {
baseCh--;
headCh++;
}
for (var line = firstLine; line <= lastLine; line++) {
var range = { anchor: new Pos2(line, baseCh), head: new Pos2(line, headCh) };
selections.push(range);
}
cm.setSelections(selections);
selectionEnd.ch = headCh;
base.ch = baseCh;
return base;
}
function selectForInsert(cm, head, height) {
var sel = [];
for (var i = 0; i < height; i++) {
var lineHead = offsetCursor(head, i, 0);
sel.push({ anchor: lineHead, head: lineHead });
}
cm.setSelections(sel, 0);
}
function getIndex(ranges, cursor, end) {
for (var i = 0; i < ranges.length; i++) {
var atAnchor = cursorEqual(ranges[i].anchor, cursor);
var atHead = cursorEqual(ranges[i].head, cursor);
if (atAnchor || atHead) {
return i;
}
}
return -1;
}
function getSelectedAreaRange(cm, vim2) {
var selections = cm.listSelections();
var start = selections[0];
var end = selections[selections.length - 1];
var selectionStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head;
var selectionEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor;
return [selectionStart, selectionEnd];
}
function updateLastSelection(cm, vim2) {
var anchor = vim2.sel.anchor;
var head = vim2.sel.head;
if (vim2.lastPastedText) {
head = cm.posFromIndex(cm.indexFromPos(anchor) + vim2.lastPastedText.length);
vim2.lastPastedText = void 0;
}
vim2.lastSelection = {
"anchorMark": cm.setBookmark(anchor),
"headMark": cm.setBookmark(head),
"anchor": copyCursor(anchor),
"head": copyCursor(head),
"visualMode": vim2.visualMode,
"visualLine": vim2.visualLine,
"visualBlock": vim2.visualBlock
};
}
function expandSelection(cm, start, end, move) {
var sel = cm.state.vim.sel;
var head = move ? start : sel.head;
var anchor = move ? start : sel.anchor;
var tmp;
if (cursorIsBefore(end, start)) {
tmp = end;
end = start;
start = tmp;
}
if (cursorIsBefore(head, anchor)) {
head = cursorMin(start, head);
anchor = cursorMax(anchor, end);
} else {
anchor = cursorMin(start, anchor);
head = cursorMax(head, end);
head = offsetCursor(head, 0, -1);
if (head.ch == -1 && head.line != cm.firstLine()) {
head = new Pos2(head.line - 1, lineLength(cm, head.line - 1));
}
}
return [anchor, head];
}
function updateCmSelection(cm, sel, mode) {
var vim2 = cm.state.vim;
sel = sel || vim2.sel;
if (!mode) {
mode = vim2.visualLine ? "line" : vim2.visualBlock ? "block" : "char";
}
var cmSel = makeCmSelection(cm, sel, mode);
cm.setSelections(cmSel.ranges, cmSel.primary);
}
function makeCmSelection(cm, sel, mode, exclusive) {
var head = copyCursor(sel.head);
var anchor = copyCursor(sel.anchor);
if (mode == "char") {
var headOffset = !exclusive && !cursorIsBefore(sel.head, sel.anchor) ? 1 : 0;
var anchorOffset = cursorIsBefore(sel.head, sel.anchor) ? 1 : 0;
head = offsetCursor(sel.head, 0, headOffset);
anchor = offsetCursor(sel.anchor, 0, anchorOffset);
return {
ranges: [{ anchor, head }],
primary: 0
};
} else if (mode == "line") {
if (!cursorIsBefore(sel.head, sel.anchor)) {
anchor.ch = 0;
var lastLine = cm.lastLine();
if (head.line > lastLine) {
head.line = lastLine;
}
head.ch = lineLength(cm, head.line);
} else {
head.ch = 0;
anchor.ch = lineLength(cm, anchor.line);
}
return {
ranges: [{ anchor, head }],
primary: 0
};
} else if (mode == "block") {
var top = Math.min(anchor.line, head.line), fromCh = anchor.ch, bottom = Math.max(anchor.line, head.line), toCh = head.ch;
if (fromCh < toCh) {
toCh += 1;
} else {
fromCh += 1;
}
var height = bottom - top + 1;
var primary = head.line == top ? 0 : height - 1;
var ranges = [];
for (var i = 0; i < height; i++) {
ranges.push({
anchor: new Pos2(top + i, fromCh),
head: new Pos2(top + i, toCh)
});
}
return {
ranges,
primary
};
}
throw "never happens";
}
function getHead(cm) {
var cur2 = cm.getCursor("head");
if (cm.getSelection().length == 1) {
cur2 = cursorMin(cur2, cm.getCursor("anchor"));
}
return cur2;
}
function exitVisualMode(cm, moveHead) {
var vim2 = cm.state.vim;
if (moveHead !== false) {
cm.setCursor(clipCursorToContent(cm, vim2.sel.head));
}
updateLastSelection(cm, vim2);
vim2.visualMode = false;
vim2.visualLine = false;
vim2.visualBlock = false;
if (!vim2.insertMode) CM.signal(cm, "vim-mode-change", { mode: "normal" });
}
function clipToLine(cm, curStart, curEnd) {
var selection = cm.getRange(curStart, curEnd);
if (/\n\s*$/.test(selection)) {
var lines = selection.split("\n");
lines.pop();
for (var line = lines.pop(); lines.length > 0 && line && isWhiteSpaceString(line); line = lines.pop()) {
curEnd.line--;
curEnd.ch = 0;
}
if (line) {
curEnd.line--;
curEnd.ch = lineLength(cm, curEnd.line);
} else {
curEnd.ch = 0;
}
}
}
function expandSelectionToLine(_cm, curStart, curEnd) {
curStart.ch = 0;
curEnd.ch = 0;
curEnd.line++;
}
function findFirstNonWhiteSpaceCharacter(text) {
if (!text) {
return 0;
}
var firstNonWS = text.search(/\S/);
return firstNonWS == -1 ? text.length : firstNonWS;
}
function expandWordUnderCursor(cm, { inclusive, innerWord, bigWord, noSymbol, multiline }, cursor) {
var cur2 = cursor || getHead(cm);
var line = cm.getLine(cur2.line);
var endLine = line;
var startLineNumber = cur2.line;
var endLineNumber = startLineNumber;
var idx = cur2.ch;
var wordOnNextLine;
var test = noSymbol ? wordCharTest[0] : bigWordCharTest[0];
if (innerWord && /\s/.test(line.charAt(idx))) {
test = function(ch) {
return /\s/.test(ch);
};
} else {
while (!test(line.charAt(idx))) {
idx++;
if (idx >= line.length) {
if (!multiline) return null;
idx--;
wordOnNextLine = findWord(cm, cur2, true, bigWord, true);
break;
}
}
if (bigWord) {
test = bigWordCharTest[0];
} else {
test = wordCharTest[0];
if (!test(line.charAt(idx))) {
test = wordCharTest[1];
}
}
}
var end = idx, start = idx;
while (test(line.charAt(start)) && start >= 0) {
start--;
}
start++;
if (wordOnNextLine) {
end = wordOnNextLine.to;
endLineNumber = wordOnNextLine.line;
endLine = cm.getLine(endLineNumber);
if (!endLine && end == 0) end++;
} else {
while (test(line.charAt(end)) && end < line.length) {
end++;
}
}
if (inclusive) {
var wordEnd = end;
var startsWithSpace = cur2.ch <= start && /\s/.test(line.charAt(cur2.ch));
if (!startsWithSpace) {
while (/\s/.test(endLine.charAt(end)) && end < endLine.length) {
end++;
}
}
if (wordEnd == end || startsWithSpace) {
var wordStart = start;
while (/\s/.test(line.charAt(start - 1)) && start > 0) {
start--;
}
if (!start && !startsWithSpace) {
start = wordStart;
}
}
}
return { start: new Pos2(startLineNumber, start), end: new Pos2(endLineNumber, end) };
}
function expandTagUnderCursor(cm, head, inclusive) {
var cur2 = head;
if (!CM.findMatchingTag || !CM.findEnclosingTag) {
return { start: cur2, end: cur2 };
}
var tags3 = CM.findMatchingTag(cm, head) || CM.findEnclosingTag(cm, head);
if (!tags3 || !tags3.open || !tags3.close) {
return { start: cur2, end: cur2 };
}
if (inclusive) {
return { start: tags3.open.from, end: tags3.close.to };
}
return { start: tags3.open.to, end: tags3.close.from };
}
function recordJumpPosition(cm, oldCur, newCur) {
if (!cursorEqual(oldCur, newCur)) {
vimGlobalState.jumpList.add(cm, oldCur, newCur);
}
}
function recordLastCharacterSearch(increment, args) {
vimGlobalState.lastCharacterSearch.increment = increment;
vimGlobalState.lastCharacterSearch.forward = args.forward;
vimGlobalState.lastCharacterSearch.selectedCharacter = args.selectedCharacter;
}
var symbolToMode = {
"(": "bracket",
")": "bracket",
"{": "bracket",
"}": "bracket",
"[": "section",
"]": "section",
"*": "comment",
"/": "comment",
"m": "method",
"M": "method",
"#": "preprocess"
};
var findSymbolModes = {
bracket: {
isComplete: function(state) {
if (state.nextCh === state.symb) {
state.depth++;
if (state.depth >= 1) return true;
} else if (state.nextCh === state.reverseSymb) {
state.depth--;
}
return false;
}
},
section: {
init: function(state) {
state.curMoveThrough = true;
state.symb = (state.forward ? "]" : "[") === state.symb ? "{" : "}";
},
isComplete: function(state) {
return state.index === 0 && state.nextCh === state.symb;
}
},
comment: {
isComplete: function(state) {
var found = state.lastCh === "*" && state.nextCh === "/";
state.lastCh = state.nextCh;
return found;
}
},
// TODO: The original Vim implementation only operates on level 1 and 2.
// The current implementation doesn't check for code block level and
// therefore it operates on any levels.
method: {
init: function(state) {
state.symb = state.symb === "m" ? "{" : "}";
state.reverseSymb = state.symb === "{" ? "}" : "{";
},
isComplete: function(state) {
if (state.nextCh === state.symb) return true;
return false;
}
},
preprocess: {
init: function(state) {
state.index = 0;
},
isComplete: function(state) {
var _a;
if (state.nextCh === "#") {
var token = (_a = state.lineText.match(/^#(\w+)/)) == null ? void 0 : _a[1];
if (token === "endif") {
if (state.forward && state.depth === 0) {
return true;
}
state.depth++;
} else if (token === "if") {
if (!state.forward && state.depth === 0) {
return true;
}
state.depth--;
}
if (token === "else" && state.depth === 0) return true;
}
return false;
}
}
};
function findSymbol(cm, repeat, forward, symb) {
var cur2 = copyCursor(cm.getCursor());
var increment = forward ? 1 : -1;
var endLine = forward ? cm.lineCount() : -1;
var curCh = cur2.ch;
var line = cur2.line;
var lineText = cm.getLine(line);
var state = {
lineText,
nextCh: lineText.charAt(curCh),
lastCh: null,
index: curCh,
symb,
reverseSymb: (forward ? { ")": "(", "}": "{" } : { "(": ")", "{": "}" })[symb],
forward,
depth: 0,
curMoveThrough: false
};
var mode = symbolToMode[symb];
if (!mode) return cur2;
var init = findSymbolModes[mode].init;
var isComplete = findSymbolModes[mode].isComplete;
if (init) {
init(state);
}
while (line !== endLine && repeat) {
state.index += increment;
state.nextCh = state.lineText.charAt(state.index);
if (!state.nextCh) {
line += increment;
state.lineText = cm.getLine(line) || "";
if (increment > 0) {
state.index = 0;
} else {
var lineLen = state.lineText.length;
state.index = lineLen > 0 ? lineLen - 1 : 0;
}
state.nextCh = state.lineText.charAt(state.index);
}
if (isComplete(state)) {
cur2.line = line;
cur2.ch = state.index;
repeat--;
}
}
if (state.nextCh || state.curMoveThrough) {
return new Pos2(line, state.index);
}
return cur2;
}
function findWord(cm, cur2, forward, bigWord, emptyLineIsWord) {
var lineNum = cur2.line;
var pos = cur2.ch;
var line = cm.getLine(lineNum);
var dir = forward ? 1 : -1;
var charTests = bigWord ? bigWordCharTest : wordCharTest;
if (emptyLineIsWord && line == "") {
lineNum += dir;
line = cm.getLine(lineNum);
if (!isLine(cm, lineNum)) {
return null;
}
pos = forward ? 0 : line.length;
}
while (true) {
if (emptyLineIsWord && line == "") {
return { from: 0, to: 0, line: lineNum };
}
var stop = dir > 0 ? line.length : -1;
var wordStart = stop, wordEnd = stop;
while (pos != stop) {
var foundWord = false;
for (var i = 0; i < charTests.length && !foundWord; ++i) {
if (charTests[i](line.charAt(pos))) {
wordStart = pos;
while (pos != stop && charTests[i](line.charAt(pos))) {
pos += dir;
}
wordEnd = pos;
foundWord = wordStart != wordEnd;
if (wordStart == cur2.ch && lineNum == cur2.line && wordEnd == wordStart + dir) {
continue;
} else {
return {
from: Math.min(wordStart, wordEnd + 1),
to: Math.max(wordStart, wordEnd),
line: lineNum
};
}
}
}
if (!foundWord) {
pos += dir;
}
}
lineNum += dir;
if (!isLine(cm, lineNum)) {
return null;
}
line = cm.getLine(lineNum);
pos = dir > 0 ? 0 : line.length;
}
}
function moveToWord(cm, cur2, repeat, forward, wordEnd, bigWord) {
var curStart = copyCursor(cur2);
var words = [];
if (forward && !wordEnd || !forward && wordEnd) {
repeat++;
}
var emptyLineIsWord = !(forward && wordEnd);
for (var i = 0; i < repeat; i++) {
var word = findWord(cm, cur2, forward, bigWord, emptyLineIsWord);
if (!word) {
var eodCh = lineLength(cm, cm.lastLine());
words.push(forward ? { line: cm.lastLine(), from: eodCh, to: eodCh } : { line: 0, from: 0, to: 0 });
break;
}
words.push(word);
cur2 = new Pos2(word.line, forward ? word.to - 1 : word.from);
}
var shortCircuit = words.length != repeat;
var firstWord = words[0];
var lastWord = words.pop();
if (forward && !wordEnd) {
if (!shortCircuit && (firstWord.from != curStart.ch || firstWord.line != curStart.line)) {
lastWord = words.pop();
}
return lastWord && new Pos2(lastWord.line, lastWord.from);
} else if (forward && wordEnd) {
return lastWord && new Pos2(lastWord.line, lastWord.to - 1);
} else if (!forward && wordEnd) {
if (!shortCircuit && (firstWord.to != curStart.ch || firstWord.line != curStart.line)) {
lastWord = words.pop();
}
return lastWord && new Pos2(lastWord.line, lastWord.to);
} else {
return lastWord && new Pos2(lastWord.line, lastWord.from);
}
}
function moveToEol(cm, head, motionArgs, vim2, keepHPos) {
var cur2 = head;
var retval = new Pos2(cur2.line + motionArgs.repeat - 1, Infinity);
var end = cm.clipPos(retval);
end.ch--;
if (!keepHPos) {
vim2.lastHPos = Infinity;
vim2.lastHSPos = cm.charCoords(end, "div").left;
}
return retval;
}
function moveToCharacter(cm, repeat, forward, character, head) {
if (!character) return;
var cur2 = head || cm.getCursor();
var start = cur2.ch;
var idx;
for (var i = 0; i < repeat; i++) {
var line = cm.getLine(cur2.line);
idx = charIdxInLine(start, line, character, forward);
if (idx == -1) {
return void 0;
}
start = idx;
}
if (idx != void 0)
return new Pos2(cm.getCursor().line, idx);
}
function moveToColumn(cm, repeat) {
var line = cm.getCursor().line;
return clipCursorToContent(cm, new Pos2(line, repeat - 1));
}
function updateMark(cm, vim2, markName, pos) {
if (!inArray(markName, validMarks) && !latinCharRegex.test(markName)) {
return;
}
if (vim2.marks[markName]) {
vim2.marks[markName].clear();
}
vim2.marks[markName] = cm.setBookmark(pos);
}
function charIdxInLine(start, line, character, forward, includeChar) {
var idx;
if (forward) {
idx = line.indexOf(character, start + 1);
} else {
idx = line.lastIndexOf(character, start - 1);
}
return idx;
}
function findParagraph(cm, head, repeat, dir, inclusive) {
var line = head.line;
var min = cm.firstLine();
var max = cm.lastLine();
var start, end, i = line;
function isEmpty(i2) {
return !cm.getLine(i2);
}
function isBoundary(i2, dir2, any) {
if (any) {
return isEmpty(i2) != isEmpty(i2 + dir2);
}
return !isEmpty(i2) && isEmpty(i2 + dir2);
}
if (dir) {
while (min <= i && i <= max && repeat > 0) {
if (isBoundary(i, dir)) {
repeat--;
}
i += dir;
}
return { start: new Pos2(i, 0), end: head };
}
var vim2 = cm.state.vim;
if (vim2.visualLine && isBoundary(line, 1, true)) {
var anchor = vim2.sel.anchor;
if (isBoundary(anchor.line, -1, true)) {
if (!inclusive || anchor.line != line) {
line += 1;
}
}
}
var startState = isEmpty(line);
for (i = line; i <= max && repeat; i++) {
if (isBoundary(i, 1, true)) {
if (!inclusive || isEmpty(i) != startState) {
repeat--;
}
}
}
end = new Pos2(i, 0);
if (i > max && !startState) {
startState = true;
} else {
inclusive = false;
}
for (i = line; i > min; i--) {
if (!inclusive || isEmpty(i) == startState || i == line) {
if (isBoundary(i, -1, true)) {
break;
}
}
}
start = new Pos2(i, 0);
return { start, end };
}
function getSentence(cm, cur2, repeat, dir, inclusive) {
function nextChar2(curr) {
if (curr.line === null) return;
if (curr.pos + curr.dir < 0 || curr.pos + curr.dir >= curr.line.length) {
curr.line = null;
} else {
curr.pos += curr.dir;
}
}
function forward(cm2, ln, pos, dir2) {
var line = cm2.getLine(ln);
var curr = {
line,
ln,
pos,
dir: dir2
};
if (curr.line === "") {
return { ln: curr.ln, pos: curr.pos };
}
var lastSentencePos = curr.pos;
nextChar2(curr);
while (curr.line !== null) {
lastSentencePos = curr.pos;
if (isEndOfSentenceSymbol(curr.line[curr.pos])) {
if (!inclusive) {
return { ln: curr.ln, pos: curr.pos + 1 };
} else {
nextChar2(curr);
while (curr.line !== null) {
if (isWhiteSpaceString(curr.line[curr.pos])) {
lastSentencePos = curr.pos;
nextChar2(curr);
} else {
break;
}
}
return { ln: curr.ln, pos: lastSentencePos + 1 };
}
}
nextChar2(curr);
}
return { ln: curr.ln, pos: lastSentencePos + 1 };
}
function reverse(cm2, ln, pos, dir2) {
var line = cm2.getLine(ln);
var curr = {
line,
ln,
pos,
dir: dir2
};
if (curr.line === "") {
return { ln: curr.ln, pos: curr.pos };
}
var lastSentencePos = curr.pos;
nextChar2(curr);
while (curr.line !== null) {
if (!isWhiteSpaceString(curr.line[curr.pos]) && !isEndOfSentenceSymbol(curr.line[curr.pos])) {
lastSentencePos = curr.pos;
} else if (isEndOfSentenceSymbol(curr.line[curr.pos])) {
if (!inclusive) {
return { ln: curr.ln, pos: lastSentencePos };
} else {
if (isWhiteSpaceString(curr.line[curr.pos + 1])) {
return { ln: curr.ln, pos: curr.pos + 1 };
} else {
return { ln: curr.ln, pos: lastSentencePos };
}
}
}
nextChar2(curr);
}
curr.line = line;
if (inclusive && isWhiteSpaceString(curr.line[curr.pos])) {
return { ln: curr.ln, pos: curr.pos };
} else {
return { ln: curr.ln, pos: lastSentencePos };
}
}
var curr_index = {
ln: cur2.line,
pos: cur2.ch
};
while (repeat > 0) {
if (dir < 0) {
curr_index = reverse(cm, curr_index.ln, curr_index.pos, dir);
} else {
curr_index = forward(cm, curr_index.ln, curr_index.pos, dir);
}
repeat--;
}
return new Pos2(curr_index.ln, curr_index.pos);
}
function findSentence(cm, cur2, repeat, dir) {
function nextChar2(cm2, idx) {
if (idx.line === null) return;
if (idx.pos + idx.dir < 0 || idx.pos + idx.dir >= idx.line.length) {
idx.ln += idx.dir;
if (!isLine(cm2, idx.ln)) {
idx.line = null;
return;
}
idx.line = cm2.getLine(idx.ln);
idx.pos = idx.dir > 0 ? 0 : idx.line.length - 1;
} else {
idx.pos += idx.dir;
}
}
function forward(cm2, ln, pos, dir2) {
var line = cm2.getLine(ln);
var stop = line === "";
var curr = {
line,
ln,
pos,
dir: dir2
};
var last_valid = {
ln: curr.ln,
pos: curr.pos
};
var skip_empty_lines = curr.line === "";
nextChar2(cm2, curr);
while (curr.line !== null) {
last_valid.ln = curr.ln;
last_valid.pos = curr.pos;
if (curr.line === "" && !skip_empty_lines) {
return { ln: curr.ln, pos: curr.pos };
} else if (stop && curr.line !== "" && !isWhiteSpaceString(curr.line[curr.pos])) {
return { ln: curr.ln, pos: curr.pos };
} else if (isEndOfSentenceSymbol(curr.line[curr.pos]) && !stop && (curr.pos === curr.line.length - 1 || isWhiteSpaceString(curr.line[curr.pos + 1]))) {
stop = true;
}
nextChar2(cm2, curr);
}
var line = cm2.getLine(last_valid.ln);
last_valid.pos = 0;
for (var i = line.length - 1; i >= 0; --i) {
if (!isWhiteSpaceString(line[i])) {
last_valid.pos = i;
break;
}
}
return last_valid;
}
function reverse(cm2, ln, pos, dir2) {
var line = cm2.getLine(ln);
var curr = {
line,
ln,
pos,
dir: dir2
};
var last_valid_ln = curr.ln;
var last_valid_pos = null;
var skip_empty_lines = curr.line === "";
nextChar2(cm2, curr);
while (curr.line !== null) {
if (curr.line === "" && !skip_empty_lines) {
if (last_valid_pos !== null) {
return { ln: last_valid_ln, pos: last_valid_pos };
} else {
return { ln: curr.ln, pos: curr.pos };
}
} else if (isEndOfSentenceSymbol(curr.line[curr.pos]) && last_valid_pos !== null && !(curr.ln === last_valid_ln && curr.pos + 1 === last_valid_pos)) {
return { ln: last_valid_ln, pos: last_valid_pos };
} else if (curr.line !== "" && !isWhiteSpaceString(curr.line[curr.pos])) {
skip_empty_lines = false;
last_valid_ln = curr.ln;
last_valid_pos = curr.pos;
}
nextChar2(cm2, curr);
}
var line = cm2.getLine(last_valid_ln);
last_valid_pos = 0;
for (var i = 0; i < line.length; ++i) {
if (!isWhiteSpaceString(line[i])) {
last_valid_pos = i;
break;
}
}
return { ln: last_valid_ln, pos: last_valid_pos };
}
var curr_index = {
ln: cur2.line,
pos: cur2.ch
};
while (repeat > 0) {
if (dir < 0) {
curr_index = reverse(cm, curr_index.ln, curr_index.pos, dir);
} else {
curr_index = forward(cm, curr_index.ln, curr_index.pos, dir);
}
repeat--;
}
return new Pos2(curr_index.ln, curr_index.pos);
}
function selectCompanionObject(cm, head, symb, inclusive) {
var cur2 = head;
var bracketRegexp = {
"(": /[()]/,
")": /[()]/,
"[": /[[\]]/,
"]": /[[\]]/,
"{": /[{}]/,
"}": /[{}]/,
"<": /[<>]/,
">": /[<>]/
}[symb];
var openSym = {
"(": "(",
")": "(",
"[": "[",
"]": "[",
"{": "{",
"}": "{",
"<": "<",
">": "<"
}[symb];
var curChar = cm.getLine(cur2.line).charAt(cur2.ch);
var offset = curChar === openSym ? 1 : 0;
var startBracket = cm.scanForBracket(new Pos2(cur2.line, cur2.ch + offset), -1, void 0, { "bracketRegex": bracketRegexp });
var endBracket = cm.scanForBracket(new Pos2(cur2.line, cur2.ch + offset), 1, void 0, { "bracketRegex": bracketRegexp });
if (!startBracket || !endBracket) return null;
var start = startBracket.pos;
var end = endBracket.pos;
if (start.line == end.line && start.ch > end.ch || start.line > end.line) {
var tmp = start;
start = end;
end = tmp;
}
if (inclusive) {
end.ch += 1;
} else {
start.ch += 1;
}
return { start, end };
}
function findBeginningAndEnd(cm, head, symb, inclusive) {
var cur2 = copyCursor(head);
var line = cm.getLine(cur2.line);
var chars = line.split("");
var start, end, i, len;
var firstIndex = chars.indexOf(symb);
if (cur2.ch < firstIndex) {
cur2.ch = firstIndex;
} else if (firstIndex < cur2.ch && chars[cur2.ch] == symb) {
var stringAfter = /string/.test(cm.getTokenTypeAt(offsetCursor(head, 0, 1)));
var stringBefore = /string/.test(cm.getTokenTypeAt(head));
var isStringStart = stringAfter && !stringBefore;
if (!isStringStart) {
end = cur2.ch;
--cur2.ch;
}
}
if (chars[cur2.ch] == symb && !end) {
start = cur2.ch + 1;
} else {
for (i = cur2.ch; i > -1 && !start; i--) {
if (chars[i] == symb) {
start = i + 1;
}
}
}
if (start && !end) {
for (i = start, len = chars.length; i < len && !end; i++) {
if (chars[i] == symb) {
end = i;
}
}
}
if (!start || !end) {
return { start: cur2, end: cur2 };
}
if (inclusive) {
--start;
++end;
}
return {
start: new Pos2(cur2.line, start),
end: new Pos2(cur2.line, end)
};
}
defineOption("pcre", true, "boolean");
class SearchState {
constructor() {
this.highlightTimeout;
}
getQuery() {
return vimGlobalState.query;
}
setQuery(query) {
vimGlobalState.query = query;
}
getOverlay() {
return this.searchOverlay;
}
setOverlay(overlay) {
this.searchOverlay = overlay;
}
isReversed() {
return vimGlobalState.isReversed;
}
setReversed(reversed) {
vimGlobalState.isReversed = reversed;
}
getScrollbarAnnotate() {
return this.annotate;
}
setScrollbarAnnotate(annotate) {
this.annotate = annotate;
}
}
function getSearchState(cm) {
var vim2 = cm.state.vim;
return vim2.searchState_ || (vim2.searchState_ = new SearchState());
}
function splitBySlash(argString) {
return splitBySeparator(argString, "/");
}
function findUnescapedSlashes(argString) {
return findUnescapedSeparators(argString, "/");
}
function splitBySeparator(argString, separator) {
var slashes = findUnescapedSeparators(argString, separator) || [];
if (!slashes.length) return [];
var tokens = [];
if (slashes[0] !== 0) return;
for (var i = 0; i < slashes.length; i++) {
if (typeof slashes[i] == "number")
tokens.push(argString.substring(slashes[i] + 1, slashes[i + 1]));
}
return tokens;
}
function findUnescapedSeparators(str, separator) {
if (!separator)
separator = "/";
var escapeNextChar = false;
var slashes = [];
for (var i = 0; i < str.length; i++) {
var c = str.charAt(i);
if (!escapeNextChar && c == separator) {
slashes.push(i);
}
escapeNextChar = !escapeNextChar && c == "\\";
}
return slashes;
}
function translateRegex(str) {
var modes = {
V: "|(){+?*.[$^",
// verynomagic
M: "|(){+?*.[",
// nomagic
m: "|(){+?",
// magic
v: "<>"
// verymagic
};
var escapes = {
">": "(?<=[\\w])(?=[^\\w]|$)",
"<": "(?<=[^\\w]|^)(?=[\\w])"
};
var specials = modes.m;
var regex = str.replace(/\\.|[\[|(){+*?.$^<>]/g, function(match) {
if (match[0] === "\\") {
var nextChar2 = match[1];
if (nextChar2 === "}" || specials.indexOf(nextChar2) != -1) {
return nextChar2;
}
if (nextChar2 in modes) {
specials = modes[nextChar2];
return "";
}
if (nextChar2 in escapes) {
return escapes[nextChar2];
}
return match;
} else {
if (specials.indexOf(match) != -1) {
return escapes[match] || "\\" + match;
}
return match;
}
});
var i = regex.indexOf("\\zs");
if (i != -1) {
regex = "(?<=" + regex.slice(0, i) + ")" + regex.slice(i + 3);
}
i = regex.indexOf("\\ze");
if (i != -1) {
regex = regex.slice(0, i) + "(?=" + regex.slice(i + 3) + ")";
}
return regex;
}
var charUnescapes = { "\\n": "\n", "\\r": "\r", "\\t": " " };
function translateRegexReplace(str) {
var escapeNextChar = false;
var out = [];
for (var i = -1; i < str.length; i++) {
var c = str.charAt(i) || "";
var n = str.charAt(i + 1) || "";
if (charUnescapes[c + n]) {
out.push(charUnescapes[c + n]);
i++;
} else if (escapeNextChar) {
out.push(c);
escapeNextChar = false;
} else {
if (c === "\\") {
escapeNextChar = true;
if (isNumber(n) || n === "$") {
out.push("$");
} else if (n !== "/" && n !== "\\") {
out.push("\\");
}
} else {
if (c === "$") {
out.push("$");
}
out.push(c);
if (n === "/") {
out.push("\\");
}
}
}
}
return out.join("");
}
var unescapes = { "\\/": "/", "\\\\": "\\", "\\n": "\n", "\\r": "\r", "\\t": " ", "\\&": "&" };
function unescapeRegexReplace(str) {
var stream = new CM.StringStream(str);
var output = [];
while (!stream.eol()) {
while (stream.peek() && stream.peek() != "\\") {
output.push(stream.next());
}
var matched = false;
for (var matcher in unescapes) {
if (stream.match(matcher, true)) {
matched = true;
output.push(unescapes[matcher]);
break;
}
}
if (!matched) {
output.push(stream.next());
}
}
return output.join("");
}
function parseQuery(query, ignoreCase, smartCase) {
var lastSearchRegister = vimGlobalState.registerController.getRegister("/");
lastSearchRegister.setText(query);
var slashes = findUnescapedSlashes(query);
var regexPart;
var forceIgnoreCase;
if (!slashes.length) {
regexPart = query;
} else {
regexPart = query.substring(0, slashes[0]);
var flagsPart = query.substring(slashes[0]);
forceIgnoreCase = flagsPart.indexOf("i") != -1;
}
if (!regexPart) {
return null;
}
if (!getOption("pcre")) {
regexPart = translateRegex(regexPart);
}
if (smartCase) {
ignoreCase = /^[^A-Z]*$/.test(regexPart);
}
var regexp = new RegExp(
regexPart,
ignoreCase || forceIgnoreCase ? "im" : "m"
);
return regexp;
}
function dom(n) {
if (typeof n === "string") n = document.createElement(n);
for (var i = 1; i < arguments.length; i++) {
var a = arguments[i];
if (!a) continue;
if (typeof a !== "object") a = document.createTextNode(a);
if (a.nodeType) n.appendChild(a);
else for (var key in a) {
if (!Object.prototype.hasOwnProperty.call(a, key)) continue;
if (key[0] === "$") n.style[key.slice(1)] = a[key];
else if (typeof a[key] == "function") n[key] = a[key];
else n.setAttribute(key, a[key]);
}
}
return n;
}
function showConfirm(cm, template, long) {
var pre = dom("div", { $color: "red", $whiteSpace: "pre", class: "cm-vim-message" }, template);
if (cm.openNotification) {
if (long) {
pre = dom("div", {}, pre, dom("div", {}, "Press ENTER or type command to continue"));
if (cm.state.closeVimNotification) {
cm.state.closeVimNotification();
}
cm.state.closeVimNotification = cm.openNotification(pre, { bottom: true, duration: 0 });
} else {
cm.openNotification(pre, { bottom: true, duration: 15e3 });
}
} else {
alert(pre.innerText);
}
}
function makePrompt(prefix, desc) {
return dom(
"div",
{ $display: "flex", $flex: 1 },
dom(
"span",
{ $fontFamily: "monospace", $whiteSpace: "pre", $flex: 1, $display: "flex" },
prefix,
dom("input", {
type: "text",
autocorrect: "off",
autocapitalize: "off",
spellcheck: "false",
$flex: 1
})
),
desc && dom("span", { $color: "#888" }, desc)
);
}
function showPrompt(cm, options2) {
var _a;
if (keyToKeyStack.length) {
if (!options2.value) options2.value = "";
virtualPrompt = options2;
return;
}
var template = makePrompt(options2.prefix, options2.desc);
if (cm.openDialog) {
cm.openDialog(template, options2.onClose, {
onKeyDown: options2.onKeyDown,
onKeyUp: options2.onKeyUp,
bottom: true,
selectValueOnOpen: false,
value: options2.value
});
} else {
var shortText = "";
if (typeof options2.prefix != "string" && options2.prefix) shortText += options2.prefix.textContent;
if (options2.desc) shortText += " " + options2.desc;
(_a = options2.onClose) == null ? void 0 : _a.call(options2, prompt(shortText, ""));
}
}
function regexEqual(r1, r2) {
if (r1 instanceof RegExp && r2 instanceof RegExp) {
return r1.flags == r2.flags && r1.source == r2.source;
}
return false;
}
function updateSearchQuery(cm, rawQuery, ignoreCase, smartCase) {
if (!rawQuery) {
return;
}
var state = getSearchState(cm);
var query = parseQuery(rawQuery, !!ignoreCase, !!smartCase);
if (!query) {
return;
}
highlightSearchMatches(cm, query);
if (regexEqual(query, state.getQuery())) {
return query;
}
state.setQuery(query);
return query;
}
function searchOverlay(query) {
if (query.source.charAt(0) == "^") {
var matchSol = true;
}
return {
token: function(stream) {
if (matchSol && !stream.sol()) {
stream.skipToEnd();
return;
}
var match = stream.match(query, false);
if (match) {
if (match[0].length == 0) {
stream.next();
return "searching";
}
if (!stream.sol()) {
stream.backUp(1);
if (!query.exec(stream.next() + match[0])) {
stream.next();
return null;
}
}
stream.match(query);
return "searching";
}
while (!stream.eol()) {
stream.next();
if (stream.match(query, false)) break;
}
},
query
};
}
var highlightTimeout = 0;
function highlightSearchMatches(cm, query) {
clearTimeout(highlightTimeout);
var searchState = getSearchState(cm);
searchState.highlightTimeout = highlightTimeout;
highlightTimeout = setTimeout(function() {
if (!cm.state.vim) return;
var searchState2 = getSearchState(cm);
searchState2.highlightTimeout = void 0;
var overlay = searchState2.getOverlay();
if (!overlay || query != overlay.query) {
if (overlay) {
cm.removeOverlay(overlay);
}
overlay = searchOverlay(query);
cm.addOverlay(overlay);
if (cm.showMatchesOnScrollbar) {
if (searchState2.getScrollbarAnnotate()) {
searchState2.getScrollbarAnnotate().clear();
}
searchState2.setScrollbarAnnotate(cm.showMatchesOnScrollbar(query));
}
searchState2.setOverlay(overlay);
}
}, 50);
}
function findNext(cm, prev, query, repeat) {
return cm.operation(function() {
if (repeat === void 0) {
repeat = 1;
}
var pos = cm.getCursor();
var cursor = cm.getSearchCursor(query, pos);
for (var i = 0; i < repeat; i++) {
var found = cursor.find(prev);
if (i == 0 && found && cursorEqual(cursor.from(), pos)) {
var lastEndPos = prev ? cursor.from() : cursor.to();
found = cursor.find(prev);
if (found && !found[0] && cursorEqual(cursor.from(), lastEndPos)) {
if (cm.getLine(lastEndPos.line).length == lastEndPos.ch)
found = cursor.find(prev);
}
}
if (!found) {
cursor = cm.getSearchCursor(
query,
// @ts-ignore
prev ? new Pos2(cm.lastLine()) : new Pos2(cm.firstLine(), 0)
);
if (!cursor.find(prev)) {
return;
}
}
}
return cursor.from();
});
}
function findNextFromAndToInclusive(cm, prev, query, repeat, vim2) {
return cm.operation(function() {
if (repeat === void 0) {
repeat = 1;
}
var pos = cm.getCursor();
var cursor = cm.getSearchCursor(query, pos);
var found = cursor.find(!prev);
if (!vim2.visualMode && found && cursorEqual(cursor.from(), pos)) {
cursor.find(!prev);
}
for (var i = 0; i < repeat; i++) {
found = cursor.find(prev);
if (!found) {
cursor = cm.getSearchCursor(
query,
// @ts-ignore
prev ? new Pos2(cm.lastLine()) : new Pos2(cm.firstLine(), 0)
);
if (!cursor.find(prev)) {
return;
}
}
}
var from = cursor.from();
var to = cursor.to();
return from && to && [from, to];
});
}
function clearSearchHighlight(cm) {
var state = getSearchState(cm);
if (state.highlightTimeout) {
clearTimeout(state.highlightTimeout);
state.highlightTimeout = void 0;
}
cm.removeOverlay(getSearchState(cm).getOverlay());
state.setOverlay(null);
if (state.getScrollbarAnnotate()) {
state.getScrollbarAnnotate().clear();
state.setScrollbarAnnotate(null);
}
}
function isInRange(pos, start, end) {
if (typeof pos != "number") {
pos = pos.line;
}
if (start instanceof Array) {
return inArray(pos, start);
} else {
if (typeof end == "number") {
return pos >= start && pos <= end;
} else {
return pos == start;
}
}
}
function getUserVisibleLines(cm) {
var scrollInfo = cm.getScrollInfo();
var occludeToleranceTop = 6;
var occludeToleranceBottom = 10;
var from = cm.coordsChar({ left: 0, top: occludeToleranceTop + scrollInfo.top }, "local");
var bottomY = scrollInfo.clientHeight - occludeToleranceBottom + scrollInfo.top;
var to = cm.coordsChar({ left: 0, top: bottomY }, "local");
return { top: from.line, bottom: to.line };
}
function getMarkPos(cm, vim2, markName) {
if (markName == "'" || markName == "`") {
return vimGlobalState.jumpList.find(cm, -1) || new Pos2(0, 0);
} else if (markName == ".") {
return getLastEditPos(cm);
}
var mark = vim2.marks[markName];
return mark && mark.find();
}
function getLastEditPos(cm) {
if (cm.getLastEditEnd) {
return cm.getLastEditEnd();
}
var done = (
/**@type{any}*/
cm.doc.history.done
);
for (var i = done.length; i--; ) {
if (done[i].changes) {
return copyCursor(done[i].changes[0].to);
}
}
}
class ExCommandDispatcher {
constructor() {
this.commandMap_;
this.buildCommandMap_();
}
/**
* @arg {CodeMirrorV} cm
* @arg {string} input
* @arg {{ callback: () => void; } | undefined} [opt_params]
*/
processCommand(cm, input, opt_params) {
var that = this;
cm.operation(function() {
if (cm.curOp) cm.curOp.isVimOp = true;
that._processCommand(cm, input, opt_params);
});
}
/**
* @arg {CodeMirrorV} cm
* @arg {string} input
* @arg {{ callback?: () => void; input?: string, line?: string, commandName?: string } } [opt_params]
*/
_processCommand(cm, input, opt_params) {
var vim2 = cm.state.vim;
var commandHistoryRegister = vimGlobalState.registerController.getRegister(":");
var previousCommand = commandHistoryRegister.toString();
var inputStream = new CM.StringStream(input);
commandHistoryRegister.setText(input);
var params = opt_params || {};
params.input = input;
try {
this.parseInput_(cm, inputStream, params);
} catch (e) {
showConfirm(cm, e + "");
throw e;
}
if (vim2.visualMode) {
exitVisualMode(cm);
}
var command;
var commandName;
if (!params.commandName) {
if (params.line !== void 0) {
commandName = "move";
}
} else {
command = this.matchCommand_(params.commandName);
if (command) {
commandName = command.name;
if (command.excludeFromCommandHistory) {
commandHistoryRegister.setText(previousCommand);
}
this.parseCommandArgs_(inputStream, params, command);
if (command.type == "exToKey") {
doKeyToKey(cm, command.toKeys || "", command);
return;
} else if (command.type == "exToEx") {
this.processCommand(cm, command.toInput || "");
return;
}
}
}
if (!commandName) {
showConfirm(cm, 'Not an editor command ":' + input + '"');
return;
}
try {
exCommands[commandName](cm, params);
if ((!command || !command.possiblyAsync) && params.callback) {
params.callback();
}
} catch (e) {
showConfirm(cm, e + "");
throw e;
}
}
/**
* @param {CodeMirrorV} cm
* @param {import("@codemirror/language").StringStream} inputStream
* @param {{ callback?: (() => void) | undefined; input?: string | undefined; line?: any; commandName?: any; lineEnd?: any; selectionLine?: any; selectionLineEnd?: any; }} result
*/
parseInput_(cm, inputStream, result) {
var _a, _b;
inputStream.eatWhile(":");
if (inputStream.eat("%")) {
result.line = cm.firstLine();
result.lineEnd = cm.lastLine();
} else {
result.line = this.parseLineSpec_(cm, inputStream);
if (result.line !== void 0 && inputStream.eat(",")) {
result.lineEnd = this.parseLineSpec_(cm, inputStream);
}
}
if (result.line == void 0) {
if (cm.state.vim.visualMode) {
result.selectionLine = (_a = getMarkPos(cm, cm.state.vim, "<")) == null ? void 0 : _a.line;
result.selectionLineEnd = (_b = getMarkPos(cm, cm.state.vim, ">")) == null ? void 0 : _b.line;
} else {
result.selectionLine = cm.getCursor().line;
}
} else {
result.selectionLine = result.line;
result.selectionLineEnd = result.lineEnd;
}
var commandMatch2 = inputStream.match(/^(\w+|!!|@@|[!#&*<=>@~])/);
if (commandMatch2) {
result.commandName = commandMatch2[1];
} else {
result.commandName = (inputStream.match(/.*/) || [""])[0];
}
return result;
}
/**
* @param {CodeMirrorV} cm
* @param {import("@codemirror/language").StringStream} inputStream
*/
parseLineSpec_(cm, inputStream) {
var numberMatch = inputStream.match(/^(\d+)/);
if (numberMatch) {
return parseInt(numberMatch[1], 10) - 1;
}
switch (inputStream.next()) {
case ".":
return this.parseLineSpecOffset_(inputStream, cm.getCursor().line);
case "$":
return this.parseLineSpecOffset_(inputStream, cm.lastLine());
case "'":
var markName = inputStream.next() || "";
var markPos = getMarkPos(cm, cm.state.vim, markName);
if (!markPos) throw new Error("Mark not set");
return this.parseLineSpecOffset_(inputStream, markPos.line);
case "-":
case "+":
inputStream.backUp(1);
return this.parseLineSpecOffset_(inputStream, cm.getCursor().line);
default:
inputStream.backUp(1);
return void 0;
}
}
/**
* @param {string | import("@codemirror/language").StringStream} inputStream
* @param {number} line
*/
parseLineSpecOffset_(inputStream, line) {
var offsetMatch = inputStream.match(/^([+-])?(\d+)/);
if (offsetMatch) {
var offset = parseInt(offsetMatch[2], 10);
if (offsetMatch[1] == "-") {
line -= offset;
} else {
line += offset;
}
}
return line;
}
/**
* @param {import("@codemirror/language").StringStream} inputStream
* @param {import("./types").exCommandArgs} params
* @param {import("./types").exCommandDefinition} command
*/
parseCommandArgs_(inputStream, params, command) {
var _a;
if (inputStream.eol()) {
return;
}
params.argString = (_a = inputStream.match(/.*/)) == null ? void 0 : _a[0];
var delim = command.argDelimiter || /\s+/;
var args = trim(params.argString || "").split(delim);
if (args.length && args[0]) {
params.args = args;
}
}
/**
* @arg {string} commandName
*/
matchCommand_(commandName) {
for (var i = commandName.length; i > 0; i--) {
var prefix = commandName.substring(0, i);
if (this.commandMap_[prefix]) {
var command = this.commandMap_[prefix];
if (command.name.indexOf(commandName) === 0) {
return command;
}
}
}
}
buildCommandMap_() {
this.commandMap_ = {};
for (var i = 0; i < defaultExCommandMap.length; i++) {
var command = defaultExCommandMap[i];
var key = command.shortName || command.name;
this.commandMap_[key] = command;
}
}
/**@type {(lhs: string, rhs: string, ctx: string|void, noremap?: boolean) => void} */
map(lhs, rhs, ctx, noremap2) {
if (lhs != ":" && lhs.charAt(0) == ":") {
if (ctx) {
throw Error("Mode not supported for ex mappings");
}
var commandName = lhs.substring(1);
if (rhs != ":" && rhs.charAt(0) == ":") {
this.commandMap_[commandName] = {
name: commandName,
type: "exToEx",
toInput: rhs.substring(1),
user: true
};
} else {
this.commandMap_[commandName] = {
name: commandName,
type: "exToKey",
toKeys: rhs,
user: true
};
}
} else {
var mapping = {
keys: lhs,
type: "keyToKey",
toKeys: rhs,
noremap: !!noremap2
};
if (ctx) {
mapping.context = ctx;
}
_mapCommand(mapping);
}
}
/**@type {(lhs: string, ctx: string) => boolean|void} */
unmap(lhs, ctx) {
if (lhs != ":" && lhs.charAt(0) == ":") {
if (ctx) {
throw Error("Mode not supported for ex mappings");
}
var commandName = lhs.substring(1);
if (this.commandMap_[commandName] && this.commandMap_[commandName].user) {
delete this.commandMap_[commandName];
return true;
}
} else {
var keys2 = lhs;
for (var i = 0; i < defaultKeymap2.length; i++) {
if (keys2 == defaultKeymap2[i].keys && defaultKeymap2[i].context === ctx) {
defaultKeymap2.splice(i, 1);
removeUsedKeys(keys2);
return true;
}
}
}
}
}
var exCommands = {
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
colorscheme: function(cm, params) {
if (!params.args || params.args.length < 1) {
showConfirm(cm, cm.getOption("theme"));
return;
}
cm.setOption("theme", params.args[0]);
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params @arg {'insert'|'normal'|string} [ctx] @arg {boolean} [defaultOnly]*/
map: function(cm, params, ctx, defaultOnly) {
var mapArgs = params.args;
if (!mapArgs || mapArgs.length < 2) {
if (cm) {
showConfirm(cm, "Invalid mapping: " + params.input);
}
return;
}
exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx, defaultOnly);
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
imap: function(cm, params) {
this.map(cm, params, "insert");
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
nmap: function(cm, params) {
this.map(cm, params, "normal");
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
vmap: function(cm, params) {
this.map(cm, params, "visual");
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
omap: function(cm, params) {
this.map(cm, params, "operatorPending");
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
noremap: function(cm, params) {
this.map(cm, params, void 0, true);
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
inoremap: function(cm, params) {
this.map(cm, params, "insert", true);
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
nnoremap: function(cm, params) {
this.map(cm, params, "normal", true);
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
vnoremap: function(cm, params) {
this.map(cm, params, "visual", true);
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
onoremap: function(cm, params) {
this.map(cm, params, "operatorPending", true);
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params @arg {string} ctx*/
unmap: function(cm, params, ctx) {
var mapArgs = params.args;
if (!mapArgs || mapArgs.length < 1 || !exCommandDispatcher.unmap(mapArgs[0], ctx)) {
if (cm) {
showConfirm(cm, "No such mapping: " + params.input);
}
}
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
mapclear: function(cm, params) {
vimApi.mapclear();
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
imapclear: function(cm, params) {
vimApi.mapclear("insert");
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
nmapclear: function(cm, params) {
vimApi.mapclear("normal");
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
vmapclear: function(cm, params) {
vimApi.mapclear("visual");
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
omapclear: function(cm, params) {
vimApi.mapclear("operatorPending");
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
move: function(cm, params) {
commandDispatcher.processCommand(cm, cm.state.vim, {
keys: "",
type: "motion",
motion: "moveToLineOrEdgeOfDocument",
motionArgs: { forward: false, explicitRepeat: true, linewise: true },
repeatOverride: params.line + 1
});
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
set: function(cm, params) {
var setArgs = params.args;
var setCfg = params.setCfg || {};
if (!setArgs || setArgs.length < 1) {
if (cm) {
showConfirm(cm, "Invalid mapping: " + params.input);
}
return;
}
var expr = setArgs[0].split("=");
var optionName = expr.shift() || "";
var value = expr.length > 0 ? expr.join("=") : void 0;
var forceGet = false;
var forceToggle = false;
if (optionName.charAt(optionName.length - 1) == "?") {
if (value) {
throw Error("Trailing characters: " + params.argString);
}
optionName = optionName.substring(0, optionName.length - 1);
forceGet = true;
} else if (optionName.charAt(optionName.length - 1) == "!") {
optionName = optionName.substring(0, optionName.length - 1);
forceToggle = true;
}
if (value === void 0 && optionName.substring(0, 2) == "no") {
optionName = optionName.substring(2);
value = false;
}
var optionIsBoolean = options[optionName] && options[optionName].type == "boolean";
if (optionIsBoolean) {
if (forceToggle) {
value = !getOption(optionName, cm, setCfg);
} else if (value == void 0) {
value = true;
}
}
if (!optionIsBoolean && value === void 0 || forceGet) {
var oldValue = getOption(optionName, cm, setCfg);
if (oldValue instanceof Error) {
showConfirm(cm, oldValue.message);
} else if (oldValue === true || oldValue === false) {
showConfirm(cm, " " + (oldValue ? "" : "no") + optionName);
} else {
showConfirm(cm, " " + optionName + "=" + oldValue);
}
} else {
var setOptionReturn = setOption(optionName, value, cm, setCfg);
if (setOptionReturn instanceof Error) {
showConfirm(cm, setOptionReturn.message);
}
}
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
setlocal: function(cm, params) {
params.setCfg = { scope: "local" };
this.set(cm, params);
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
setglobal: function(cm, params) {
params.setCfg = { scope: "global" };
this.set(cm, params);
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
registers: function(cm, params) {
var regArgs = params.args;
var registers = vimGlobalState.registerController.registers;
var regInfo = "----------Registers----------\n\n";
if (!regArgs) {
for (var registerName in registers) {
var text = registers[registerName].toString();
if (text.length) {
regInfo += '"' + registerName + " " + text + "\n";
}
}
} else {
var registerNames = regArgs.join("");
for (var i = 0; i < registerNames.length; i++) {
var registerName = registerNames.charAt(i);
if (!vimGlobalState.registerController.isValidRegister(registerName)) {
continue;
}
var register = registers[registerName] || new Register();
regInfo += '"' + registerName + " " + register.toString() + "\n";
}
}
showConfirm(cm, regInfo, true);
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
marks: function(cm, params) {
var filterArgs = params.args;
var marks = cm.state.vim.marks;
var regInfo = "-----------Marks-----------\nmark line col\n\n";
if (!filterArgs) {
for (var name in marks) {
var marker = marks[name] && marks[name].find();
if (marker) {
regInfo += name + " " + marker.line + " " + marker.ch + "\n";
}
}
} else {
var registerNames = filterArgs.join("");
for (var i = 0; i < registerNames.length; i++) {
var name = registerNames.charAt(i);
var marker = marks[name] && marks[name].find();
if (marker) {
regInfo += name + " " + marker.line + " " + marker.ch + "\n";
}
}
}
showConfirm(cm, regInfo, true);
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
sort: function(cm, params) {
var reverse, ignoreCase, unique, number, pattern;
function parseArgs() {
if (params.argString) {
var args = new CM.StringStream(params.argString);
if (args.eat("!")) {
reverse = true;
}
if (args.eol()) {
return;
}
if (!args.eatSpace()) {
return "Invalid arguments";
}
var opts = args.match(/([dinuox]+)?\s*(\/.+\/)?\s*/);
if (!opts || !args.eol()) {
return "Invalid arguments";
}
if (opts[1]) {
ignoreCase = opts[1].indexOf("i") != -1;
unique = opts[1].indexOf("u") != -1;
var decimal = opts[1].indexOf("d") != -1 || opts[1].indexOf("n") != -1;
var hex = opts[1].indexOf("x") != -1;
var octal = opts[1].indexOf("o") != -1;
if (Number(decimal) + Number(hex) + Number(octal) > 1) {
return "Invalid arguments";
}
number = decimal && "decimal" || hex && "hex" || octal && "octal";
}
if (opts[2]) {
pattern = new RegExp(opts[2].substr(1, opts[2].length - 2), ignoreCase ? "i" : "");
}
}
}
var err = parseArgs();
if (err) {
showConfirm(cm, err + ": " + params.argString);
return;
}
var lineStart = params.line || cm.firstLine();
var lineEnd = params.lineEnd || params.line || cm.lastLine();
if (lineStart == lineEnd) {
return;
}
var curStart = new Pos2(lineStart, 0);
var curEnd = new Pos2(lineEnd, lineLength(cm, lineEnd));
var text = cm.getRange(curStart, curEnd).split("\n");
var numberRegex2 = number == "decimal" ? /(-?)([\d]+)/ : number == "hex" ? /(-?)(?:0x)?([0-9a-f]+)/i : number == "octal" ? /([0-7]+)/ : null;
var radix = number == "decimal" ? 10 : number == "hex" ? 16 : number == "octal" ? 8 : void 0;
var numPart = [], textPart = [];
if (number || pattern) {
for (var i = 0; i < text.length; i++) {
var matchPart = pattern ? text[i].match(pattern) : null;
if (matchPart && matchPart[0] != "") {
numPart.push(matchPart);
} else if (numberRegex2 && numberRegex2.exec(text[i])) {
numPart.push(text[i]);
} else {
textPart.push(text[i]);
}
}
} else {
textPart = text;
}
function compareFn(a, b) {
if (reverse) {
var tmp;
tmp = a;
a = b;
b = tmp;
}
if (ignoreCase) {
a = a.toLowerCase();
b = b.toLowerCase();
}
var amatch = numberRegex2 && numberRegex2.exec(a);
var bmatch = numberRegex2 && numberRegex2.exec(b);
if (!amatch || !bmatch) {
return a < b ? -1 : 1;
}
var anum = parseInt((amatch[1] + amatch[2]).toLowerCase(), radix);
var bnum = parseInt((bmatch[1] + bmatch[2]).toLowerCase(), radix);
return anum - bnum;
}
function comparePatternFn(a, b) {
if (reverse) {
var tmp;
tmp = a;
a = b;
b = tmp;
}
if (ignoreCase) {
a[0] = a[0].toLowerCase();
b[0] = b[0].toLowerCase();
}
return a[0] < b[0] ? -1 : 1;
}
numPart.sort(pattern ? comparePatternFn : compareFn);
if (pattern) {
for (var i = 0; i < numPart.length; i++) {
numPart[i] = numPart[i].input;
}
} else if (!number) {
textPart.sort(compareFn);
}
text = !reverse ? textPart.concat(numPart) : numPart.concat(textPart);
if (unique) {
var textOld = text;
var lastLine;
text = [];
for (var i = 0; i < textOld.length; i++) {
if (textOld[i] != lastLine) {
text.push(textOld[i]);
}
lastLine = textOld[i];
}
}
cm.replaceRange(text.join("\n"), curStart, curEnd);
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
vglobal: function(cm, params) {
this.global(cm, params);
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
normal: function(cm, params) {
var noremap2 = false;
var argString = params.argString;
if (argString && argString[0] == "!") {
argString = argString.slice(1);
noremap2 = true;
}
argString = argString.trimStart();
if (!argString) {
showConfirm(cm, "Argument is required.");
return;
}
var line = params.line;
if (typeof line == "number") {
var lineEnd = isNaN(params.lineEnd) ? line : params.lineEnd;
for (var i = line; i <= lineEnd; i++) {
cm.setCursor(i, 0);
doKeyToKey(cm, params.argString.trimStart(), { noremap: noremap2 });
if (cm.state.vim.insertMode) {
exitInsertMode(cm, true);
}
}
} else {
doKeyToKey(cm, params.argString.trimStart(), { noremap: noremap2 });
if (cm.state.vim.insertMode) {
exitInsertMode(cm, true);
}
}
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
global: function(cm, params) {
var argString = params.argString;
if (!argString) {
showConfirm(cm, "Regular Expression missing from global");
return;
}
var inverted = params.commandName[0] === "v";
if (argString[0] === "!" && params.commandName[0] === "g") {
inverted = true;
argString = argString.slice(1);
}
var lineStart = params.line !== void 0 ? params.line : cm.firstLine();
var lineEnd = params.lineEnd || params.line || cm.lastLine();
var tokens = splitBySlash(argString);
var regexPart = argString, cmd = "";
if (tokens && tokens.length) {
regexPart = tokens[0];
cmd = tokens.slice(1, tokens.length).join("/");
}
if (regexPart) {
try {
updateSearchQuery(
cm,
regexPart,
true,
true
/** smartCase */
);
} catch (e) {
showConfirm(cm, "Invalid regex: " + regexPart);
return;
}
}
var query = getSearchState(cm).getQuery();
var matchedLines = [];
for (var i = lineStart; i <= lineEnd; i++) {
var line = cm.getLine(i);
var matched = query.test(line);
if (matched !== inverted) {
matchedLines.push(cmd ? cm.getLineHandle(i) : line);
}
}
if (!cmd) {
showConfirm(cm, matchedLines.join("\n"));
return;
}
var index = 0;
var nextCommand = function() {
if (index < matchedLines.length) {
var lineHandle = matchedLines[index++];
var lineNum = cm.getLineNumber(lineHandle);
if (lineNum == null) {
nextCommand();
return;
}
var command = lineNum + 1 + cmd;
exCommandDispatcher.processCommand(cm, command, {
callback: nextCommand
});
} else if (cm.releaseLineHandles) {
cm.releaseLineHandles();
}
};
nextCommand();
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
substitute: function(cm, params) {
if (!cm.getSearchCursor) {
throw new Error("Search feature not available. Requires searchcursor.js or any other getSearchCursor implementation.");
}
var argString = params.argString;
var tokens = argString ? splitBySeparator(argString, argString[0]) : [];
var regexPart = "", replacePart = "", trailing, flagsPart, count;
var confirm = false;
var global = false;
if (tokens && tokens.length) {
regexPart = tokens[0];
if (getOption("pcre") && regexPart !== "") {
regexPart = new RegExp(regexPart).source;
}
replacePart = tokens[1];
if (replacePart !== void 0) {
if (getOption("pcre")) {
replacePart = unescapeRegexReplace(replacePart.replace(/([^\\])&/g, "$1$$&"));
} else {
replacePart = translateRegexReplace(replacePart);
}
vimGlobalState.lastSubstituteReplacePart = replacePart;
}
trailing = tokens[2] ? tokens[2].split(" ") : [];
} else {
if (argString && argString.length) {
showConfirm(cm, "Substitutions should be of the form :s/pattern/replace/");
return;
}
}
if (trailing) {
flagsPart = trailing[0];
count = parseInt(trailing[1]);
if (flagsPart) {
if (flagsPart.indexOf("c") != -1) {
confirm = true;
}
if (flagsPart.indexOf("g") != -1) {
global = true;
}
if (getOption("pcre")) {
regexPart = regexPart + "/" + flagsPart;
} else {
regexPart = regexPart.replace(/\//g, "\\/") + "/" + flagsPart;
}
}
}
if (regexPart) {
try {
updateSearchQuery(
cm,
regexPart,
true,
true
/** smartCase */
);
} catch (e) {
showConfirm(cm, "Invalid regex: " + regexPart);
return;
}
}
replacePart = replacePart || vimGlobalState.lastSubstituteReplacePart;
if (replacePart === void 0) {
showConfirm(cm, "No previous substitute regular expression");
return;
}
var state = getSearchState(cm);
var query = state.getQuery();
var lineStart = params.line !== void 0 ? params.line : cm.getCursor().line;
var lineEnd = params.lineEnd || lineStart;
if (lineStart == cm.firstLine() && lineEnd == cm.lastLine()) {
lineEnd = Infinity;
}
if (count) {
lineStart = lineEnd;
lineEnd = lineStart + count - 1;
}
var startPos = clipCursorToContent(cm, new Pos2(lineStart, 0));
var cursor = cm.getSearchCursor(query, startPos);
doReplace(cm, confirm, global, lineStart, lineEnd, cursor, query, replacePart, params.callback);
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
startinsert: function(cm, params) {
doKeyToKey(cm, params.argString == "!" ? "A" : "i", {});
},
redo: CM.commands.redo,
undo: CM.commands.undo,
/** @arg {CodeMirrorV} cm */
write: function(cm) {
if (CM.commands.save) {
CM.commands.save(cm);
} else if (cm.save) {
cm.save();
}
},
/** @arg {CodeMirrorV} cm */
nohlsearch: function(cm) {
clearSearchHighlight(cm);
},
/** @arg {CodeMirrorV} cm */
yank: function(cm) {
var cur2 = copyCursor(cm.getCursor());
var line = cur2.line;
var lineText = cm.getLine(line);
vimGlobalState.registerController.pushText(
"0",
"yank",
lineText,
true,
true
);
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
delete: function(cm, params) {
var line = params.selectionLine;
var lineEnd = isNaN(params.selectionLineEnd) ? line : params.selectionLineEnd;
operators.delete(cm, { linewise: true }, [
{
anchor: new Pos2(line, 0),
head: new Pos2(lineEnd + 1, 0)
}
]);
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
join: function(cm, params) {
var line = params.selectionLine;
var lineEnd = isNaN(params.selectionLineEnd) ? line : params.selectionLineEnd;
cm.setCursor(new Pos2(line, 0));
actions.joinLines(cm, { repeat: lineEnd - line }, cm.state.vim);
},
/** @arg {CodeMirrorV} cm @arg {ExParams} params*/
delmarks: function(cm, params) {
if (!params.argString || !trim(params.argString)) {
showConfirm(cm, "Argument required");
return;
}
var state = cm.state.vim;
var stream = new CM.StringStream(trim(params.argString));
while (!stream.eol()) {
stream.eatSpace();
var count = stream.pos;
if (!stream.match(/[a-zA-Z]/, false)) {
showConfirm(cm, "Invalid argument: " + params.argString.substring(count));
return;
}
var sym = stream.next();
if (stream.match("-", true)) {
if (!stream.match(/[a-zA-Z]/, false)) {
showConfirm(cm, "Invalid argument: " + params.argString.substring(count));
return;
}
var startMark = sym;
var finishMark = stream.next();
if (startMark && finishMark && isLowerCase(startMark) == isLowerCase(finishMark)) {
var start = startMark.charCodeAt(0);
var finish = finishMark.charCodeAt(0);
if (start >= finish) {
showConfirm(cm, "Invalid argument: " + params.argString.substring(count));
return;
}
for (var j = 0; j <= finish - start; j++) {
var mark = String.fromCharCode(start + j);
delete state.marks[mark];
}
} else {
showConfirm(cm, "Invalid argument: " + startMark + "-");
return;
}
} else if (sym) {
delete state.marks[sym];
}
}
}
};
var exCommandDispatcher = new ExCommandDispatcher();
vimApi.defineEx("version", "ve", (cm) => {
showConfirm(cm, "Codemirror-vim version: 6.3.0");
});
function doReplace(cm, confirm, global, lineStart, lineEnd, searchCursor, query, replaceWith, callback) {
cm.state.vim.exMode = true;
var done = false;
var matches = 0;
var lastPos;
var modifiedLineNumber;
var joined;
function replaceAll() {
cm.operation(function() {
while (!done) {
replace();
next();
}
stop();
});
}
function replace() {
var newText = "";
var match = searchCursor.match || searchCursor.pos && searchCursor.pos.match;
if (match) {
newText = replaceWith.replace(/\$(\d{1,3}|[$&])/g, function(_, x) {
if (x == "$") return "$";
if (x == "&") return match[0];
var x1 = x;
while (parseInt(x1) >= match.length && x1.length > 0) {
x1 = x1.slice(0, x1.length - 1);
}
if (x1) return match[x1] + x.slice(x1.length, x.length);
return _;
});
} else {
var text = cm.getRange(searchCursor.from(), searchCursor.to());
newText = text.replace(query, replaceWith);
}
var unmodifiedLineNumber = searchCursor.to().line;
searchCursor.replace(newText);
modifiedLineNumber = searchCursor.to().line;
lineEnd += modifiedLineNumber - unmodifiedLineNumber;
joined = modifiedLineNumber < unmodifiedLineNumber;
}
function findNextValidMatch() {
var lastMatchTo = lastPos && copyCursor(searchCursor.to());
var match = searchCursor.findNext();
if (match && !match[0] && lastMatchTo && cursorEqual(searchCursor.from(), lastMatchTo)) {
match = searchCursor.findNext();
}
if (match) matches++;
return match;
}
function next() {
while (findNextValidMatch() && isInRange(searchCursor.from(), lineStart, lineEnd)) {
if (!global && searchCursor.from().line == modifiedLineNumber && !joined) {
continue;
}
cm.scrollIntoView(searchCursor.from(), 30);
cm.setSelection(searchCursor.from(), searchCursor.to());
lastPos = searchCursor.from();
done = false;
return;
}
done = true;
}
function stop(close) {
if (close) {
close();
}
cm.focus();
if (lastPos) {
cm.setCursor(lastPos);
var vim2 = cm.state.vim;
vim2.exMode = false;
vim2.lastHPos = vim2.lastHSPos = lastPos.ch;
}
if (callback) {
callback();
} else if (done) {
showConfirm(
cm,
(matches ? "Found " + matches + " matches" : "No matches found") + " for pattern: " + query + (getOption("pcre") ? " (set nopcre to use Vim regexps)" : "")
);
}
}
function onPromptKeyDown(e, _value, close) {
CM.e_stop(e);
var keyName = vimKeyFromEvent(e);
switch (keyName) {
case "y":
replace();
next();
break;
case "n":
next();
break;
case "a":
var savedCallback = callback;
callback = void 0;
cm.operation(replaceAll);
callback = savedCallback;
break;
case "l":
replace();
// fall through and exit.
case "q":
case "<Esc>":
case "<C-c>":
case "<C-[>":
stop(close);
break;
}
if (done) {
stop(close);
}
return true;
}
next();
if (done) {
showConfirm(cm, "No matches for " + query + (getOption("pcre") ? " (set nopcre to use vim regexps)" : ""));
return;
}
if (!confirm) {
replaceAll();
if (callback) {
callback();
}
return;
}
showPrompt(cm, {
prefix: dom("span", "replace with ", dom("strong", replaceWith), " (y/n/a/q/l)"),
onKeyDown: onPromptKeyDown
});
}
function exitInsertMode(cm, keepCursor) {
var vim2 = cm.state.vim;
var macroModeState = vimGlobalState.macroModeState;
var insertModeChangeRegister = vimGlobalState.registerController.getRegister(".");
var isPlaying = macroModeState.isPlaying;
var lastChange = macroModeState.lastInsertModeChanges;
if (!isPlaying) {
cm.off("change", onChange);
if (vim2.insertEnd) vim2.insertEnd.clear();
vim2.insertEnd = void 0;
CM.off(cm.getInputField(), "keydown", onKeyEventTargetKeyDown);
}
if (!isPlaying && vim2.insertModeRepeat && vim2.insertModeRepeat > 1) {
repeatLastEdit(
cm,
vim2,
vim2.insertModeRepeat - 1,
true
/** repeatForInsert */
);
vim2.lastEditInputState.repeatOverride = vim2.insertModeRepeat;
}
delete vim2.insertModeRepeat;
vim2.insertMode = false;
if (!keepCursor) {
cm.setCursor(cm.getCursor().line, cm.getCursor().ch - 1);
}
cm.setOption("keyMap", "vim");
cm.setOption("disableInput", true);
cm.toggleOverwrite(false);
insertModeChangeRegister.setText(lastChange.changes.join(""));
CM.signal(cm, "vim-mode-change", { mode: "normal" });
if (macroModeState.isRecording) {
logInsertModeChange(macroModeState);
}
}
function _mapCommand(command) {
defaultKeymap2.unshift(command);
if (command.keys) addUsedKeys(command.keys);
}
function addUsedKeys(keys2) {
keys2.split(/(<(?:[CSMA]-)*\w+>|.)/i).forEach(function(part) {
if (part) {
if (!usedKeys[part]) usedKeys[part] = 0;
usedKeys[part]++;
}
});
}
function removeUsedKeys(keys2) {
keys2.split(/(<(?:[CSMA]-)*\w+>|.)/i).forEach(function(part) {
if (usedKeys[part])
usedKeys[part]--;
});
}
function mapCommand(keys2, type, name, args, extra) {
var command = { keys: keys2, type };
command[type] = name;
command[type + "Args"] = args;
for (var key in extra)
command[key] = extra[key];
_mapCommand(command);
}
defineOption("insertModeEscKeysTimeout", 200, "number");
function executeMacroRegister(cm, vim2, macroModeState, registerName) {
var register = vimGlobalState.registerController.getRegister(registerName);
if (registerName == ":") {
if (register.keyBuffer[0]) {
exCommandDispatcher.processCommand(cm, register.keyBuffer[0]);
}
macroModeState.isPlaying = false;
return;
}
var keyBuffer = register.keyBuffer;
var imc = 0;
macroModeState.isPlaying = true;
macroModeState.replaySearchQueries = register.searchQueries.slice(0);
for (var i = 0; i < keyBuffer.length; i++) {
var text = keyBuffer[i];
var match, key;
var keyRe = /<(?:[CSMA]-)*\w+>|./gi;
while (match = keyRe.exec(text)) {
key = match[0];
vimApi.handleKey(cm, key, "macro");
if (vim2.insertMode) {
var changes = register.insertModeChanges[imc++].changes;
vimGlobalState.macroModeState.lastInsertModeChanges.changes = changes;
repeatInsertModeChanges(cm, changes, 1);
exitInsertMode(cm);
}
}
}
macroModeState.isPlaying = false;
}
function logKey(macroModeState, key) {
if (macroModeState.isPlaying) {
return;
}
var registerName = macroModeState.latestRegister;
var register = vimGlobalState.registerController.getRegister(registerName);
if (register) {
register.pushText(key);
}
}
function logInsertModeChange(macroModeState) {
if (macroModeState.isPlaying) {
return;
}
var registerName = macroModeState.latestRegister;
var register = vimGlobalState.registerController.getRegister(registerName);
if (register && register.pushInsertModeChanges) {
register.pushInsertModeChanges(macroModeState.lastInsertModeChanges);
}
}
function logSearchQuery(macroModeState, query) {
if (macroModeState.isPlaying) {
return;
}
var registerName = macroModeState.latestRegister;
var register = vimGlobalState.registerController.getRegister(registerName);
if (register && register.pushSearchQuery) {
register.pushSearchQuery(query);
}
}
function onChange(cm, changeObj) {
var macroModeState = vimGlobalState.macroModeState;
var lastChange = macroModeState.lastInsertModeChanges;
if (!macroModeState.isPlaying) {
var vim2 = cm.state.vim;
while (changeObj) {
lastChange.expectCursorActivityForChange = true;
if (lastChange.ignoreCount > 1) {
lastChange.ignoreCount--;
} else if (changeObj.origin == "+input" || changeObj.origin == "paste" || changeObj.origin === void 0) {
var selectionCount = cm.listSelections().length;
if (selectionCount > 1)
lastChange.ignoreCount = selectionCount;
var text = changeObj.text.join("\n");
if (lastChange.maybeReset) {
lastChange.changes = [];
lastChange.maybeReset = false;
}
if (text) {
if (cm.state.overwrite && !/\n/.test(text)) {
lastChange.changes.push([text]);
} else {
if (text.length > 1) {
var insertEnd = vim2 && vim2.insertEnd && vim2.insertEnd.find();
var cursor = cm.getCursor();
if (insertEnd && insertEnd.line == cursor.line) {
var offset = insertEnd.ch - cursor.ch;
if (offset > 0 && offset < text.length) {
lastChange.changes.push([text, offset]);
text = "";
}
}
}
if (text) lastChange.changes.push(text);
}
}
}
changeObj = changeObj.next;
}
}
}
function onCursorActivity(cm) {
var _a;
var vim2 = cm.state.vim;
if (vim2.insertMode) {
var macroModeState = vimGlobalState.macroModeState;
if (macroModeState.isPlaying) {
return;
}
var lastChange = macroModeState.lastInsertModeChanges;
if (lastChange.expectCursorActivityForChange) {
lastChange.expectCursorActivityForChange = false;
} else {
lastChange.maybeReset = true;
if (vim2.insertEnd) vim2.insertEnd.clear();
vim2.insertEnd = cm.setBookmark(cm.getCursor(), { insertLeft: true });
}
} else if (!((_a = cm.curOp) == null ? void 0 : _a.isVimOp)) {
handleExternalSelection(cm, vim2);
}
}
function handleExternalSelection(cm, vim2) {
var anchor = cm.getCursor("anchor");
var head = cm.getCursor("head");
if (vim2.visualMode && !cm.somethingSelected()) {
exitVisualMode(cm, false);
} else if (!vim2.visualMode && !vim2.insertMode && cm.somethingSelected()) {
vim2.visualMode = true;
vim2.visualLine = false;
CM.signal(cm, "vim-mode-change", { mode: "visual" });
}
if (vim2.visualMode) {
var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0;
var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0;
head = offsetCursor(head, 0, headOffset);
anchor = offsetCursor(anchor, 0, anchorOffset);
vim2.sel = {
anchor,
head
};
updateMark(cm, vim2, "<", cursorMin(head, anchor));
updateMark(cm, vim2, ">", cursorMax(head, anchor));
} else if (!vim2.insertMode) {
vim2.lastHPos = cm.getCursor().ch;
}
}
function onKeyEventTargetKeyDown(e) {
var macroModeState = vimGlobalState.macroModeState;
var lastChange = macroModeState.lastInsertModeChanges;
var keyName = CM.keyName ? CM.keyName(e) : e.key;
if (!keyName) {
return;
}
if (keyName.indexOf("Delete") != -1 || keyName.indexOf("Backspace") != -1) {
if (lastChange.maybeReset) {
lastChange.changes = [];
lastChange.maybeReset = false;
}
lastChange.changes.push(new InsertModeKey(keyName, e));
}
}
function repeatLastEdit(cm, vim2, repeat, repeatForInsert) {
var macroModeState = vimGlobalState.macroModeState;
macroModeState.isPlaying = true;
var lastAction = vim2.lastEditActionCommand;
var cachedInputState = vim2.inputState;
function repeatCommand() {
if (lastAction) {
commandDispatcher.processAction(cm, vim2, lastAction);
} else {
commandDispatcher.evalInput(cm, vim2);
}
}
function repeatInsert(repeat2) {
if (macroModeState.lastInsertModeChanges.changes.length > 0) {
repeat2 = !vim2.lastEditActionCommand ? 1 : repeat2;
var changeObject = macroModeState.lastInsertModeChanges;
repeatInsertModeChanges(cm, changeObject.changes, repeat2);
}
}
vim2.inputState = vim2.lastEditInputState;
if (lastAction && lastAction.interlaceInsertRepeat) {
for (var i = 0; i < repeat; i++) {
repeatCommand();
repeatInsert(1);
}
} else {
if (!repeatForInsert) {
repeatCommand();
}
repeatInsert(repeat);
}
vim2.inputState = cachedInputState;
if (vim2.insertMode && !repeatForInsert) {
exitInsertMode(cm);
}
macroModeState.isPlaying = false;
}
function sendCmKey(cm, key) {
CM.lookupKey(key, "vim-insert", function keyHandler(binding) {
if (typeof binding == "string") {
CM.commands[binding](cm);
} else {
binding(cm);
}
return true;
});
}
function repeatInsertModeChanges(cm, changes, repeat) {
var head = cm.getCursor("head");
var visualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.visualBlock;
if (visualBlock) {
selectForInsert(cm, head, visualBlock + 1);
repeat = cm.listSelections().length;
cm.setCursor(head);
}
for (var i = 0; i < repeat; i++) {
if (visualBlock) {
cm.setCursor(offsetCursor(head, i, 0));
}
for (var j = 0; j < changes.length; j++) {
var change = changes[j];
if (change instanceof InsertModeKey) {
sendCmKey(cm, change.keyName);
} else if (typeof change == "string") {
cm.replaceSelection(change);
} else {
var start = cm.getCursor();
var end = offsetCursor(start, 0, change[0].length - (change[1] || 0));
cm.replaceRange(change[0], start, change[1] ? start : end);
cm.setCursor(end);
}
}
}
if (visualBlock) {
cm.setCursor(offsetCursor(head, 0, 1));
}
}
function cloneVimState(state) {
var n = new state.constructor();
Object.keys(state).forEach(function(key) {
if (key == "insertEnd") return;
var o = state[key];
if (Array.isArray(o))
o = o.slice();
else if (o && typeof o == "object" && o.constructor != Object)
o = cloneVimState(o);
n[key] = o;
});
if (state.sel) {
n.sel = {
head: state.sel.head && copyCursor(state.sel.head),
anchor: state.sel.anchor && copyCursor(state.sel.anchor)
};
}
return n;
}
function multiSelectHandleKey(cm_, key, origin) {
var vim2 = maybeInitVimState(cm_);
var cm = (
/**@type {CodeMirrorV}*/
cm_
);
var isHandled = false;
var vim2 = vimApi.maybeInitVimState_(cm);
var visualBlock = vim2.visualBlock || vim2.wasInVisualBlock;
if (cm.state.closeVimNotification) {
var close = cm.state.closeVimNotification;
cm.state.closeVimNotification = null;
close();
if (key == "<CR>") {
clearInputState(cm);
return true;
}
}
var wasMultiselect = cm.isInMultiSelectMode();
if (vim2.wasInVisualBlock && !wasMultiselect) {
vim2.wasInVisualBlock = false;
} else if (wasMultiselect && vim2.visualBlock) {
vim2.wasInVisualBlock = true;
}
if (key == "<Esc>" && !vim2.insertMode && !vim2.visualMode && wasMultiselect && vim2.status == "<Esc>") {
clearInputState(cm);
} else if (visualBlock || !wasMultiselect || cm.inVirtualSelectionMode) {
isHandled = vimApi.handleKey(cm, key, origin);
} else {
var old = cloneVimState(vim2);
var changeQueueList = vim2.inputState.changeQueueList || [];
cm.operation(function() {
var _a;
if (cm.curOp)
cm.curOp.isVimOp = true;
var index = 0;
cm.forEachSelection(function() {
cm.state.vim.inputState.changeQueue = changeQueueList[index];
var head = cm.getCursor("head");
var anchor = cm.getCursor("anchor");
var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0;
var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0;
head = offsetCursor(head, 0, headOffset);
anchor = offsetCursor(anchor, 0, anchorOffset);
cm.state.vim.sel.head = head;
cm.state.vim.sel.anchor = anchor;
isHandled = vimApi.handleKey(cm, key, origin);
if (cm.virtualSelection) {
changeQueueList[index] = cm.state.vim.inputState.changeQueue;
cm.state.vim = cloneVimState(old);
}
index++;
});
if (((_a = cm.curOp) == null ? void 0 : _a.cursorActivity) && !isHandled)
cm.curOp.cursorActivity = false;
cm.state.vim = vim2;
vim2.inputState.changeQueueList = changeQueueList;
vim2.inputState.changeQueue = null;
}, true);
}
if (isHandled && !vim2.visualMode && !vim2.insertMode && vim2.visualMode != cm.somethingSelected()) {
handleExternalSelection(cm, vim2);
}
return isHandled;
}
resetVimGlobalState();
return vimApi;
}
function indexFromPos(doc, pos) {
var ch = pos.ch;
var lineNumber = pos.line + 1;
if (lineNumber < 1) {
lineNumber = 1;
ch = 0;
}
if (lineNumber > doc.lines) {
lineNumber = doc.lines;
ch = Number.MAX_VALUE;
}
var line = doc.line(lineNumber);
return Math.min(line.from + Math.max(0, ch), line.to);
}
function posFromIndex(doc, offset) {
let line = doc.lineAt(offset);
return { line: line.number - 1, ch: offset - line.from };
}
var Pos = class {
constructor(line, ch) {
this.line = line;
this.ch = ch;
}
};
function on(emitter, type, f) {
if (emitter.addEventListener) {
emitter.addEventListener(type, f, false);
} else {
var map = emitter._handlers || (emitter._handlers = {});
map[type] = (map[type] || []).concat(f);
}
}
function off(emitter, type, f) {
if (emitter.removeEventListener) {
emitter.removeEventListener(type, f, false);
} else {
var map = emitter._handlers, arr = map && map[type];
if (arr) {
var index = arr.indexOf(f);
if (index > -1) {
map[type] = arr.slice(0, index).concat(arr.slice(index + 1));
}
}
}
}
function signal(emitter, type, ...args) {
var _a;
var handlers = (_a = emitter._handlers) === null || _a === void 0 ? void 0 : _a[type];
if (!handlers)
return;
for (var i = 0; i < handlers.length; ++i) {
handlers[i](...args);
}
}
function signalTo(handlers, ...args) {
if (!handlers)
return;
for (var i = 0; i < handlers.length; ++i) {
handlers[i](...args);
}
}
var wordChar;
try {
wordChar = /* @__PURE__ */ new RegExp("[\\w\\p{Alphabetic}\\p{Number}_]", "u");
} catch (_) {
wordChar = /[\w]/;
}
function dispatchChange(cm, transaction) {
var view = cm.cm6;
if (view.state.readOnly)
return;
var type = "input.type.compose";
if (cm.curOp) {
if (!cm.curOp.lastChange)
type = "input.type.compose.start";
}
if (transaction.annotations) {
try {
transaction.annotations.some(function(note) {
if (note.value == "input")
note.value = type;
});
} catch (e) {
console.error(e);
}
} else {
transaction.userEvent = type;
}
return view.dispatch(transaction);
}
function runHistoryCommand(cm, revert) {
var _a;
if (cm.curOp) {
cm.curOp.$changeStart = void 0;
}
(revert ? import_commands.undo : import_commands.redo)(cm.cm6);
let changeStartIndex = (_a = cm.curOp) === null || _a === void 0 ? void 0 : _a.$changeStart;
if (changeStartIndex != null) {
cm.cm6.dispatch({ selection: { anchor: changeStartIndex } });
}
}
var keys = {
Left: (cm) => (0, import_view.runScopeHandlers)(cm.cm6, { key: "Left" }, "editor"),
Right: (cm) => (0, import_view.runScopeHandlers)(cm.cm6, { key: "Right" }, "editor"),
Up: (cm) => (0, import_view.runScopeHandlers)(cm.cm6, { key: "Up" }, "editor"),
Down: (cm) => (0, import_view.runScopeHandlers)(cm.cm6, { key: "Down" }, "editor"),
Backspace: (cm) => (0, import_view.runScopeHandlers)(cm.cm6, { key: "Backspace" }, "editor"),
Delete: (cm) => (0, import_view.runScopeHandlers)(cm.cm6, { key: "Delete" }, "editor")
};
var CodeMirror = class _CodeMirror {
// --------------------------
openDialog(template, callback, options) {
return openDialog(this, template, callback, options);
}
openNotification(template, options) {
return openNotification(this, template, options);
}
constructor(cm6) {
this.state = {};
this.marks = /* @__PURE__ */ Object.create(null);
this.$mid = 0;
this.options = {};
this._handlers = {};
this.$lastChangeEndOffset = 0;
this.virtualSelection = null;
this.cm6 = cm6;
this.onChange = this.onChange.bind(this);
this.onSelectionChange = this.onSelectionChange.bind(this);
}
on(type, f) {
on(this, type, f);
}
off(type, f) {
off(this, type, f);
}
signal(type, e, handlers) {
signal(this, type, e, handlers);
}
indexFromPos(pos) {
return indexFromPos(this.cm6.state.doc, pos);
}
posFromIndex(offset) {
return posFromIndex(this.cm6.state.doc, offset);
}
foldCode(pos) {
let view = this.cm6;
let ranges = view.state.selection.ranges;
let doc = this.cm6.state.doc;
let index = indexFromPos(doc, pos);
let tmpRanges = import_state.EditorSelection.create([import_state.EditorSelection.range(index, index)], 0).ranges;
view.state.selection.ranges = tmpRanges;
(0, import_language.foldCode)(view);
view.state.selection.ranges = ranges;
}
firstLine() {
return 0;
}
lastLine() {
return this.cm6.state.doc.lines - 1;
}
lineCount() {
return this.cm6.state.doc.lines;
}
setCursor(line, ch) {
if (typeof line === "object") {
ch = line.ch;
line = line.line;
}
var offset = indexFromPos(this.cm6.state.doc, { line, ch: ch || 0 });
this.cm6.dispatch({ selection: { anchor: offset } }, { scrollIntoView: !this.curOp });
if (this.curOp && !this.curOp.isVimOp)
this.onBeforeEndOperation();
}
getCursor(p) {
var sel = this.cm6.state.selection.main;
var offset = p == "head" || !p ? sel.head : p == "anchor" ? sel.anchor : p == "start" ? sel.from : p == "end" ? sel.to : null;
if (offset == null)
throw new Error("Invalid cursor type");
return this.posFromIndex(offset);
}
listSelections() {
var doc = this.cm6.state.doc;
return this.cm6.state.selection.ranges.map((r) => {
return {
anchor: posFromIndex(doc, r.anchor),
head: posFromIndex(doc, r.head)
};
});
}
setSelections(p, primIndex) {
var doc = this.cm6.state.doc;
var ranges = p.map((x) => {
var head = indexFromPos(doc, x.head);
var anchor = indexFromPos(doc, x.anchor);
if (head == anchor)
return import_state.EditorSelection.cursor(head, 1);
return import_state.EditorSelection.range(anchor, head);
});
this.cm6.dispatch({
selection: import_state.EditorSelection.create(ranges, primIndex)
});
}
setSelection(anchor, head, options) {
this.setSelections([{ anchor, head }], 0);
if (options && options.origin == "*mouse") {
this.onBeforeEndOperation();
}
}
getLine(row) {
var doc = this.cm6.state.doc;
if (row < 0 || row >= doc.lines)
return "";
return this.cm6.state.doc.line(row + 1).text;
}
getLineHandle(row) {
if (!this.$lineHandleChanges)
this.$lineHandleChanges = [];
return { row, index: this.indexFromPos(new Pos(row, 0)) };
}
getLineNumber(handle) {
var updates = this.$lineHandleChanges;
if (!updates)
return null;
var offset = handle.index;
for (var i = 0; i < updates.length; i++) {
offset = updates[i].changes.mapPos(offset, 1, import_state.MapMode.TrackAfter);
if (offset == null)
return null;
}
var pos = this.posFromIndex(offset);
return pos.ch == 0 ? pos.line : null;
}
releaseLineHandles() {
this.$lineHandleChanges = void 0;
}
getRange(s, e) {
var doc = this.cm6.state.doc;
return this.cm6.state.sliceDoc(indexFromPos(doc, s), indexFromPos(doc, e));
}
replaceRange(text, s, e, source) {
if (!e)
e = s;
var doc = this.cm6.state.doc;
var from = indexFromPos(doc, s);
var to = indexFromPos(doc, e);
dispatchChange(this, { changes: { from, to, insert: text } });
}
replaceSelection(text) {
dispatchChange(this, this.cm6.state.replaceSelection(text));
}
replaceSelections(replacements) {
var ranges = this.cm6.state.selection.ranges;
var changes = ranges.map((r, i) => {
return { from: r.from, to: r.to, insert: replacements[i] || "" };
});
dispatchChange(this, { changes });
}
getSelection() {
return this.getSelections().join("\n");
}
getSelections() {
var cm = this.cm6;
return cm.state.selection.ranges.map((r) => cm.state.sliceDoc(r.from, r.to));
}
somethingSelected() {
return this.cm6.state.selection.ranges.some((r) => !r.empty);
}
getInputField() {
return this.cm6.contentDOM;
}
clipPos(p) {
var doc = this.cm6.state.doc;
var ch = p.ch;
var lineNumber = p.line + 1;
if (lineNumber < 1) {
lineNumber = 1;
ch = 0;
}
if (lineNumber > doc.lines) {
lineNumber = doc.lines;
ch = Number.MAX_VALUE;
}
var line = doc.line(lineNumber);
ch = Math.min(Math.max(0, ch), line.to - line.from);
return new Pos(lineNumber - 1, ch);
}
getValue() {
return this.cm6.state.doc.toString();
}
setValue(text) {
var cm = this.cm6;
return cm.dispatch({
changes: { from: 0, to: cm.state.doc.length, insert: text },
selection: import_state.EditorSelection.range(0, 0)
});
}
focus() {
return this.cm6.focus();
}
blur() {
return this.cm6.contentDOM.blur();
}
defaultTextHeight() {
return this.cm6.defaultLineHeight;
}
findMatchingBracket(pos, _options) {
var state = this.cm6.state;
var offset = indexFromPos(state.doc, pos);
var m = (0, import_language.matchBrackets)(state, offset + 1, -1);
if (m && m.end) {
return { to: posFromIndex(state.doc, m.end.from) };
}
m = (0, import_language.matchBrackets)(state, offset, 1);
if (m && m.end) {
return { to: posFromIndex(state.doc, m.end.from) };
}
return { to: void 0 };
}
scanForBracket(pos, dir, style, config3) {
return scanForBracket(this, pos, dir, style, config3);
}
indentLine(line, more) {
if (more)
this.indentMore();
else
this.indentLess();
}
indentMore() {
(0, import_commands.indentMore)(this.cm6);
}
indentLess() {
(0, import_commands.indentLess)(this.cm6);
}
execCommand(name) {
if (name == "indentAuto")
_CodeMirror.commands.indentAuto(this);
else if (name == "goLineLeft")
(0, import_commands.cursorLineBoundaryBackward)(this.cm6);
else if (name == "goLineRight") {
(0, import_commands.cursorLineBoundaryForward)(this.cm6);
let state = this.cm6.state;
let cur2 = state.selection.main.head;
if (cur2 < state.doc.length && state.sliceDoc(cur2, cur2 + 1) !== "\n") {
(0, import_commands.cursorCharBackward)(this.cm6);
}
} else
console.log(name + " is not implemented");
}
setBookmark(cursor, options) {
var assoc = (options === null || options === void 0 ? void 0 : options.insertLeft) ? 1 : -1;
var offset = this.indexFromPos(cursor);
var bm = new Marker(this, offset, assoc);
return bm;
}
addOverlay({ query }) {
let cm6Query = new import_search.SearchQuery({
regexp: true,
search: query.source,
caseSensitive: !/i/.test(query.flags)
});
if (cm6Query.valid) {
cm6Query.forVim = true;
this.cm6Query = cm6Query;
let effect = import_search.setSearchQuery.of(cm6Query);
this.cm6.dispatch({ effects: effect });
return cm6Query;
}
}
removeOverlay(overlay) {
if (!this.cm6Query)
return;
this.cm6Query.forVim = false;
let effect = import_search.setSearchQuery.of(this.cm6Query);
this.cm6.dispatch({ effects: effect });
}
getSearchCursor(query, pos) {
var cm = this;
var last = null;
var lastCM5Result = null;
var afterEmptyMatch = false;
if (pos.ch == void 0)
pos.ch = Number.MAX_VALUE;
var firstOffset = indexFromPos(cm.cm6.state.doc, pos);
var source = query.source.replace(/(\\.|{(?:\d+(?:,\d*)?|,\d+)})|[{}]/g, function(a, b) {
if (!b)
return "\\" + a;
return b;
});
function rCursor(doc, from = 0, to = doc.length) {
return new import_search.RegExpCursor(doc, source, { ignoreCase: query.ignoreCase }, from, to);
}
function nextMatch(from) {
var doc = cm.cm6.state.doc;
if (from > doc.length)
return null;
let res = rCursor(doc, from).next();
return res.done ? null : res.value;
}
var ChunkSize = 1e4;
function prevMatchInRange(from, to) {
var doc = cm.cm6.state.doc;
for (let size = 1; ; size++) {
let start = Math.max(from, to - size * ChunkSize);
let cursor = rCursor(doc, start, to), range = null;
while (!cursor.next().done)
range = cursor.value;
if (range && (start == from || range.from > start + 10))
return range;
if (start == from)
return null;
}
}
return {
findNext: function() {
return this.find(false);
},
findPrevious: function() {
return this.find(true);
},
find: function(back) {
var doc = cm.cm6.state.doc;
if (back) {
let endAt = last ? afterEmptyMatch ? last.to - 1 : last.from : firstOffset;
last = prevMatchInRange(0, endAt);
} else {
let startFrom = last ? afterEmptyMatch ? last.to + 1 : last.to : firstOffset;
last = nextMatch(startFrom);
}
lastCM5Result = last && {
from: posFromIndex(doc, last.from),
to: posFromIndex(doc, last.to),
match: last.match
};
afterEmptyMatch = last ? last.from == last.to : false;
return last && last.match;
},
from: function() {
return lastCM5Result === null || lastCM5Result === void 0 ? void 0 : lastCM5Result.from;
},
to: function() {
return lastCM5Result === null || lastCM5Result === void 0 ? void 0 : lastCM5Result.to;
},
replace: function(text) {
if (last) {
dispatchChange(cm, {
changes: { from: last.from, to: last.to, insert: text }
});
last.to = last.from + text.length;
if (lastCM5Result) {
lastCM5Result.to = posFromIndex(cm.cm6.state.doc, last.to);
}
}
},
get match() {
return lastCM5Result && lastCM5Result.match;
}
};
}
findPosV(start, amount, unit, goalColumn) {
let { cm6 } = this;
const doc = cm6.state.doc;
let pixels = unit == "page" ? cm6.dom.clientHeight : 0;
const startOffset = indexFromPos(doc, start);
let range = import_state.EditorSelection.cursor(startOffset, 1, void 0, goalColumn);
let count = Math.round(Math.abs(amount));
for (let i = 0; i < count; i++) {
if (unit == "page") {
range = cm6.moveVertically(range, amount > 0, pixels);
} else if (unit == "line") {
range = cm6.moveVertically(range, amount > 0);
}
}
let pos = posFromIndex(doc, range.head);
if (amount < 0 && range.head == 0 && goalColumn != 0 && start.line == 0 && start.ch != 0 || amount > 0 && range.head == doc.length && pos.ch != goalColumn && start.line == pos.line) {
pos.hitSide = true;
}
return pos;
}
charCoords(pos, mode) {
var rect = this.cm6.contentDOM.getBoundingClientRect();
var offset = indexFromPos(this.cm6.state.doc, pos);
var coords = this.cm6.coordsAtPos(offset);
var d = -rect.top;
return { left: ((coords === null || coords === void 0 ? void 0 : coords.left) || 0) - rect.left, top: ((coords === null || coords === void 0 ? void 0 : coords.top) || 0) + d, bottom: ((coords === null || coords === void 0 ? void 0 : coords.bottom) || 0) + d };
}
coordsChar(coords, mode) {
var rect = this.cm6.contentDOM.getBoundingClientRect();
var offset = this.cm6.posAtCoords({ x: coords.left + rect.left, y: coords.top + rect.top }) || 0;
return posFromIndex(this.cm6.state.doc, offset);
}
getScrollInfo() {
var scroller = this.cm6.scrollDOM;
return {
left: scroller.scrollLeft,
top: scroller.scrollTop,
height: scroller.scrollHeight,
width: scroller.scrollWidth,
clientHeight: scroller.clientHeight,
clientWidth: scroller.clientWidth
};
}
scrollTo(x, y) {
if (x != null)
this.cm6.scrollDOM.scrollLeft = x;
if (y != null)
this.cm6.scrollDOM.scrollTop = y;
}
scrollIntoView(pos, margin) {
if (pos) {
var offset = this.indexFromPos(pos);
this.cm6.dispatch({
effects: import_view.EditorView.scrollIntoView(offset)
});
} else {
this.cm6.dispatch({ scrollIntoView: true, userEvent: "scroll" });
}
}
getWrapperElement() {
return this.cm6.dom;
}
// for tests
getMode() {
return { name: this.getOption("mode") };
}
setSize(w, h) {
this.cm6.dom.style.width = w + 4 + "px";
this.cm6.dom.style.height = h + "px";
this.refresh();
}
refresh() {
this.cm6.measure();
}
// event listeners
destroy() {
this.removeOverlay();
}
getLastEditEnd() {
return this.posFromIndex(this.$lastChangeEndOffset);
}
onChange(update) {
if (this.$lineHandleChanges) {
this.$lineHandleChanges.push(update);
}
for (let i in this.marks) {
let m = this.marks[i];
m.update(update.changes);
}
if (this.virtualSelection) {
this.virtualSelection.ranges = this.virtualSelection.ranges.map((range) => range.map(update.changes));
}
var curOp = this.curOp = this.curOp || {};
update.changes.iterChanges((fromA, toA, fromB, toB, text) => {
if (curOp.$changeStart == null || curOp.$changeStart > fromB)
curOp.$changeStart = fromB;
this.$lastChangeEndOffset = toB;
var change = { text: text.toJSON() };
if (!curOp.lastChange) {
curOp.lastChange = curOp.change = change;
} else {
curOp.lastChange.next = curOp.lastChange = change;
}
}, true);
if (!curOp.changeHandlers)
curOp.changeHandlers = this._handlers["change"] && this._handlers["change"].slice();
}
onSelectionChange() {
var curOp = this.curOp = this.curOp || {};
if (!curOp.cursorActivityHandlers)
curOp.cursorActivityHandlers = this._handlers["cursorActivity"] && this._handlers["cursorActivity"].slice();
this.curOp.cursorActivity = true;
}
operation(fn, force) {
if (!this.curOp)
this.curOp = { $d: 0 };
this.curOp.$d++;
try {
var result = fn();
} finally {
if (this.curOp) {
this.curOp.$d--;
if (!this.curOp.$d)
this.onBeforeEndOperation();
}
}
return result;
}
onBeforeEndOperation() {
var op = this.curOp;
var scrollIntoView2 = false;
if (op) {
if (op.change) {
signalTo(op.changeHandlers, this, op.change);
}
if (op && op.cursorActivity) {
signalTo(op.cursorActivityHandlers, this, null);
if (op.isVimOp)
scrollIntoView2 = true;
}
this.curOp = null;
}
if (scrollIntoView2)
this.scrollIntoView();
}
moveH(increment, unit) {
if (unit == "char") {
var cur2 = this.getCursor();
this.setCursor(cur2.line, cur2.ch + increment);
}
}
setOption(name, val) {
switch (name) {
case "keyMap":
this.state.keyMap = val;
break;
case "textwidth":
this.state.textwidth = val;
break;
}
}
getOption(name) {
switch (name) {
case "firstLineNumber":
return 1;
case "tabSize":
return this.cm6.state.tabSize || 4;
case "readOnly":
return this.cm6.state.readOnly;
case "indentWithTabs":
return this.cm6.state.facet(import_language.indentUnit) == " ";
// TODO
case "indentUnit":
return this.cm6.state.facet(import_language.indentUnit).length || 2;
case "textwidth":
return this.state.textwidth;
// for tests
case "keyMap":
return this.state.keyMap || "vim";
}
}
toggleOverwrite(on2) {
this.state.overwrite = on2;
}
getTokenTypeAt(pos) {
var _a;
var offset = this.indexFromPos(pos);
var tree = (0, import_language.ensureSyntaxTree)(this.cm6.state, offset);
var node = tree === null || tree === void 0 ? void 0 : tree.resolve(offset);
var type = ((_a = node === null || node === void 0 ? void 0 : node.type) === null || _a === void 0 ? void 0 : _a.name) || "";
if (/comment/i.test(type))
return "comment";
if (/string/i.test(type))
return "string";
return "";
}
overWriteSelection(text) {
var doc = this.cm6.state.doc;
var sel = this.cm6.state.selection;
var ranges = sel.ranges.map((x) => {
if (x.empty) {
var ch = x.to < doc.length ? doc.sliceString(x.from, x.to + 1) : "";
if (ch && !/\n/.test(ch))
return import_state.EditorSelection.range(x.from, x.to + 1);
}
return x;
});
this.cm6.dispatch({
selection: import_state.EditorSelection.create(ranges, sel.mainIndex)
});
this.replaceSelection(text);
}
/*** multiselect ****/
isInMultiSelectMode() {
return this.cm6.state.selection.ranges.length > 1;
}
virtualSelectionMode() {
return !!this.virtualSelection;
}
forEachSelection(command) {
var selection = this.cm6.state.selection;
this.virtualSelection = import_state.EditorSelection.create(selection.ranges, selection.mainIndex);
for (var i = 0; i < this.virtualSelection.ranges.length; i++) {
var range = this.virtualSelection.ranges[i];
if (!range)
continue;
this.cm6.dispatch({ selection: import_state.EditorSelection.create([range]) });
command();
this.virtualSelection.ranges[i] = this.cm6.state.selection.ranges[0];
}
this.cm6.dispatch({ selection: this.virtualSelection });
this.virtualSelection = null;
}
hardWrap(options) {
return hardWrap(this, options);
}
};
CodeMirror.isMac = typeof navigator != "undefined" && /* @__PURE__ */ /Mac/.test(navigator.platform);
CodeMirror.Pos = Pos;
CodeMirror.StringStream = import_language.StringStream;
CodeMirror.commands = {
cursorCharLeft: function(cm) {
(0, import_commands.cursorCharLeft)(cm.cm6);
},
redo: function(cm) {
runHistoryCommand(cm, false);
},
undo: function(cm) {
runHistoryCommand(cm, true);
},
newlineAndIndent: function(cm) {
(0, import_commands.insertNewlineAndIndent)({
state: cm.cm6.state,
dispatch: (tr) => {
return dispatchChange(cm, tr);
}
});
},
indentAuto: function(cm) {
(0, import_commands.indentSelection)(cm.cm6);
},
newlineAndIndentContinueComment: void 0,
save: void 0
};
CodeMirror.isWordChar = function(ch) {
return wordChar.test(ch);
};
CodeMirror.keys = keys;
CodeMirror.addClass = function(el, str) {
};
CodeMirror.rmClass = function(el, str) {
};
CodeMirror.e_preventDefault = function(e) {
e.preventDefault();
};
CodeMirror.e_stop = function(e) {
var _a, _b;
(_a = e === null || e === void 0 ? void 0 : e.stopPropagation) === null || _a === void 0 ? void 0 : _a.call(e);
(_b = e === null || e === void 0 ? void 0 : e.preventDefault) === null || _b === void 0 ? void 0 : _b.call(e);
};
CodeMirror.lookupKey = function lookupKey(key, map, handle) {
var result = CodeMirror.keys[key];
if (!result && /^Arrow/.test(key))
result = CodeMirror.keys[key.slice(5)];
if (result)
handle(result);
};
CodeMirror.on = on;
CodeMirror.off = off;
CodeMirror.signal = signal;
CodeMirror.findMatchingTag = findMatchingTag;
CodeMirror.findEnclosingTag = findEnclosingTag;
CodeMirror.keyName = void 0;
function dialogDiv(cm, template, bottom) {
var dialog = document.createElement("div");
dialog.appendChild(template);
return dialog;
}
function closeNotification(cm, newVal) {
if (cm.state.currentNotificationClose)
cm.state.currentNotificationClose();
cm.state.currentNotificationClose = newVal;
}
function openNotification(cm, template, options) {
closeNotification(cm, close);
var dialog = dialogDiv(cm, template, options && options.bottom);
var closed = false;
var doneTimer;
var duration = options && typeof options.duration !== "undefined" ? options.duration : 5e3;
function close() {
if (closed)
return;
closed = true;
clearTimeout(doneTimer);
dialog.remove();
hideDialog(cm, dialog);
}
dialog.onclick = function(e) {
e.preventDefault();
close();
};
showDialog(cm, dialog);
if (duration)
doneTimer = setTimeout(close, duration);
return close;
}
function showDialog(cm, dialog) {
var oldDialog = cm.state.dialog;
cm.state.dialog = dialog;
dialog.style.flex = "1";
if (dialog && oldDialog !== dialog) {
if (oldDialog && oldDialog.contains(document.activeElement))
cm.focus();
if (oldDialog && oldDialog.parentElement) {
oldDialog.parentElement.replaceChild(dialog, oldDialog);
} else if (oldDialog) {
oldDialog.remove();
}
CodeMirror.signal(cm, "dialog");
}
}
function hideDialog(cm, dialog) {
if (cm.state.dialog == dialog) {
cm.state.dialog = null;
CodeMirror.signal(cm, "dialog");
}
}
function openDialog(me, template, callback, options) {
if (!options)
options = {};
closeNotification(me, void 0);
var dialog = dialogDiv(me, template, options.bottom);
var closed = false;
showDialog(me, dialog);
function close(newVal) {
if (typeof newVal == "string") {
inp.value = newVal;
} else {
if (closed)
return;
closed = true;
hideDialog(me, dialog);
if (!me.state.dialog)
me.focus();
if (options.onClose)
options.onClose(dialog);
}
}
var inp = dialog.getElementsByTagName("input")[0];
if (inp) {
if (options.value) {
inp.value = options.value;
if (options.selectValueOnOpen !== false)
inp.select();
}
if (options.onInput)
CodeMirror.on(inp, "input", function(e) {
options.onInput(e, inp.value, close);
});
if (options.onKeyUp)
CodeMirror.on(inp, "keyup", function(e) {
options.onKeyUp(e, inp.value, close);
});
CodeMirror.on(inp, "keydown", function(e) {
if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) {
return;
}
if (e.keyCode == 13)
callback && callback(inp.value);
if (e.keyCode == 27 || options.closeOnEnter !== false && e.keyCode == 13) {
inp.blur();
CodeMirror.e_stop(e);
close();
}
});
if (options.closeOnBlur !== false)
CodeMirror.on(inp, "blur", function() {
setTimeout(function() {
if (document.activeElement === inp)
return;
close();
});
});
inp.focus();
}
return close;
}
var matching = { "(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<", "<": ">>", ">": "<<" };
function bracketRegex(config3) {
return config3 && config3.bracketRegex || /[(){}[\]]/;
}
function scanForBracket(cm, where, dir, style, config3) {
var maxScanLen = config3 && config3.maxScanLineLength || 1e4;
var maxScanLines = config3 && config3.maxScanLines || 1e3;
var stack = [];
var re = bracketRegex(config3);
var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1) : Math.max(cm.firstLine() - 1, where.line - maxScanLines);
for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) {
var line = cm.getLine(lineNo);
if (!line)
continue;
var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1;
if (line.length > maxScanLen)
continue;
if (lineNo == where.line)
pos = where.ch - (dir < 0 ? 1 : 0);
for (; pos != end; pos += dir) {
var ch = line.charAt(pos);
if (re.test(ch)) {
var match = matching[ch];
if (match && match.charAt(1) == ">" == dir > 0)
stack.push(ch);
else if (!stack.length)
return { pos: new Pos(lineNo, pos), ch };
else
stack.pop();
}
}
}
return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null;
}
function findMatchingTag(cm, pos) {
return null;
}
function findEnclosingTag(cm, pos) {
var _a, _b;
var state = cm.cm6.state;
var offset = cm.indexFromPos(pos);
if (offset < state.doc.length) {
var text = state.sliceDoc(offset, offset + 1);
if (text == "<")
offset++;
}
var tree = (0, import_language.ensureSyntaxTree)(state, offset);
var node = (tree === null || tree === void 0 ? void 0 : tree.resolve(offset)) || null;
while (node) {
if (((_a = node.firstChild) === null || _a === void 0 ? void 0 : _a.type.name) == "OpenTag" && ((_b = node.lastChild) === null || _b === void 0 ? void 0 : _b.type.name) == "CloseTag") {
return {
open: convertRange(state.doc, node.firstChild),
close: convertRange(state.doc, node.lastChild)
};
}
node = node.parent;
}
}
function convertRange(doc, cm6Range) {
return {
from: posFromIndex(doc, cm6Range.from),
to: posFromIndex(doc, cm6Range.to)
};
}
var Marker = class {
constructor(cm, offset, assoc) {
this.cm = cm;
this.id = cm.$mid++;
this.offset = offset;
this.assoc = assoc;
cm.marks[this.id] = this;
}
clear() {
delete this.cm.marks[this.id];
}
find() {
if (this.offset == null)
return null;
return this.cm.posFromIndex(this.offset);
}
update(change) {
if (this.offset != null)
this.offset = change.mapPos(this.offset, this.assoc, import_state.MapMode.TrackDel);
}
};
function hardWrap(cm, options) {
var _a;
var max = options.column || cm.getOption("textwidth") || 80;
var allowMerge = options.allowMerge != false;
var row = Math.min(options.from, options.to);
var endRow = Math.max(options.from, options.to);
while (row <= endRow) {
var line = cm.getLine(row);
if (line.length > max) {
var space2 = findSpace(line, max, 5);
if (space2) {
var indentation = (_a = /^\s*/.exec(line)) === null || _a === void 0 ? void 0 : _a[0];
cm.replaceRange("\n" + indentation, new Pos(row, space2.start), new Pos(row, space2.end));
}
endRow++;
} else if (allowMerge && /\S/.test(line) && row != endRow) {
var nextLine = cm.getLine(row + 1);
if (nextLine && /\S/.test(nextLine)) {
var trimmedLine = line.replace(/\s+$/, "");
var trimmedNextLine = nextLine.replace(/^\s+/, "");
var mergedLine = trimmedLine + " " + trimmedNextLine;
var space2 = findSpace(mergedLine, max, 5);
if (space2 && space2.start > trimmedLine.length || mergedLine.length < max) {
cm.replaceRange(" ", new Pos(row, trimmedLine.length), new Pos(row + 1, nextLine.length - trimmedNextLine.length));
row--;
endRow--;
} else if (trimmedLine.length < line.length) {
cm.replaceRange("", new Pos(row, trimmedLine.length), new Pos(row, line.length));
}
}
}
row++;
}
return row;
function findSpace(line2, max2, min) {
if (line2.length < max2)
return;
var before = line2.slice(0, max2);
var after = line2.slice(max2);
var spaceAfter = /^(?:(\s+)|(\S+)(\s+))/.exec(after);
var spaceBefore = /(?:(\s+)|(\s+)(\S+))$/.exec(before);
var start = 0;
var end = 0;
if (spaceBefore && !spaceBefore[2]) {
start = max2 - spaceBefore[1].length;
end = max2;
}
if (spaceAfter && !spaceAfter[2]) {
if (!start)
start = max2;
end = max2 + spaceAfter[1].length;
}
if (start) {
return {
start,
end
};
}
if (spaceBefore && spaceBefore[2] && spaceBefore.index > min) {
return {
start: spaceBefore.index,
end: spaceBefore.index + spaceBefore[2].length
};
}
if (spaceAfter && spaceAfter[2]) {
start = max2 + spaceAfter[2].length;
return {
start,
end: start + spaceAfter[3].length
};
}
}
}
var getDrawSelectionConfig2 = View.getDrawSelectionConfig || /* @__PURE__ */ function() {
let defaultConfig = { cursorBlinkRate: 1200 };
return function() {
return defaultConfig;
};
}();
var Piece = class {
constructor(left, top, height, fontFamily, fontSize, fontWeight, color, className, letter, partial) {
this.left = left;
this.top = top;
this.height = height;
this.fontFamily = fontFamily;
this.fontSize = fontSize;
this.fontWeight = fontWeight;
this.color = color;
this.className = className;
this.letter = letter;
this.partial = partial;
}
draw() {
let elt = document.createElement("div");
elt.className = this.className;
this.adjust(elt);
return elt;
}
adjust(elt) {
elt.style.left = this.left + "px";
elt.style.top = this.top + "px";
elt.style.height = this.height + "px";
elt.style.lineHeight = this.height + "px";
elt.style.fontFamily = this.fontFamily;
elt.style.fontSize = this.fontSize;
elt.style.fontWeight = this.fontWeight;
elt.style.color = this.partial ? "transparent" : this.color;
elt.className = this.className;
elt.textContent = this.letter;
}
eq(p) {
return this.left == p.left && this.top == p.top && this.height == p.height && this.fontFamily == p.fontFamily && this.fontSize == p.fontSize && this.fontWeight == p.fontWeight && this.color == p.color && this.className == p.className && this.letter == p.letter;
}
};
var BlockCursorPlugin = class {
constructor(view, cm) {
this.view = view;
this.rangePieces = [];
this.cursors = [];
this.cm = cm;
this.measureReq = { read: this.readPos.bind(this), write: this.drawSel.bind(this) };
this.cursorLayer = view.scrollDOM.appendChild(document.createElement("div"));
this.cursorLayer.className = "cm-cursorLayer cm-vimCursorLayer";
this.cursorLayer.setAttribute("aria-hidden", "true");
view.requestMeasure(this.measureReq);
this.setBlinkRate();
}
setBlinkRate() {
let config3 = getDrawSelectionConfig2(this.cm.cm6.state);
let blinkRate = config3.cursorBlinkRate;
this.cursorLayer.style.animationDuration = blinkRate + "ms";
}
update(update) {
if (update.selectionSet || update.geometryChanged || update.viewportChanged) {
this.view.requestMeasure(this.measureReq);
this.cursorLayer.style.animationName = this.cursorLayer.style.animationName == "cm-blink" ? "cm-blink2" : "cm-blink";
}
if (configChanged(update))
this.setBlinkRate();
}
scheduleRedraw() {
this.view.requestMeasure(this.measureReq);
}
readPos() {
let { state } = this.view;
let cursors = [];
for (let r of state.selection.ranges) {
let prim = r == state.selection.main;
let piece = measureCursor(this.cm, this.view, r, prim);
if (piece)
cursors.push(piece);
}
return { cursors };
}
drawSel({ cursors }) {
if (cursors.length != this.cursors.length || cursors.some((c, i) => !c.eq(this.cursors[i]))) {
let oldCursors = this.cursorLayer.children;
if (oldCursors.length !== cursors.length) {
this.cursorLayer.textContent = "";
for (const c of cursors)
this.cursorLayer.appendChild(c.draw());
} else {
cursors.forEach((c, idx) => c.adjust(oldCursors[idx]));
}
this.cursors = cursors;
}
}
destroy() {
this.cursorLayer.remove();
}
};
function configChanged(update) {
return getDrawSelectionConfig2(update.startState) != getDrawSelectionConfig2(update.state);
}
var themeSpec = {
".cm-vimMode .cm-line": {
"& ::selection": { backgroundColor: "transparent !important" },
"&::selection": { backgroundColor: "transparent !important" },
caretColor: "transparent !important"
},
".cm-fat-cursor": {
position: "absolute",
background: "#ff9696",
border: "none",
whiteSpace: "pre"
},
"&:not(.cm-focused) .cm-fat-cursor": {
background: "none",
outline: "solid 1px #ff9696",
color: "transparent !important"
}
};
var hideNativeSelection = /* @__PURE__ */ import_state.Prec.highest(/* @__PURE__ */ import_view.EditorView.theme(themeSpec));
function getBase(view) {
let rect = view.scrollDOM.getBoundingClientRect();
let left = view.textDirection == import_view.Direction.LTR ? rect.left : rect.right - view.scrollDOM.clientWidth;
return { left: left - view.scrollDOM.scrollLeft * view.scaleX, top: rect.top - view.scrollDOM.scrollTop * view.scaleY };
}
function measureCursor(cm, view, cursor, primary) {
var _a, _b, _c, _d;
let head = cursor.head;
let fatCursor = false;
let hCoeff = 1;
let vim2 = cm.state.vim;
if (vim2 && (!vim2.insertMode || cm.state.overwrite)) {
fatCursor = true;
if (vim2.visualBlock && !primary)
return null;
if (cursor.anchor < cursor.head) {
let letter = head < view.state.doc.length && view.state.sliceDoc(head, head + 1);
if (letter != "\n")
head--;
}
if (cm.state.overwrite)
hCoeff = 0.2;
else if (vim2.status)
hCoeff = 0.5;
}
if (fatCursor) {
let letter = head < view.state.doc.length && view.state.sliceDoc(head, head + 1);
if (letter && (/[\uDC00-\uDFFF]/.test(letter) && head > 1)) {
head--;
letter = view.state.sliceDoc(head, head + 1);
}
let pos = view.coordsAtPos(head, 1);
if (!pos)
return null;
let base = getBase(view);
let domAtPos = view.domAtPos(head);
let node = domAtPos ? domAtPos.node : view.contentDOM;
if (node instanceof Text && domAtPos.offset >= node.data.length) {
if ((_a = node.parentElement) === null || _a === void 0 ? void 0 : _a.nextSibling) {
node = (_b = node.parentElement) === null || _b === void 0 ? void 0 : _b.nextSibling;
domAtPos = { node, offset: 0 };
}
}
while (domAtPos && domAtPos.node instanceof HTMLElement) {
node = domAtPos.node;
domAtPos = { node: domAtPos.node.childNodes[domAtPos.offset], offset: 0 };
}
if (!(node instanceof HTMLElement)) {
if (!node.parentNode)
return null;
node = node.parentNode;
}
let style = getComputedStyle(node);
let left = pos.left;
let charCoords = (_d = (_c = view).coordsForChar) === null || _d === void 0 ? void 0 : _d.call(_c, head);
if (charCoords) {
left = charCoords.left;
}
if (!letter || letter == "\n" || letter == "\r") {
letter = "\xA0";
} else if (letter == " ") {
letter = "\xA0";
var nextPos = view.coordsAtPos(head + 1, -1);
if (nextPos) {
left = nextPos.left - (nextPos.left - pos.left) / parseInt(style.tabSize);
}
} else if (/[\uD800-\uDBFF]/.test(letter) && head < view.state.doc.length - 1) {
letter += view.state.sliceDoc(head + 1, head + 2);
}
let h = pos.bottom - pos.top;
return new Piece((left - base.left) / view.scaleX, (pos.top - base.top + h * (1 - hCoeff)) / view.scaleY, h * hCoeff / view.scaleY, style.fontFamily, style.fontSize, style.fontWeight, style.color, primary ? "cm-fat-cursor cm-cursor-primary" : "cm-fat-cursor cm-cursor-secondary", letter, hCoeff != 1);
} else {
return null;
}
}
var FIREFOX_LINUX = typeof navigator != "undefined" && /* @__PURE__ */ /linux/i.test(navigator.platform) && /* @__PURE__ */ / Gecko\/\d+/.exec(navigator.userAgent);
var Vim = /* @__PURE__ */ initVim(CodeMirror);
var HighlightMargin = 250;
var vimStyle = /* @__PURE__ */ import_view.EditorView.baseTheme({
".cm-vimMode .cm-cursorLayer:not(.cm-vimCursorLayer)": {
display: "none"
},
".cm-vim-panel": {
padding: "0px 10px",
fontFamily: "monospace",
minHeight: "1.3em",
display: "flex"
},
".cm-vim-panel input": {
border: "none",
outline: "none",
backgroundColor: "inherit"
},
"&light .cm-searchMatch": { backgroundColor: "#ffff0054" },
"&dark .cm-searchMatch": { backgroundColor: "#00ffff8a" }
});
var vimPlugin = /* @__PURE__ */ import_view.ViewPlugin.fromClass(class {
constructor(view) {
this.status = "";
this.query = null;
this.decorations = import_view.Decoration.none;
this.waitForCopy = false;
this.lastKeydown = "";
this.useNextTextInput = false;
this.compositionText = "";
this.view = view;
const cm = this.cm = new CodeMirror(view);
Vim.enterVimMode(this.cm);
this.view.cm = this.cm;
this.cm.state.vimPlugin = this;
this.blockCursor = new BlockCursorPlugin(view, cm);
this.updateClass();
this.cm.on("vim-command-done", () => {
if (cm.state.vim)
cm.state.vim.status = "";
this.blockCursor.scheduleRedraw();
this.updateStatus();
});
this.cm.on("vim-mode-change", (e) => {
if (!cm.state.vim)
return;
cm.state.vim.mode = e.mode;
if (e.subMode) {
cm.state.vim.mode += " block";
}
cm.state.vim.status = "";
this.blockCursor.scheduleRedraw();
this.updateClass();
this.updateStatus();
});
this.cm.on("dialog", () => {
if (this.cm.state.statusbar) {
this.updateStatus();
} else {
view.dispatch({
effects: showVimPanel.of(!!this.cm.state.dialog)
});
}
});
this.dom = document.createElement("span");
this.spacer = document.createElement("span");
this.spacer.style.flex = "1";
this.statusButton = document.createElement("span");
this.statusButton.onclick = (e) => {
Vim.handleKey(this.cm, "<Esc>", "user");
this.cm.focus();
};
this.statusButton.style.cssText = "cursor: pointer";
}
update(update) {
var _a;
if ((update.viewportChanged || update.docChanged) && this.query) {
this.highlight(this.query);
}
if (update.docChanged) {
this.cm.onChange(update);
}
if (update.selectionSet) {
this.cm.onSelectionChange();
}
if (update.viewportChanged) ;
if (this.cm.curOp && !this.cm.curOp.isVimOp) {
this.cm.onBeforeEndOperation();
}
if (update.transactions) {
for (let tr of update.transactions)
for (let effect of tr.effects) {
if (effect.is(import_search.setSearchQuery)) {
let forVim = (_a = effect.value) === null || _a === void 0 ? void 0 : _a.forVim;
if (!forVim) {
this.highlight(null);
} else {
let query = effect.value.create();
this.highlight(query);
}
}
}
}
this.blockCursor.update(update);
}
updateClass() {
const state = this.cm.state;
if (!state.vim || state.vim.insertMode && !state.overwrite)
this.view.scrollDOM.classList.remove("cm-vimMode");
else
this.view.scrollDOM.classList.add("cm-vimMode");
}
updateStatus() {
let dom = this.cm.state.statusbar;
let vim2 = this.cm.state.vim;
if (!dom || !vim2)
return;
let dialog = this.cm.state.dialog;
if (dialog) {
if (dialog.parentElement != dom) {
dom.textContent = "";
dom.appendChild(dialog);
}
} else {
dom.textContent = "";
var status = (vim2.mode || "normal").toUpperCase();
if (vim2.insertModeReturn)
status += "(C-O)";
this.statusButton.textContent = `--${status}--`;
dom.appendChild(this.statusButton);
dom.appendChild(this.spacer);
}
this.dom.textContent = vim2.status;
dom.appendChild(this.dom);
}
destroy() {
Vim.leaveVimMode(this.cm);
this.updateClass();
this.blockCursor.destroy();
delete this.view.cm;
}
highlight(query) {
this.query = query;
if (!query)
return this.decorations = import_view.Decoration.none;
let { view } = this;
let builder = new import_state.RangeSetBuilder();
for (let i = 0, ranges = view.visibleRanges, l = ranges.length; i < l; i++) {
let { from, to } = ranges[i];
while (i < l - 1 && to > ranges[i + 1].from - 2 * HighlightMargin)
to = ranges[++i].to;
query.highlight(view.state, from, to, (from2, to2) => {
builder.add(from2, to2, matchMark);
});
}
return this.decorations = builder.finish();
}
handleKey(e, view) {
const cm = this.cm;
let vim2 = cm.state.vim;
if (!vim2)
return;
const key = Vim.vimKeyFromEvent(e, vim2);
CodeMirror.signal(this.cm, "inputEvent", { type: "handleKey", key });
if (!key)
return;
if (key == "<Esc>" && !vim2.insertMode && !vim2.visualMode && this.query) {
const searchState = vim2.searchState_;
if (searchState) {
cm.removeOverlay(searchState.getOverlay());
searchState.setOverlay(null);
}
}
let isCopy = key === "<C-c>" && !CodeMirror.isMac;
if (isCopy && cm.somethingSelected()) {
this.waitForCopy = true;
return true;
}
vim2.status = (vim2.status || "") + key;
let result = Vim.multiSelectHandleKey(cm, key, "user");
vim2 = Vim.maybeInitVimState_(cm);
if (!result && vim2.insertMode && cm.state.overwrite) {
if (e.key && e.key.length == 1 && !/\n/.test(e.key)) {
result = true;
cm.overWriteSelection(e.key);
} else if (e.key == "Backspace") {
result = true;
CodeMirror.commands.cursorCharLeft(cm);
}
}
if (result) {
CodeMirror.signal(this.cm, "vim-keypress", key);
e.preventDefault();
e.stopPropagation();
this.blockCursor.scheduleRedraw();
}
this.updateStatus();
return !!result;
}
}, {
eventHandlers: {
copy: function(e, view) {
if (!this.waitForCopy)
return;
this.waitForCopy = false;
Promise.resolve().then(() => {
var cm = this.cm;
var vim2 = cm.state.vim;
if (!vim2)
return;
if (vim2.insertMode) {
cm.setSelection(cm.getCursor(), cm.getCursor());
} else {
cm.operation(() => {
if (cm.curOp)
cm.curOp.isVimOp = true;
Vim.handleKey(cm, "<Esc>", "user");
});
}
});
},
compositionstart: function(e, view) {
this.useNextTextInput = true;
CodeMirror.signal(this.cm, "inputEvent", e);
},
compositionupdate: function(e, view) {
CodeMirror.signal(this.cm, "inputEvent", e);
},
compositionend: function(e, view) {
CodeMirror.signal(this.cm, "inputEvent", e);
},
keypress: function(e, view) {
CodeMirror.signal(this.cm, "inputEvent", e);
if (this.lastKeydown == "Dead")
this.handleKey(e, view);
},
keydown: function(e, view) {
CodeMirror.signal(this.cm, "inputEvent", e);
this.lastKeydown = e.key;
if (this.lastKeydown == "Unidentified" || this.lastKeydown == "Process" || this.lastKeydown == "Dead") {
this.useNextTextInput = true;
} else {
this.useNextTextInput = false;
this.handleKey(e, view);
}
}
},
provide: () => {
return [
import_view.EditorView.inputHandler.of((view, from, to, text) => {
var _a, _b;
var cm = getCM(view);
if (!cm)
return false;
var vim2 = (_a = cm.state) === null || _a === void 0 ? void 0 : _a.vim;
var vimPlugin2 = cm.state.vimPlugin;
if (vim2 && !vim2.insertMode && !((_b = cm.curOp) === null || _b === void 0 ? void 0 : _b.isVimOp)) {
if (text === "\0\0") {
return true;
}
CodeMirror.signal(cm, "inputEvent", {
type: "text",
text,
from,
to
});
if (text.length == 1 && vimPlugin2.useNextTextInput) {
if (vim2.expectLiteralNext && view.composing) {
vimPlugin2.compositionText = text;
return false;
}
if (vimPlugin2.compositionText) {
var toRemove = vimPlugin2.compositionText;
vimPlugin2.compositionText = "";
var head = view.state.selection.main.head;
var textInDoc = view.state.sliceDoc(head - toRemove.length, head);
if (toRemove === textInDoc) {
var pos = cm.getCursor();
cm.replaceRange("", cm.posFromIndex(head - toRemove.length), pos);
}
}
vimPlugin2.handleKey({
key: text,
preventDefault: () => {
},
stopPropagation: () => {
}
});
forceEndComposition(view);
return true;
}
}
return false;
})
];
},
decorations: (v) => v.decorations
});
function forceEndComposition(view) {
var parent = view.scrollDOM.parentElement;
if (!parent)
return;
if (FIREFOX_LINUX) {
view.contentDOM.textContent = "\0\0";
view.contentDOM.dispatchEvent(new CustomEvent("compositionend"));
return;
}
var sibling = view.scrollDOM.nextSibling;
var selection = window.getSelection();
var savedSelection = selection && {
anchorNode: selection.anchorNode,
anchorOffset: selection.anchorOffset,
focusNode: selection.focusNode,
focusOffset: selection.focusOffset
};
view.scrollDOM.remove();
parent.insertBefore(view.scrollDOM, sibling);
try {
if (savedSelection && selection) {
selection.setPosition(savedSelection.anchorNode, savedSelection.anchorOffset);
if (savedSelection.focusNode) {
selection.extend(savedSelection.focusNode, savedSelection.focusOffset);
}
}
} catch (e) {
console.error(e);
}
view.focus();
view.contentDOM.dispatchEvent(new CustomEvent("compositionend"));
}
var matchMark = /* @__PURE__ */ import_view.Decoration.mark({ class: "cm-searchMatch" });
var showVimPanel = /* @__PURE__ */ import_state.StateEffect.define();
var vimPanelState = /* @__PURE__ */ import_state.StateField.define({
create: () => false,
update(value, tr) {
for (let e of tr.effects)
if (e.is(showVimPanel))
value = e.value;
return value;
},
provide: (f) => {
return import_view.showPanel.from(f, (on2) => on2 ? createVimPanel : null);
}
});
function createVimPanel(view) {
let dom = document.createElement("div");
dom.className = "cm-vim-panel";
let cm = view.cm;
if (cm.state.dialog) {
dom.appendChild(cm.state.dialog);
}
return { top: false, dom };
}
function statusPanel(view) {
let dom = document.createElement("div");
dom.className = "cm-vim-panel";
let cm = view.cm;
cm.state.statusbar = dom;
cm.state.vimPlugin.updateStatus();
return { dom };
}
function vim(options = {}) {
return [
vimStyle,
vimPlugin,
hideNativeSelection,
options.status ? import_view.showPanel.of(statusPanel) : vimPanelState
];
}
function getCM(view) {
return view.cm || null;
}
// src/CssFile.ts
var CssFile = class {
constructor(name) {
/** File extension. */
this.extension = "css";
if (typeof name !== "string" || name.length === 0) {
throw new Error("Invalid file name.");
}
const extensionWithDot = `.${this.extension}`;
const basename = name.endsWith(extensionWithDot) ? name.slice(0, name.length - extensionWithDot.length) : name;
this.name = `${basename}.${this.extension}`;
this.basename = basename;
}
};
// src/obsidian/file-system-helpers.ts
var import_obsidian = require("obsidian");
function getSnippetDirectory(app) {
return `${app.vault.configDir}/snippets/`;
}
async function readSnippetFile(app, file) {
const data = await app.vault.adapter.read(
(0, import_obsidian.normalizePath)(`${getSnippetDirectory(app)}${file.name}`)
);
return data;
}
async function createSnippetFile(app, fileName, data = "") {
const file = new CssFile(fileName);
await _validateFile(app, file);
await _createSnippetDirectoryIfNotExists(app);
await app.vault.adapter.write(
(0, import_obsidian.normalizePath)(`${getSnippetDirectory(app)}${file.name}`),
data
);
return file;
}
async function renameSnippetFile(app, oldFile, newFileName) {
const newFile = new CssFile(newFileName);
if (oldFile.name === newFile.name) return oldFile;
await _validateFile(app, newFile);
await app.vault.adapter.rename(
(0, import_obsidian.normalizePath)(`${getSnippetDirectory(app)}${oldFile.name}`),
(0, import_obsidian.normalizePath)(`${getSnippetDirectory(app)}${newFile.name}`)
);
toggleSnippetFileState(app, oldFile);
toggleSnippetFileState(app, newFile);
app.workspace.trigger("css-snippet-rename", newFile, oldFile.name);
return newFile;
}
async function writeSnippetFile(app, file, data) {
await app.vault.adapter.write(
(0, import_obsidian.normalizePath)(`${getSnippetDirectory(app)}${file.name}`),
data
);
}
async function checkSnippetExists(app, fileName) {
return app.vault.adapter.exists(
(0, import_obsidian.normalizePath)(`${getSnippetDirectory(app)}${fileName}`)
);
}
async function deleteSnippetFile(app, file) {
await app.vault.adapter.remove(
(0, import_obsidian.normalizePath)(`${getSnippetDirectory(app)}${file.name}`)
);
}
function toggleSnippetFileState(app, file) {
var _a;
if (!((_a = app.customCss) == null ? void 0 : _a.enabledSnippets) || !app.customCss.setCssEnabledStatus) {
throw new Error("Failed to enable/disable CSS snippet.");
}
const isEnabled = app.customCss.enabledSnippets.has(file.basename);
app.customCss.setCssEnabledStatus(file.basename, !isEnabled);
return !isEnabled;
}
async function _createSnippetDirectoryIfNotExists(app) {
if (!await app.vault.adapter.exists(getSnippetDirectory(app))) {
await app.vault.adapter.mkdir(getSnippetDirectory(app));
}
}
async function _validateFile(app, file) {
const errors = {
exists: "",
regex: ""
};
if (file.name.length > 0 && await checkSnippetExists(app, file.name)) {
errors.exists = "File already exists.";
}
const regex = /^[0-9a-zA-Z\-_ ]+\.css$/;
if (!regex.test(file.name)) {
errors.regex = "Must end with .css and only contain alphanumeric, spaces, dashes, or underscore characters.";
}
if (Object.values(errors).some((x) => x !== "")) {
const message = Object.values(errors).filter((x) => x !== "").reduce((acc, curr) => `${acc}
${curr}`, "Failed to create file.");
throw new Error(message);
}
}
// src/codemirror-extensions/basic-extensions.ts
var import_commands2 = require("@codemirror/commands");
var import_language6 = require("@codemirror/language");
var import_state3 = require("@codemirror/state");
var import_view5 = require("@codemirror/view");
// node_modules/@codemirror/autocomplete/dist/index.js
var import_state2 = require("@codemirror/state");
var import_view2 = require("@codemirror/view");
var import_language2 = require("@codemirror/language");
var CompletionContext = class {
/**
Create a new completion context. (Mostly useful for testing
completion sources—in the editor, the extension will create
these for you.)
*/
constructor(state, pos, explicit) {
this.state = state;
this.pos = pos;
this.explicit = explicit;
this.abortListeners = [];
}
/**
Get the extent, content, and (if there is a token) type of the
token before `this.pos`.
*/
tokenBefore(types) {
let token = (0, import_language2.syntaxTree)(this.state).resolveInner(this.pos, -1);
while (token && types.indexOf(token.name) < 0)
token = token.parent;
return token ? {
from: token.from,
to: this.pos,
text: this.state.sliceDoc(token.from, this.pos),
type: token.type
} : null;
}
/**
Get the match of the given expression directly before the
cursor.
*/
matchBefore(expr) {
let line = this.state.doc.lineAt(this.pos);
let start = Math.max(line.from, this.pos - 250);
let str = line.text.slice(start - line.from, this.pos - line.from);
let found = str.search(ensureAnchor(expr, false));
return found < 0 ? null : { from: start + found, to: this.pos, text: str.slice(found) };
}
/**
Yields true when the query has been aborted. Can be useful in
asynchronous queries to avoid doing work that will be ignored.
*/
get aborted() {
return this.abortListeners == null;
}
/**
Allows you to register abort handlers, which will be called when
the query is
[aborted](https://codemirror.net/6/docs/ref/#autocomplete.CompletionContext.aborted).
*/
addEventListener(type, listener) {
if (type == "abort" && this.abortListeners)
this.abortListeners.push(listener);
}
};
function toSet(chars) {
let flat = Object.keys(chars).join("");
let words = /\w/.test(flat);
if (words)
flat = flat.replace(/\w/g, "");
return `[${words ? "\\w" : ""}${flat.replace(/[^\w\s]/g, "\\$&")}]`;
}
function prefixMatch(options) {
let first = /* @__PURE__ */ Object.create(null), rest = /* @__PURE__ */ Object.create(null);
for (let { label } of options) {
first[label[0]] = true;
for (let i = 1; i < label.length; i++)
rest[label[i]] = true;
}
let source = toSet(first) + toSet(rest) + "*$";
return [new RegExp("^" + source), new RegExp(source)];
}
function completeFromList(list) {
let options = list.map((o) => typeof o == "string" ? { label: o } : o);
let [validFor, match] = options.every((o) => /^\w+$/.test(o.label)) ? [/\w*$/, /\w+$/] : prefixMatch(options);
return (context) => {
let token = context.matchBefore(match);
return token || context.explicit ? { from: token ? token.from : context.pos, options, validFor } : null;
};
}
var Option = class {
constructor(completion, source, match, score2) {
this.completion = completion;
this.source = source;
this.match = match;
this.score = score2;
}
};
function cur(state) {
return state.selection.main.from;
}
function ensureAnchor(expr, start) {
var _a;
let { source } = expr;
let addStart = start && source[0] != "^", addEnd = source[source.length - 1] != "$";
if (!addStart && !addEnd)
return expr;
return new RegExp(`${addStart ? "^" : ""}(?:${source})${addEnd ? "$" : ""}`, (_a = expr.flags) !== null && _a !== void 0 ? _a : expr.ignoreCase ? "i" : "");
}
var pickedCompletion = /* @__PURE__ */ import_state2.Annotation.define();
function insertCompletionText(state, text, from, to) {
let { main } = state.selection, fromOff = from - main.from, toOff = to - main.from;
return Object.assign(Object.assign({}, state.changeByRange((range) => {
if (range != main && from != to && state.sliceDoc(range.from + fromOff, range.from + toOff) != state.sliceDoc(from, to))
return { range };
return {
changes: { from: range.from + fromOff, to: to == main.from ? range.to : range.from + toOff, insert: text },
range: import_state2.EditorSelection.cursor(range.from + fromOff + text.length)
};
})), { userEvent: "input.complete" });
}
var SourceCache = /* @__PURE__ */ new WeakMap();
function asSource(source) {
if (!Array.isArray(source))
return source;
let known = SourceCache.get(source);
if (!known)
SourceCache.set(source, known = completeFromList(source));
return known;
}
var startCompletionEffect = /* @__PURE__ */ import_state2.StateEffect.define();
var closeCompletionEffect = /* @__PURE__ */ import_state2.StateEffect.define();
var FuzzyMatcher = class {
constructor(pattern) {
this.pattern = pattern;
this.chars = [];
this.folded = [];
this.any = [];
this.precise = [];
this.byWord = [];
for (let p = 0; p < pattern.length; ) {
let char = (0, import_state2.codePointAt)(pattern, p), size = (0, import_state2.codePointSize)(char);
this.chars.push(char);
let part = pattern.slice(p, p + size), upper = part.toUpperCase();
this.folded.push((0, import_state2.codePointAt)(upper == part ? part.toLowerCase() : upper, 0));
p += size;
}
this.astral = pattern.length != this.chars.length;
}
// Matches a given word (completion) against the pattern (input).
// Will return null for no match, and otherwise an array that starts
// with the match score, followed by any number of `from, to` pairs
// indicating the matched parts of `word`.
//
// The score is a number that is more negative the worse the match
// is. See `Penalty` above.
match(word) {
if (this.pattern.length == 0)
return [
-100
/* NotFull */
];
if (word.length < this.pattern.length)
return null;
let { chars, folded, any, precise, byWord } = this;
if (chars.length == 1) {
let first = (0, import_state2.codePointAt)(word, 0), firstSize = (0, import_state2.codePointSize)(first);
let score2 = firstSize == word.length ? 0 : -100;
if (first == chars[0]) ;
else if (first == folded[0])
score2 += -200;
else
return null;
return [score2, 0, firstSize];
}
let direct = word.indexOf(this.pattern);
if (direct == 0)
return [word.length == this.pattern.length ? 0 : -100, 0, this.pattern.length];
let len = chars.length, anyTo = 0;
if (direct < 0) {
for (let i = 0, e = Math.min(word.length, 200); i < e && anyTo < len; ) {
let next = (0, import_state2.codePointAt)(word, i);
if (next == chars[anyTo] || next == folded[anyTo])
any[anyTo++] = i;
i += (0, import_state2.codePointSize)(next);
}
if (anyTo < len)
return null;
}
let preciseTo = 0;
let byWordTo = 0, byWordFolded = false;
let adjacentTo = 0, adjacentStart = -1, adjacentEnd = -1;
let hasLower = /[a-z]/.test(word), wordAdjacent = true;
for (let i = 0, e = Math.min(word.length, 200), prevType = 0; i < e && byWordTo < len; ) {
let next = (0, import_state2.codePointAt)(word, i);
if (direct < 0) {
if (preciseTo < len && next == chars[preciseTo])
precise[preciseTo++] = i;
if (adjacentTo < len) {
if (next == chars[adjacentTo] || next == folded[adjacentTo]) {
if (adjacentTo == 0)
adjacentStart = i;
adjacentEnd = i + 1;
adjacentTo++;
} else {
adjacentTo = 0;
}
}
}
let ch, type = next < 255 ? next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 : next >= 65 && next <= 90 ? 1 : 0 : (ch = (0, import_state2.fromCodePoint)(next)) != ch.toLowerCase() ? 1 : ch != ch.toUpperCase() ? 2 : 0;
if (!i || type == 1 && hasLower || prevType == 0 && type != 0) {
if (chars[byWordTo] == next || folded[byWordTo] == next && (byWordFolded = true))
byWord[byWordTo++] = i;
else if (byWord.length)
wordAdjacent = false;
}
prevType = type;
i += (0, import_state2.codePointSize)(next);
}
if (byWordTo == len && byWord[0] == 0 && wordAdjacent)
return this.result(-100 + (byWordFolded ? -200 : 0), byWord, word);
if (adjacentTo == len && adjacentStart == 0)
return [-200 - word.length + (adjacentEnd == word.length ? 0 : -100), 0, adjacentEnd];
if (direct > -1)
return [-700 - word.length, direct, direct + this.pattern.length];
if (adjacentTo == len)
return [-200 + -700 - word.length, adjacentStart, adjacentEnd];
if (byWordTo == len)
return this.result(-100 + (byWordFolded ? -200 : 0) + -700 + (wordAdjacent ? 0 : -1100), byWord, word);
return chars.length == 2 ? null : this.result((any[0] ? -700 : 0) + -200 + -1100, any, word);
}
result(score2, positions, word) {
let result = [score2 - word.length], i = 1;
for (let pos of positions) {
let to = pos + (this.astral ? (0, import_state2.codePointSize)((0, import_state2.codePointAt)(word, pos)) : 1);
if (i > 1 && result[i - 1] == pos)
result[i - 1] = to;
else {
result[i++] = pos;
result[i++] = to;
}
}
return result;
}
};
var completionConfig = /* @__PURE__ */ import_state2.Facet.define({
combine(configs) {
return (0, import_state2.combineConfig)(configs, {
activateOnTyping: true,
selectOnOpen: true,
override: null,
closeOnBlur: true,
maxRenderedOptions: 100,
defaultKeymap: true,
tooltipClass: () => "",
optionClass: () => "",
aboveCursor: false,
icons: true,
addToOptions: [],
positionInfo: defaultPositionInfo,
compareCompletions: (a, b) => a.label.localeCompare(b.label),
interactionDelay: 75
}, {
defaultKeymap: (a, b) => a && b,
closeOnBlur: (a, b) => a && b,
icons: (a, b) => a && b,
tooltipClass: (a, b) => (c) => joinClass(a(c), b(c)),
optionClass: (a, b) => (c) => joinClass(a(c), b(c)),
addToOptions: (a, b) => a.concat(b)
});
}
});
function joinClass(a, b) {
return a ? b ? a + " " + b : a : b;
}
function defaultPositionInfo(view, list, option, info, space2) {
let rtl = view.textDirection == import_view2.Direction.RTL, left = rtl, narrow = false;
let side = "top", offset, maxWidth;
let spaceLeft = list.left - space2.left, spaceRight = space2.right - list.right;
let infoWidth = info.right - info.left, infoHeight = info.bottom - info.top;
if (left && spaceLeft < Math.min(infoWidth, spaceRight))
left = false;
else if (!left && spaceRight < Math.min(infoWidth, spaceLeft))
left = true;
if (infoWidth <= (left ? spaceLeft : spaceRight)) {
offset = Math.max(space2.top, Math.min(option.top, space2.bottom - infoHeight)) - list.top;
maxWidth = Math.min(400, left ? spaceLeft : spaceRight);
} else {
narrow = true;
maxWidth = Math.min(
400,
(rtl ? list.right : space2.right - list.left) - 30
/* Margin */
);
let spaceBelow = space2.bottom - list.bottom;
if (spaceBelow >= infoHeight || spaceBelow > list.top) {
offset = option.bottom - list.top;
} else {
side = "bottom";
offset = list.bottom - option.top;
}
}
return {
style: `${side}: ${offset}px; max-width: ${maxWidth}px`,
class: "cm-completionInfo-" + (narrow ? rtl ? "left-narrow" : "right-narrow" : left ? "left" : "right")
};
}
function optionContent(config3) {
let content = config3.addToOptions.slice();
if (config3.icons)
content.push({
render(completion) {
let icon = document.createElement("div");
icon.classList.add("cm-completionIcon");
if (completion.type)
icon.classList.add(...completion.type.split(/\s+/g).map((cls) => "cm-completionIcon-" + cls));
icon.setAttribute("aria-hidden", "true");
return icon;
},
position: 20
});
content.push({
render(completion, _s, match) {
let labelElt = document.createElement("span");
labelElt.className = "cm-completionLabel";
let { label } = completion, off2 = 0;
for (let j = 1; j < match.length; ) {
let from = match[j++], to = match[j++];
if (from > off2)
labelElt.appendChild(document.createTextNode(label.slice(off2, from)));
let span = labelElt.appendChild(document.createElement("span"));
span.appendChild(document.createTextNode(label.slice(from, to)));
span.className = "cm-completionMatchedText";
off2 = to;
}
if (off2 < label.length)
labelElt.appendChild(document.createTextNode(label.slice(off2)));
return labelElt;
},
position: 50
}, {
render(completion) {
if (!completion.detail)
return null;
let detailElt = document.createElement("span");
detailElt.className = "cm-completionDetail";
detailElt.textContent = completion.detail;
return detailElt;
},
position: 80
});
return content.sort((a, b) => a.position - b.position).map((a) => a.render);
}
function rangeAroundSelected(total, selected, max) {
if (total <= max)
return { from: 0, to: total };
if (selected < 0)
selected = 0;
if (selected <= total >> 1) {
let off3 = Math.floor(selected / max);
return { from: off3 * max, to: (off3 + 1) * max };
}
let off2 = Math.floor((total - selected) / max);
return { from: total - (off2 + 1) * max, to: total - off2 * max };
}
var CompletionTooltip = class {
constructor(view, stateField, applyCompletion2) {
this.view = view;
this.stateField = stateField;
this.applyCompletion = applyCompletion2;
this.info = null;
this.infoDestroy = null;
this.placeInfoReq = {
read: () => this.measureInfo(),
write: (pos) => this.placeInfo(pos),
key: this
};
this.space = null;
this.currentClass = "";
let cState = view.state.field(stateField);
let { options, selected } = cState.open;
let config3 = view.state.facet(completionConfig);
this.optionContent = optionContent(config3);
this.optionClass = config3.optionClass;
this.tooltipClass = config3.tooltipClass;
this.range = rangeAroundSelected(options.length, selected, config3.maxRenderedOptions);
this.dom = document.createElement("div");
this.dom.className = "cm-tooltip-autocomplete";
this.updateTooltipClass(view.state);
this.dom.addEventListener("mousedown", (e) => {
for (let dom = e.target, match; dom && dom != this.dom; dom = dom.parentNode) {
if (dom.nodeName == "LI" && (match = /-(\d+)$/.exec(dom.id)) && +match[1] < options.length) {
this.applyCompletion(view, options[+match[1]]);
e.preventDefault();
return;
}
}
});
this.dom.addEventListener("focusout", (e) => {
let state = view.state.field(this.stateField, false);
if (state && state.tooltip && view.state.facet(completionConfig).closeOnBlur && e.relatedTarget != view.contentDOM)
view.dispatch({ effects: closeCompletionEffect.of(null) });
});
this.list = this.dom.appendChild(this.createListBox(options, cState.id, this.range));
this.list.addEventListener("scroll", () => {
if (this.info)
this.view.requestMeasure(this.placeInfoReq);
});
}
mount() {
this.updateSel();
}
update(update) {
var _a, _b, _c;
let cState = update.state.field(this.stateField);
let prevState = update.startState.field(this.stateField);
this.updateTooltipClass(update.state);
if (cState != prevState) {
this.updateSel();
if (((_a = cState.open) === null || _a === void 0 ? void 0 : _a.disabled) != ((_b = prevState.open) === null || _b === void 0 ? void 0 : _b.disabled))
this.dom.classList.toggle("cm-tooltip-autocomplete-disabled", !!((_c = cState.open) === null || _c === void 0 ? void 0 : _c.disabled));
}
}
updateTooltipClass(state) {
let cls = this.tooltipClass(state);
if (cls != this.currentClass) {
for (let c of this.currentClass.split(" "))
if (c)
this.dom.classList.remove(c);
for (let c of cls.split(" "))
if (c)
this.dom.classList.add(c);
this.currentClass = cls;
}
}
positioned(space2) {
this.space = space2;
if (this.info)
this.view.requestMeasure(this.placeInfoReq);
}
updateSel() {
let cState = this.view.state.field(this.stateField), open = cState.open;
if (open.selected > -1 && open.selected < this.range.from || open.selected >= this.range.to) {
this.range = rangeAroundSelected(open.options.length, open.selected, this.view.state.facet(completionConfig).maxRenderedOptions);
this.list.remove();
this.list = this.dom.appendChild(this.createListBox(open.options, cState.id, this.range));
this.list.addEventListener("scroll", () => {
if (this.info)
this.view.requestMeasure(this.placeInfoReq);
});
}
if (this.updateSelectedOption(open.selected)) {
this.destroyInfo();
let { completion } = open.options[open.selected];
let { info } = completion;
if (!info)
return;
let infoResult = typeof info === "string" ? document.createTextNode(info) : info(completion);
if (!infoResult)
return;
if ("then" in infoResult) {
infoResult.then((obj) => {
if (obj && this.view.state.field(this.stateField, false) == cState)
this.addInfoPane(obj, completion);
}).catch((e) => (0, import_view2.logException)(this.view.state, e, "completion info"));
} else {
this.addInfoPane(infoResult, completion);
}
}
}
addInfoPane(content, completion) {
this.destroyInfo();
let wrap = this.info = document.createElement("div");
wrap.className = "cm-tooltip cm-completionInfo";
if (content.nodeType != null) {
wrap.appendChild(content);
this.infoDestroy = null;
} else {
let { dom, destroy } = content;
wrap.appendChild(dom);
this.infoDestroy = destroy || null;
}
this.dom.appendChild(wrap);
this.view.requestMeasure(this.placeInfoReq);
}
updateSelectedOption(selected) {
let set = null;
for (let opt = this.list.firstChild, i = this.range.from; opt; opt = opt.nextSibling, i++) {
if (opt.nodeName != "LI" || !opt.id) {
i--;
} else if (i == selected) {
if (!opt.hasAttribute("aria-selected")) {
opt.setAttribute("aria-selected", "true");
set = opt;
}
} else {
if (opt.hasAttribute("aria-selected"))
opt.removeAttribute("aria-selected");
}
}
if (set)
scrollIntoView(this.list, set);
return set;
}
measureInfo() {
let sel = this.dom.querySelector("[aria-selected]");
if (!sel || !this.info)
return null;
let listRect = this.dom.getBoundingClientRect();
let infoRect = this.info.getBoundingClientRect();
let selRect = sel.getBoundingClientRect();
let space2 = this.space;
if (!space2) {
let win = this.dom.ownerDocument.defaultView || window;
space2 = { left: 0, top: 0, right: win.innerWidth, bottom: win.innerHeight };
}
if (selRect.top > Math.min(space2.bottom, listRect.bottom) - 10 || selRect.bottom < Math.max(space2.top, listRect.top) + 10)
return null;
return this.view.state.facet(completionConfig).positionInfo(this.view, listRect, selRect, infoRect, space2);
}
placeInfo(pos) {
if (this.info) {
if (pos) {
if (pos.style)
this.info.style.cssText = pos.style;
this.info.className = "cm-tooltip cm-completionInfo " + (pos.class || "");
} else {
this.info.style.cssText = "top: -1e6px";
}
}
}
createListBox(options, id, range) {
const ul = document.createElement("ul");
ul.id = id;
ul.setAttribute("role", "listbox");
ul.setAttribute("aria-expanded", "true");
ul.setAttribute("aria-label", this.view.state.phrase("Completions"));
let curSection = null;
for (let i = range.from; i < range.to; i++) {
let { completion, match } = options[i], { section } = completion;
if (section) {
let name = typeof section == "string" ? section : section.name;
if (name != curSection && (i > range.from || range.from == 0)) {
curSection = name;
if (typeof section != "string" && section.header) {
ul.appendChild(section.header(section));
} else {
let header = ul.appendChild(document.createElement("completion-section"));
header.textContent = name;
}
}
}
const li = ul.appendChild(document.createElement("li"));
li.id = id + "-" + i;
li.setAttribute("role", "option");
let cls = this.optionClass(completion);
if (cls)
li.className = cls;
for (let source of this.optionContent) {
let node = source(completion, this.view.state, match);
if (node)
li.appendChild(node);
}
}
if (range.from)
ul.classList.add("cm-completionListIncompleteTop");
if (range.to < options.length)
ul.classList.add("cm-completionListIncompleteBottom");
return ul;
}
destroyInfo() {
if (this.info) {
if (this.infoDestroy)
this.infoDestroy();
this.info.remove();
this.info = null;
}
}
destroy() {
this.destroyInfo();
}
};
function completionTooltip(stateField, applyCompletion2) {
return (view) => new CompletionTooltip(view, stateField, applyCompletion2);
}
function scrollIntoView(container, element) {
let parent = container.getBoundingClientRect();
let self = element.getBoundingClientRect();
if (self.top < parent.top)
container.scrollTop -= parent.top - self.top;
else if (self.bottom > parent.bottom)
container.scrollTop += self.bottom - parent.bottom;
}
function score(option) {
return (option.boost || 0) * 100 + (option.apply ? 10 : 0) + (option.info ? 5 : 0) + (option.type ? 1 : 0);
}
function sortOptions(active, state) {
let options = [];
let sections = null;
let addOption = (option) => {
options.push(option);
let { section } = option.completion;
if (section) {
if (!sections)
sections = [];
let name = typeof section == "string" ? section : section.name;
if (!sections.some((s) => s.name == name))
sections.push(typeof section == "string" ? { name } : section);
}
};
for (let a of active)
if (a.hasResult()) {
if (a.result.filter === false) {
let getMatch = a.result.getMatch;
for (let option of a.result.options) {
let match = [1e9 - options.length];
if (getMatch)
for (let n of getMatch(option))
match.push(n);
addOption(new Option(option, a.source, match, match[0]));
}
} else {
let matcher = new FuzzyMatcher(state.sliceDoc(a.from, a.to)), match;
for (let option of a.result.options)
if (match = matcher.match(option.label)) {
addOption(new Option(option, a.source, match, match[0] + (option.boost || 0)));
}
}
}
if (sections) {
let sectionOrder = /* @__PURE__ */ Object.create(null), pos = 0;
let cmp = (a, b) => {
var _a, _b;
return ((_a = a.rank) !== null && _a !== void 0 ? _a : 1e9) - ((_b = b.rank) !== null && _b !== void 0 ? _b : 1e9) || (a.name < b.name ? -1 : 1);
};
for (let s of sections.sort(cmp)) {
pos -= 1e5;
sectionOrder[s.name] = pos;
}
for (let option of options) {
let { section } = option.completion;
if (section)
option.score += sectionOrder[typeof section == "string" ? section : section.name];
}
}
let result = [], prev = null;
let compare = state.facet(completionConfig).compareCompletions;
for (let opt of options.sort((a, b) => b.score - a.score || compare(a.completion, b.completion))) {
let cur2 = opt.completion;
if (!prev || prev.label != cur2.label || prev.detail != cur2.detail || prev.type != null && cur2.type != null && prev.type != cur2.type || prev.apply != cur2.apply || prev.boost != cur2.boost)
result.push(opt);
else if (score(opt.completion) > score(prev))
result[result.length - 1] = opt;
prev = opt.completion;
}
return result;
}
var CompletionDialog = class _CompletionDialog {
constructor(options, attrs, tooltip, timestamp, selected, disabled) {
this.options = options;
this.attrs = attrs;
this.tooltip = tooltip;
this.timestamp = timestamp;
this.selected = selected;
this.disabled = disabled;
}
setSelected(selected, id) {
return selected == this.selected || selected >= this.options.length ? this : new _CompletionDialog(this.options, makeAttrs(id, selected), this.tooltip, this.timestamp, selected, this.disabled);
}
static build(active, state, id, prev, conf) {
let options = sortOptions(active, state);
if (!options.length) {
return prev && active.some(
(a) => a.state == 1
/* Pending */
) ? new _CompletionDialog(prev.options, prev.attrs, prev.tooltip, prev.timestamp, prev.selected, true) : null;
}
let selected = state.facet(completionConfig).selectOnOpen ? 0 : -1;
if (prev && prev.selected != selected && prev.selected != -1) {
let selectedValue = prev.options[prev.selected].completion;
for (let i = 0; i < options.length; i++)
if (options[i].completion == selectedValue) {
selected = i;
break;
}
}
return new _CompletionDialog(options, makeAttrs(id, selected), {
pos: active.reduce((a, b) => b.hasResult() ? Math.min(a, b.from) : a, 1e8),
create: completionTooltip(completionState, applyCompletion),
above: conf.aboveCursor
}, prev ? prev.timestamp : Date.now(), selected, false);
}
map(changes) {
return new _CompletionDialog(this.options, this.attrs, Object.assign(Object.assign({}, this.tooltip), { pos: changes.mapPos(this.tooltip.pos) }), this.timestamp, this.selected, this.disabled);
}
};
var CompletionState = class _CompletionState {
constructor(active, id, open) {
this.active = active;
this.id = id;
this.open = open;
}
static start() {
return new _CompletionState(none, "cm-ac-" + Math.floor(Math.random() * 2e6).toString(36), null);
}
update(tr) {
let { state } = tr, conf = state.facet(completionConfig);
let sources = conf.override || state.languageDataAt("autocomplete", cur(state)).map(asSource);
let active = sources.map((source) => {
let value = this.active.find((s) => s.source == source) || new ActiveSource(
source,
this.active.some(
(a) => a.state != 0
/* Inactive */
) ? 1 : 0
/* Inactive */
);
return value.update(tr, conf);
});
if (active.length == this.active.length && active.every((a, i) => a == this.active[i]))
active = this.active;
let open = this.open;
if (open && tr.docChanged)
open = open.map(tr.changes);
if (tr.selection || active.some((a) => a.hasResult() && tr.changes.touchesRange(a.from, a.to)) || !sameResults(active, this.active))
open = CompletionDialog.build(active, state, this.id, open, conf);
else if (open && open.disabled && !active.some(
(a) => a.state == 1
/* Pending */
))
open = null;
if (!open && active.every(
(a) => a.state != 1
/* Pending */
) && active.some((a) => a.hasResult()))
active = active.map((a) => a.hasResult() ? new ActiveSource(
a.source,
0
/* Inactive */
) : a);
for (let effect of tr.effects)
if (effect.is(setSelectedEffect))
open = open && open.setSelected(effect.value, this.id);
return active == this.active && open == this.open ? this : new _CompletionState(active, this.id, open);
}
get tooltip() {
return this.open ? this.open.tooltip : null;
}
get attrs() {
return this.open ? this.open.attrs : baseAttrs;
}
};
function sameResults(a, b) {
if (a == b)
return true;
for (let iA = 0, iB = 0; ; ) {
while (iA < a.length && !a[iA].hasResult)
iA++;
while (iB < b.length && !b[iB].hasResult)
iB++;
let endA = iA == a.length, endB = iB == b.length;
if (endA || endB)
return endA == endB;
if (a[iA++].result != b[iB++].result)
return false;
}
}
var baseAttrs = {
"aria-autocomplete": "list"
};
function makeAttrs(id, selected) {
let result = {
"aria-autocomplete": "list",
"aria-haspopup": "listbox",
"aria-controls": id
};
if (selected > -1)
result["aria-activedescendant"] = id + "-" + selected;
return result;
}
var none = [];
function getUserEvent(tr) {
return tr.isUserEvent("input.type") ? "input" : tr.isUserEvent("delete.backward") ? "delete" : null;
}
var ActiveSource = class _ActiveSource {
constructor(source, state, explicitPos = -1) {
this.source = source;
this.state = state;
this.explicitPos = explicitPos;
}
hasResult() {
return false;
}
update(tr, conf) {
let event = getUserEvent(tr), value = this;
if (event)
value = value.handleUserEvent(tr, event, conf);
else if (tr.docChanged)
value = value.handleChange(tr);
else if (tr.selection && value.state != 0)
value = new _ActiveSource(
value.source,
0
/* Inactive */
);
for (let effect of tr.effects) {
if (effect.is(startCompletionEffect))
value = new _ActiveSource(value.source, 1, effect.value ? cur(tr.state) : -1);
else if (effect.is(closeCompletionEffect))
value = new _ActiveSource(
value.source,
0
/* Inactive */
);
else if (effect.is(setActiveEffect)) {
for (let active of effect.value)
if (active.source == value.source)
value = active;
}
}
return value;
}
handleUserEvent(tr, type, conf) {
return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new _ActiveSource(
this.source,
1
/* Pending */
);
}
handleChange(tr) {
return tr.changes.touchesRange(cur(tr.startState)) ? new _ActiveSource(
this.source,
0
/* Inactive */
) : this.map(tr.changes);
}
map(changes) {
return changes.empty || this.explicitPos < 0 ? this : new _ActiveSource(this.source, this.state, changes.mapPos(this.explicitPos));
}
};
var ActiveResult = class _ActiveResult extends ActiveSource {
constructor(source, explicitPos, result, from, to) {
super(source, 2, explicitPos);
this.result = result;
this.from = from;
this.to = to;
}
hasResult() {
return true;
}
handleUserEvent(tr, type, conf) {
var _a;
let from = tr.changes.mapPos(this.from), to = tr.changes.mapPos(this.to, 1);
let pos = cur(tr.state);
if ((this.explicitPos < 0 ? pos <= from : pos < this.from) || pos > to || type == "delete" && cur(tr.startState) == this.from)
return new ActiveSource(
this.source,
type == "input" && conf.activateOnTyping ? 1 : 0
/* Inactive */
);
let explicitPos = this.explicitPos < 0 ? -1 : tr.changes.mapPos(this.explicitPos), updated;
if (checkValid(this.result.validFor, tr.state, from, to))
return new _ActiveResult(this.source, explicitPos, this.result, from, to);
if (this.result.update && (updated = this.result.update(this.result, from, to, new CompletionContext(tr.state, pos, explicitPos >= 0))))
return new _ActiveResult(this.source, explicitPos, updated, updated.from, (_a = updated.to) !== null && _a !== void 0 ? _a : cur(tr.state));
return new ActiveSource(this.source, 1, explicitPos);
}
handleChange(tr) {
return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(
this.source,
0
/* Inactive */
) : this.map(tr.changes);
}
map(mapping) {
return mapping.empty ? this : new _ActiveResult(this.source, this.explicitPos < 0 ? -1 : mapping.mapPos(this.explicitPos), this.result, mapping.mapPos(this.from), mapping.mapPos(this.to, 1));
}
};
function checkValid(validFor, state, from, to) {
if (!validFor)
return false;
let text = state.sliceDoc(from, to);
return typeof validFor == "function" ? validFor(text, from, to, state) : ensureAnchor(validFor, true).test(text);
}
var setActiveEffect = /* @__PURE__ */ import_state2.StateEffect.define({
map(sources, mapping) {
return sources.map((s) => s.map(mapping));
}
});
var setSelectedEffect = /* @__PURE__ */ import_state2.StateEffect.define();
var completionState = /* @__PURE__ */ import_state2.StateField.define({
create() {
return CompletionState.start();
},
update(value, tr) {
return value.update(tr);
},
provide: (f) => [
import_view2.showTooltip.from(f, (val) => val.tooltip),
import_view2.EditorView.contentAttributes.from(f, (state) => state.attrs)
]
});
function applyCompletion(view, option) {
const apply = option.completion.apply || option.completion.label;
let result = view.state.field(completionState).active.find((a) => a.source == option.source);
if (!(result instanceof ActiveResult))
return false;
if (typeof apply == "string")
view.dispatch(Object.assign(Object.assign({}, insertCompletionText(view.state, apply, result.from, result.to)), { annotations: pickedCompletion.of(option.completion) }));
else
apply(view, option.completion, result.from, result.to);
return true;
}
function moveCompletionSelection(forward, by = "option") {
return (view) => {
let cState = view.state.field(completionState, false);
if (!cState || !cState.open || cState.open.disabled || Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay)
return false;
let step = 1, tooltip;
if (by == "page" && (tooltip = (0, import_view2.getTooltip)(view, cState.open.tooltip)))
step = Math.max(2, Math.floor(tooltip.dom.offsetHeight / tooltip.dom.querySelector("li").offsetHeight) - 1);
let { length } = cState.open.options;
let selected = cState.open.selected > -1 ? cState.open.selected + step * (forward ? 1 : -1) : forward ? 0 : length - 1;
if (selected < 0)
selected = by == "page" ? 0 : length - 1;
else if (selected >= length)
selected = by == "page" ? length - 1 : 0;
view.dispatch({ effects: setSelectedEffect.of(selected) });
return true;
};
}
var acceptCompletion = (view) => {
let cState = view.state.field(completionState, false);
if (view.state.readOnly || !cState || !cState.open || cState.open.selected < 0 || cState.open.disabled || Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay)
return false;
return applyCompletion(view, cState.open.options[cState.open.selected]);
};
var startCompletion = (view) => {
let cState = view.state.field(completionState, false);
if (!cState)
return false;
view.dispatch({ effects: startCompletionEffect.of(true) });
return true;
};
var closeCompletion = (view) => {
let cState = view.state.field(completionState, false);
if (!cState || !cState.active.some(
(a) => a.state != 0
/* Inactive */
))
return false;
view.dispatch({ effects: closeCompletionEffect.of(null) });
return true;
};
var RunningQuery = class {
constructor(active, context) {
this.active = active;
this.context = context;
this.time = Date.now();
this.updates = [];
this.done = void 0;
}
};
var DebounceTime = 50;
var MaxUpdateCount = 50;
var MinAbortTime = 1e3;
var completionPlugin = /* @__PURE__ */ import_view2.ViewPlugin.fromClass(class {
constructor(view) {
this.view = view;
this.debounceUpdate = -1;
this.running = [];
this.debounceAccept = -1;
this.composing = 0;
for (let active of view.state.field(completionState).active)
if (active.state == 1)
this.startQuery(active);
}
update(update) {
let cState = update.state.field(completionState);
if (!update.selectionSet && !update.docChanged && update.startState.field(completionState) == cState)
return;
let doesReset = update.transactions.some((tr) => {
return (tr.selection || tr.docChanged) && !getUserEvent(tr);
});
for (let i = 0; i < this.running.length; i++) {
let query = this.running[i];
if (doesReset || query.updates.length + update.transactions.length > MaxUpdateCount && Date.now() - query.time > MinAbortTime) {
for (let handler of query.context.abortListeners) {
try {
handler();
} catch (e) {
(0, import_view2.logException)(this.view.state, e);
}
}
query.context.abortListeners = null;
this.running.splice(i--, 1);
} else {
query.updates.push(...update.transactions);
}
}
if (this.debounceUpdate > -1)
clearTimeout(this.debounceUpdate);
this.debounceUpdate = cState.active.some((a) => a.state == 1 && !this.running.some((q) => q.active.source == a.source)) ? setTimeout(() => this.startUpdate(), DebounceTime) : -1;
if (this.composing != 0)
for (let tr of update.transactions) {
if (getUserEvent(tr) == "input")
this.composing = 2;
else if (this.composing == 2 && tr.selection)
this.composing = 3;
}
}
startUpdate() {
this.debounceUpdate = -1;
let { state } = this.view, cState = state.field(completionState);
for (let active of cState.active) {
if (active.state == 1 && !this.running.some((r) => r.active.source == active.source))
this.startQuery(active);
}
}
startQuery(active) {
let { state } = this.view, pos = cur(state);
let context = new CompletionContext(state, pos, active.explicitPos == pos);
let pending = new RunningQuery(active, context);
this.running.push(pending);
Promise.resolve(active.source(context)).then((result) => {
if (!pending.context.aborted) {
pending.done = result || null;
this.scheduleAccept();
}
}, (err) => {
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
(0, import_view2.logException)(this.view.state, err);
});
}
scheduleAccept() {
if (this.running.every((q) => q.done !== void 0))
this.accept();
else if (this.debounceAccept < 0)
this.debounceAccept = setTimeout(() => this.accept(), DebounceTime);
}
// For each finished query in this.running, try to create a result
// or, if appropriate, restart the query.
accept() {
var _a;
if (this.debounceAccept > -1)
clearTimeout(this.debounceAccept);
this.debounceAccept = -1;
let updated = [];
let conf = this.view.state.facet(completionConfig);
for (let i = 0; i < this.running.length; i++) {
let query = this.running[i];
if (query.done === void 0)
continue;
this.running.splice(i--, 1);
if (query.done) {
let active = new ActiveResult(query.active.source, query.active.explicitPos, query.done, query.done.from, (_a = query.done.to) !== null && _a !== void 0 ? _a : cur(query.updates.length ? query.updates[0].startState : this.view.state));
for (let tr of query.updates)
active = active.update(tr, conf);
if (active.hasResult()) {
updated.push(active);
continue;
}
}
let current = this.view.state.field(completionState).active.find((a) => a.source == query.active.source);
if (current && current.state == 1) {
if (query.done == null) {
let active = new ActiveSource(
query.active.source,
0
/* Inactive */
);
for (let tr of query.updates)
active = active.update(tr, conf);
if (active.state != 1)
updated.push(active);
} else {
this.startQuery(current);
}
}
}
if (updated.length)
this.view.dispatch({ effects: setActiveEffect.of(updated) });
}
}, {
eventHandlers: {
blur(event) {
let state = this.view.state.field(completionState, false);
if (state && state.tooltip && this.view.state.facet(completionConfig).closeOnBlur) {
let dialog = state.open && (0, import_view2.getTooltip)(this.view, state.open.tooltip);
if (!dialog || !dialog.dom.contains(event.relatedTarget))
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
}
},
compositionstart() {
this.composing = 1;
},
compositionend() {
if (this.composing == 3) {
setTimeout(() => this.view.dispatch({ effects: startCompletionEffect.of(false) }), 20);
}
this.composing = 0;
}
}
});
var baseTheme = /* @__PURE__ */ import_view2.EditorView.baseTheme({
".cm-tooltip.cm-tooltip-autocomplete": {
"& > ul": {
fontFamily: "monospace",
whiteSpace: "nowrap",
overflow: "hidden auto",
maxWidth_fallback: "700px",
maxWidth: "min(700px, 95vw)",
minWidth: "250px",
maxHeight: "10em",
height: "100%",
listStyle: "none",
margin: 0,
padding: 0,
"& > li, & > completion-section": {
padding: "1px 3px",
lineHeight: 1.2
},
"& > li": {
overflowX: "hidden",
textOverflow: "ellipsis",
cursor: "pointer"
},
"& > completion-section": {
display: "list-item",
borderBottom: "1px solid silver",
paddingLeft: "0.5em",
opacity: 0.7
}
}
},
"&light .cm-tooltip-autocomplete ul li[aria-selected]": {
background: "#17c",
color: "white"
},
"&light .cm-tooltip-autocomplete-disabled ul li[aria-selected]": {
background: "#777"
},
"&dark .cm-tooltip-autocomplete ul li[aria-selected]": {
background: "#347",
color: "white"
},
"&dark .cm-tooltip-autocomplete-disabled ul li[aria-selected]": {
background: "#444"
},
".cm-completionListIncompleteTop:before, .cm-completionListIncompleteBottom:after": {
content: '"\xB7\xB7\xB7"',
opacity: 0.5,
display: "block",
textAlign: "center"
},
".cm-tooltip.cm-completionInfo": {
position: "absolute",
padding: "3px 9px",
width: "max-content",
maxWidth: `${400}px`,
boxSizing: "border-box"
},
".cm-completionInfo.cm-completionInfo-left": { right: "100%" },
".cm-completionInfo.cm-completionInfo-right": { left: "100%" },
".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30}px` },
".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30}px` },
"&light .cm-snippetField": { backgroundColor: "#00000022" },
"&dark .cm-snippetField": { backgroundColor: "#ffffff22" },
".cm-snippetFieldPosition": {
verticalAlign: "text-top",
width: 0,
height: "1.15em",
display: "inline-block",
margin: "0 -0.7px -.7em",
borderLeft: "1.4px dotted #888"
},
".cm-completionMatchedText": {
textDecoration: "underline"
},
".cm-completionDetail": {
marginLeft: "0.5em",
fontStyle: "italic"
},
".cm-completionIcon": {
fontSize: "90%",
width: ".8em",
display: "inline-block",
textAlign: "center",
paddingRight: ".6em",
opacity: "0.6",
boxSizing: "content-box"
},
".cm-completionIcon-function, .cm-completionIcon-method": {
"&:after": { content: "'\u0192'" }
},
".cm-completionIcon-class": {
"&:after": { content: "'\u25CB'" }
},
".cm-completionIcon-interface": {
"&:after": { content: "'\u25CC'" }
},
".cm-completionIcon-variable": {
"&:after": { content: "'\u{1D465}'" }
},
".cm-completionIcon-constant": {
"&:after": { content: "'\u{1D436}'" }
},
".cm-completionIcon-type": {
"&:after": { content: "'\u{1D461}'" }
},
".cm-completionIcon-enum": {
"&:after": { content: "'\u222A'" }
},
".cm-completionIcon-property": {
"&:after": { content: "'\u25A1'" }
},
".cm-completionIcon-keyword": {
"&:after": { content: "'\u{1F511}\uFE0E'" }
// Disable emoji rendering
},
".cm-completionIcon-namespace": {
"&:after": { content: "'\u25A2'" }
},
".cm-completionIcon-text": {
"&:after": { content: "'abc'", fontSize: "50%", verticalAlign: "middle" }
}
});
var defaults = {
brackets: ["(", "[", "{", "'", '"'],
before: ")]}:;>",
stringPrefixes: []
};
var closeBracketEffect = /* @__PURE__ */ import_state2.StateEffect.define({
map(value, mapping) {
let mapped = mapping.mapPos(value, -1, import_state2.MapMode.TrackAfter);
return mapped == null ? void 0 : mapped;
}
});
var closedBracket = /* @__PURE__ */ new class extends import_state2.RangeValue {
}();
closedBracket.startSide = 1;
closedBracket.endSide = -1;
var bracketState = /* @__PURE__ */ import_state2.StateField.define({
create() {
return import_state2.RangeSet.empty;
},
update(value, tr) {
if (tr.selection) {
let lineStart = tr.state.doc.lineAt(tr.selection.main.head).from;
let prevLineStart = tr.startState.doc.lineAt(tr.startState.selection.main.head).from;
if (lineStart != tr.changes.mapPos(prevLineStart, -1))
value = import_state2.RangeSet.empty;
}
value = value.map(tr.changes);
for (let effect of tr.effects)
if (effect.is(closeBracketEffect))
value = value.update({ add: [closedBracket.range(effect.value, effect.value + 1)] });
return value;
}
});
function closeBrackets() {
return [inputHandler, bracketState];
}
var definedClosing = "()[]{}<>";
function closing(ch) {
for (let i = 0; i < definedClosing.length; i += 2)
if (definedClosing.charCodeAt(i) == ch)
return definedClosing.charAt(i + 1);
return (0, import_state2.fromCodePoint)(ch < 128 ? ch : ch + 1);
}
function config(state, pos) {
return state.languageDataAt("closeBrackets", pos)[0] || defaults;
}
var android = typeof navigator == "object" && /* @__PURE__ */ /Android\b/.test(navigator.userAgent);
var inputHandler = /* @__PURE__ */ import_view2.EditorView.inputHandler.of((view, from, to, insert) => {
if ((android ? view.composing : view.compositionStarted) || view.state.readOnly)
return false;
let sel = view.state.selection.main;
if (insert.length > 2 || insert.length == 2 && (0, import_state2.codePointSize)((0, import_state2.codePointAt)(insert, 0)) == 1 || from != sel.from || to != sel.to)
return false;
let tr = insertBracket(view.state, insert);
if (!tr)
return false;
view.dispatch(tr);
return true;
});
var deleteBracketPair = ({ state, dispatch }) => {
if (state.readOnly)
return false;
let conf = config(state, state.selection.main.head);
let tokens = conf.brackets || defaults.brackets;
let dont = null, changes = state.changeByRange((range) => {
if (range.empty) {
let before = prevChar(state.doc, range.head);
for (let token of tokens) {
if (token == before && nextChar(state.doc, range.head) == closing((0, import_state2.codePointAt)(token, 0)))
return {
changes: { from: range.head - token.length, to: range.head + token.length },
range: import_state2.EditorSelection.cursor(range.head - token.length)
};
}
}
return { range: dont = range };
});
if (!dont)
dispatch(state.update(changes, { scrollIntoView: true, userEvent: "delete.backward" }));
return !dont;
};
var closeBracketsKeymap = [
{ key: "Backspace", run: deleteBracketPair }
];
function insertBracket(state, bracket) {
let conf = config(state, state.selection.main.head);
let tokens = conf.brackets || defaults.brackets;
for (let tok of tokens) {
let closed = closing((0, import_state2.codePointAt)(tok, 0));
if (bracket == tok)
return closed == tok ? handleSame(state, tok, tokens.indexOf(tok + tok + tok) > -1, conf) : handleOpen(state, tok, closed, conf.before || defaults.before);
if (bracket == closed && closedBracketAt(state, state.selection.main.from))
return handleClose(state, tok, closed);
}
return null;
}
function closedBracketAt(state, pos) {
let found = false;
state.field(bracketState).between(0, state.doc.length, (from) => {
if (from == pos)
found = true;
});
return found;
}
function nextChar(doc, pos) {
let next = doc.sliceString(pos, pos + 2);
return next.slice(0, (0, import_state2.codePointSize)((0, import_state2.codePointAt)(next, 0)));
}
function prevChar(doc, pos) {
let prev = doc.sliceString(pos - 2, pos);
return (0, import_state2.codePointSize)((0, import_state2.codePointAt)(prev, 0)) == prev.length ? prev : prev.slice(1);
}
function handleOpen(state, open, close, closeBefore) {
let dont = null, changes = state.changeByRange((range) => {
if (!range.empty)
return {
changes: [{ insert: open, from: range.from }, { insert: close, from: range.to }],
effects: closeBracketEffect.of(range.to + open.length),
range: import_state2.EditorSelection.range(range.anchor + open.length, range.head + open.length)
};
let next = nextChar(state.doc, range.head);
if (!next || /\s/.test(next) || closeBefore.indexOf(next) > -1)
return {
changes: { insert: open + close, from: range.head },
effects: closeBracketEffect.of(range.head + open.length),
range: import_state2.EditorSelection.cursor(range.head + open.length)
};
return { range: dont = range };
});
return dont ? null : state.update(changes, {
scrollIntoView: true,
userEvent: "input.type"
});
}
function handleClose(state, _open, close) {
let dont = null, changes = state.changeByRange((range) => {
if (range.empty && nextChar(state.doc, range.head) == close)
return {
changes: { from: range.head, to: range.head + close.length, insert: close },
range: import_state2.EditorSelection.cursor(range.head + close.length)
};
return dont = { range };
});
return dont ? null : state.update(changes, {
scrollIntoView: true,
userEvent: "input.type"
});
}
function handleSame(state, token, allowTriple, config3) {
let stringPrefixes = config3.stringPrefixes || defaults.stringPrefixes;
let dont = null, changes = state.changeByRange((range) => {
if (!range.empty)
return {
changes: [{ insert: token, from: range.from }, { insert: token, from: range.to }],
effects: closeBracketEffect.of(range.to + token.length),
range: import_state2.EditorSelection.range(range.anchor + token.length, range.head + token.length)
};
let pos = range.head, next = nextChar(state.doc, pos), start;
if (next == token) {
if (nodeStart(state, pos)) {
return {
changes: { insert: token + token, from: pos },
effects: closeBracketEffect.of(pos + token.length),
range: import_state2.EditorSelection.cursor(pos + token.length)
};
} else if (closedBracketAt(state, pos)) {
let isTriple = allowTriple && state.sliceDoc(pos, pos + token.length * 3) == token + token + token;
let content = isTriple ? token + token + token : token;
return {
changes: { from: pos, to: pos + content.length, insert: content },
range: import_state2.EditorSelection.cursor(pos + content.length)
};
}
} else if (allowTriple && state.sliceDoc(pos - 2 * token.length, pos) == token + token && (start = canStartStringAt(state, pos - 2 * token.length, stringPrefixes)) > -1 && nodeStart(state, start)) {
return {
changes: { insert: token + token + token + token, from: pos },
effects: closeBracketEffect.of(pos + token.length),
range: import_state2.EditorSelection.cursor(pos + token.length)
};
} else if (state.charCategorizer(pos)(next) != import_state2.CharCategory.Word) {
if (canStartStringAt(state, pos, stringPrefixes) > -1 && !probablyInString(state, pos, token, stringPrefixes))
return {
changes: { insert: token + token, from: pos },
effects: closeBracketEffect.of(pos + token.length),
range: import_state2.EditorSelection.cursor(pos + token.length)
};
}
return { range: dont = range };
});
return dont ? null : state.update(changes, {
scrollIntoView: true,
userEvent: "input.type"
});
}
function nodeStart(state, pos) {
let tree = (0, import_language2.syntaxTree)(state).resolveInner(pos + 1);
return tree.parent && tree.from == pos;
}
function probablyInString(state, pos, quoteToken, prefixes) {
let node = (0, import_language2.syntaxTree)(state).resolveInner(pos, -1);
let maxPrefix = prefixes.reduce((m, p) => Math.max(m, p.length), 0);
for (let i = 0; i < 5; i++) {
let start = state.sliceDoc(node.from, Math.min(node.to, node.from + quoteToken.length + maxPrefix));
let quotePos = start.indexOf(quoteToken);
if (!quotePos || quotePos > -1 && prefixes.indexOf(start.slice(0, quotePos)) > -1) {
let first = node.firstChild;
while (first && first.from == node.from && first.to - first.from > quoteToken.length + quotePos) {
if (state.sliceDoc(first.to - quoteToken.length, first.to) == quoteToken)
return false;
first = first.firstChild;
}
return true;
}
let parent = node.to == pos && node.parent;
if (!parent)
break;
node = parent;
}
return false;
}
function canStartStringAt(state, pos, prefixes) {
let charCat = state.charCategorizer(pos);
if (charCat(state.sliceDoc(pos - 1, pos)) != import_state2.CharCategory.Word)
return pos;
for (let prefix of prefixes) {
let start = pos - prefix.length;
if (state.sliceDoc(start, pos) == prefix && charCat(state.sliceDoc(start - 1, start)) != import_state2.CharCategory.Word)
return start;
}
return -1;
}
function autocompletion(config3 = {}) {
return [
completionState,
completionConfig.of(config3),
completionPlugin,
completionKeymapExt,
baseTheme
];
}
var completionKeymap = [
{ key: "Ctrl-Space", run: startCompletion },
{ key: "Escape", run: closeCompletion },
{ key: "ArrowDown", run: /* @__PURE__ */ moveCompletionSelection(true) },
{ key: "ArrowUp", run: /* @__PURE__ */ moveCompletionSelection(false) },
{ key: "PageDown", run: /* @__PURE__ */ moveCompletionSelection(true, "page") },
{ key: "PageUp", run: /* @__PURE__ */ moveCompletionSelection(false, "page") },
{ key: "Enter", run: acceptCompletion }
];
var completionKeymapExt = /* @__PURE__ */ import_state2.Prec.highest(/* @__PURE__ */ import_view2.keymap.computeN([completionConfig], (state) => state.facet(completionConfig).defaultKeymap ? [completionKeymap] : []));
// src/codemirror-extensions/basic-extensions.ts
var import_search2 = require("@codemirror/search");
var import_lint = require("@codemirror/lint");
// src/codemirror-extensions/obsidian-theme.ts
var import_view3 = require("@codemirror/view");
var import_language3 = require("@codemirror/language");
var import_highlight = require("@lezer/highlight");
var config2 = {
name: "obsidian",
dark: false,
background: "var(--background-primary)",
foreground: "var(--text-normal)",
selection: "var(--text-selection)",
cursor: "var(--text-normal)",
dropdownBackground: "var(--background-primary)",
dropdownBorder: "var(--background-modifier-border)",
activeLine: "var(--background-secondary)",
activeLineNumber: "var(--text-normal)",
matchingBracket: "var(--background-modifier-accent)",
keyword: "#d73a49",
storage: "#d73a49",
variable: "var(--text-normal)",
parameter: "var(--text-accent-hover)",
function: "var(--text-accent-hover)",
string: "var(--text-accent)",
constant: "var(--text-accent-hover)",
type: "var(--text-accent-hover)",
class: "#6f42c1",
number: "var(--text-accent-hover)",
comment: "var(--text-faint)",
invalid: "var(--text-error)",
regexp: "#032f62",
monospace: "var(--font-monospace)"
};
var obsidianTheme = import_view3.EditorView.theme(
{
"&": {
color: config2.foreground,
backgroundColor: config2.background
},
".cm-scroller": { fontFamily: config2.monospace },
".cm-content": { caretColor: config2.cursor },
"&.cm-focused .cm-cursor": { borderLeftColor: config2.cursor },
".cm-selectionBackground, &.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, & ::selection": { backgroundColor: config2.selection },
".cm-panels": {
backgroundColor: config2.dropdownBackground,
color: config2.foreground
},
".cm-panels.cm-panels-top": { borderBottom: "2px solid black" },
".cm-panels.cm-panels-bottom": { borderTop: "2px solid black" },
".cm-searchMatch": {
backgroundColor: config2.dropdownBackground,
outline: `1px solid ${config2.dropdownBorder}`
},
".cm-searchMatch.cm-searchMatch-selected": {
backgroundColor: config2.selection
},
".cm-activeLine": { backgroundColor: config2.activeLine },
".cm-activeLineGutter": {
backgroundColor: config2.activeLine,
".cm-lineNumbers &": {
color: config2.activeLineNumber
}
},
".cm-selectionMatch": { backgroundColor: config2.selection },
".cm-matchingBracket, .cm-nonmatchingBracket": {
backgroundColor: config2.matchingBracket,
outline: "none"
},
".cm-gutters": {
backgroundColor: config2.background,
color: config2.comment,
borderRight: "1px solid var(--background-modifier-border)"
},
".cm-lineNumbers, .cm-gutterElement": { color: "inherit" },
".cm-foldPlaceholder": {
backgroundColor: "transparent",
border: "none",
color: config2.foreground
},
".cm-tooltip": {
border: `1px solid ${config2.dropdownBorder}`,
backgroundColor: config2.dropdownBackground,
color: config2.foreground
},
".cm-tooltip.cm-tooltip-autocomplete": {
"& > ul": {
fontFamily: config2.monospace,
"& > li[aria-selected]": {
background: config2.selection,
color: config2.foreground
}
}
}
},
{ dark: config2.dark }
);
var obsidianHighlightStyle = import_language3.HighlightStyle.define([
{ tag: import_highlight.tags.keyword, color: config2.keyword },
{
tag: [import_highlight.tags.name, import_highlight.tags.deleted, import_highlight.tags.character, import_highlight.tags.macroName],
color: config2.variable
},
{ tag: [import_highlight.tags.propertyName], color: config2.function },
{
tag: [
import_highlight.tags.processingInstruction,
import_highlight.tags.string,
import_highlight.tags.inserted,
import_highlight.tags.special(import_highlight.tags.string)
],
color: config2.string
},
{ tag: [import_highlight.tags.function(import_highlight.tags.variableName), import_highlight.tags.labelName], color: config2.function },
{
tag: [import_highlight.tags.color, import_highlight.tags.constant(import_highlight.tags.name), import_highlight.tags.standard(import_highlight.tags.name)],
color: config2.constant
},
{ tag: [import_highlight.tags.definition(import_highlight.tags.name), import_highlight.tags.separator], color: config2.variable },
{ tag: [import_highlight.tags.className], color: config2.class },
{
tag: [
import_highlight.tags.number,
import_highlight.tags.changed,
import_highlight.tags.annotation,
import_highlight.tags.modifier,
import_highlight.tags.self,
import_highlight.tags.namespace
],
color: config2.number
},
{ tag: [import_highlight.tags.typeName], color: config2.type, fontStyle: config2.type },
{ tag: [import_highlight.tags.operator, import_highlight.tags.operatorKeyword], color: config2.keyword },
{ tag: [import_highlight.tags.url, import_highlight.tags.escape, import_highlight.tags.regexp, import_highlight.tags.link], color: config2.regexp },
{ tag: [import_highlight.tags.meta, import_highlight.tags.comment], color: config2.comment },
{
tag: [import_highlight.tags.atom, import_highlight.tags.bool, import_highlight.tags.special(import_highlight.tags.variableName)],
color: config2.variable
},
{ tag: import_highlight.tags.invalid, color: config2.invalid }
]);
var obsidian = [
obsidianTheme,
(0, import_language3.syntaxHighlighting)(obsidianHighlightStyle)
];
// node_modules/@lezer/css/dist/index.es.js
var import_lr = require("@lezer/lr");
var import_highlight2 = require("@lezer/highlight");
var descendantOp = 94;
var Unit = 1;
var callee = 95;
var identifier = 96;
var VariableName = 2;
var space = [
9,
10,
11,
12,
13,
32,
133,
160,
5760,
8192,
8193,
8194,
8195,
8196,
8197,
8198,
8199,
8200,
8201,
8202,
8232,
8233,
8239,
8287,
12288
];
var colon = 58;
var parenL = 40;
var underscore = 95;
var bracketL = 91;
var dash = 45;
var period = 46;
var hash = 35;
var percent = 37;
function isAlpha(ch) {
return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || ch >= 161;
}
function isDigit(ch) {
return ch >= 48 && ch <= 57;
}
var identifiers = new import_lr.ExternalTokenizer((input, stack) => {
for (let inside = false, dashes = 0, i = 0; ; i++) {
let { next } = input;
if (isAlpha(next) || next == dash || next == underscore || inside && isDigit(next)) {
if (!inside && (next != dash || i > 0)) inside = true;
if (dashes === i && next == dash) dashes++;
input.advance();
} else {
if (inside)
input.acceptToken(next == parenL ? callee : dashes == 2 && stack.canShift(VariableName) ? VariableName : identifier);
break;
}
}
});
var descendant = new import_lr.ExternalTokenizer((input) => {
if (space.includes(input.peek(-1))) {
let { next } = input;
if (isAlpha(next) || next == underscore || next == hash || next == period || next == bracketL || next == colon || next == dash)
input.acceptToken(descendantOp);
}
});
var unitToken = new import_lr.ExternalTokenizer((input) => {
if (!space.includes(input.peek(-1))) {
let { next } = input;
if (next == percent) {
input.advance();
input.acceptToken(Unit);
}
if (isAlpha(next)) {
do {
input.advance();
} while (isAlpha(input.next));
input.acceptToken(Unit);
}
}
});
var cssHighlighting = (0, import_highlight2.styleTags)({
"AtKeyword import charset namespace keyframes media supports": import_highlight2.tags.definitionKeyword,
"from to selector": import_highlight2.tags.keyword,
NamespaceName: import_highlight2.tags.namespace,
KeyframeName: import_highlight2.tags.labelName,
TagName: import_highlight2.tags.tagName,
ClassName: import_highlight2.tags.className,
PseudoClassName: import_highlight2.tags.constant(import_highlight2.tags.className),
IdName: import_highlight2.tags.labelName,
"FeatureName PropertyName": import_highlight2.tags.propertyName,
AttributeName: import_highlight2.tags.attributeName,
NumberLiteral: import_highlight2.tags.number,
KeywordQuery: import_highlight2.tags.keyword,
UnaryQueryOp: import_highlight2.tags.operatorKeyword,
"CallTag ValueName": import_highlight2.tags.atom,
VariableName: import_highlight2.tags.variableName,
Callee: import_highlight2.tags.operatorKeyword,
Unit: import_highlight2.tags.unit,
"UniversalSelector NestingSelector": import_highlight2.tags.definitionOperator,
MatchOp: import_highlight2.tags.compareOperator,
"ChildOp SiblingOp, LogicOp": import_highlight2.tags.logicOperator,
BinOp: import_highlight2.tags.arithmeticOperator,
Important: import_highlight2.tags.modifier,
Comment: import_highlight2.tags.blockComment,
ParenthesizedContent: import_highlight2.tags.special(import_highlight2.tags.name),
ColorLiteral: import_highlight2.tags.color,
StringLiteral: import_highlight2.tags.string,
":": import_highlight2.tags.punctuation,
"PseudoOp #": import_highlight2.tags.derefOperator,
"; ,": import_highlight2.tags.separator,
"( )": import_highlight2.tags.paren,
"[ ]": import_highlight2.tags.squareBracket,
"{ }": import_highlight2.tags.brace
});
var spec_callee = { __proto__: null, lang: 32, "nth-child": 32, "nth-last-child": 32, "nth-of-type": 32, "nth-last-of-type": 32, dir: 32, "host-context": 32, url: 60, "url-prefix": 60, domain: 60, regexp: 60, selector: 134 };
var spec_AtKeyword = { __proto__: null, "@import": 114, "@media": 138, "@charset": 142, "@namespace": 146, "@keyframes": 152, "@supports": 164 };
var spec_identifier = { __proto__: null, not: 128, only: 128, from: 158, to: 160 };
var parser = import_lr.LRParser.deserialize({
version: 14,
states: "7WQYQ[OOO#_Q[OOOOQP'#Cd'#CdOOQP'#Cc'#CcO#fQ[O'#CfO$YQXO'#CaO$aQ[O'#ChO$lQ[O'#DPO$qQ[O'#DTOOQP'#Ed'#EdO$vQdO'#DeO%bQ[O'#DrO$vQdO'#DtO%sQ[O'#DvO&OQ[O'#DyO&TQ[O'#EPO&cQ[O'#EROOQS'#Ec'#EcOOQS'#ET'#ETQYQ[OOO&jQXO'#CdO'_QWO'#DaO'dQWO'#EjO'oQ[O'#EjQOQWOOOOQP'#Cg'#CgOOQP,59Q,59QO#fQ[O,59QO'yQ[O'#EWO(eQWO,58{O(mQ[O,59SO$lQ[O,59kO$qQ[O,59oO'yQ[O,59sO'yQ[O,59uO'yQ[O,59vO(xQ[O'#D`OOQS,58{,58{OOQP'#Ck'#CkOOQO'#C}'#C}OOQP,59S,59SO)PQWO,59SO)UQWO,59SOOQP'#DR'#DROOQP,59k,59kOOQO'#DV'#DVO)ZQ`O,59oOOQS'#Cp'#CpO$vQdO'#CqO)cQvO'#CsO*pQtO,5:POOQO'#Cx'#CxO)UQWO'#CwO+UQWO'#CyOOQS'#Eg'#EgOOQO'#Dh'#DhO+ZQ[O'#DoO+iQWO'#EkO&TQ[O'#DmO+wQWO'#DpOOQO'#El'#ElO(hQWO,5:^O+|QpO,5:`OOQS'#Dx'#DxO,UQWO,5:bO,ZQ[O,5:bOOQO'#D{'#D{O,cQWO,5:eO,hQWO,5:kO,pQWO,5:mOOQS-E8R-E8RO$vQdO,59{O,xQ[O'#EYO-VQWO,5;UO-VQWO,5;UOOQP1G.l1G.lO-|QXO,5:rOOQO-E8U-E8UOOQS1G.g1G.gOOQP1G.n1G.nO)PQWO1G.nO)UQWO1G.nOOQP1G/V1G/VO.ZQ`O1G/ZO.tQXO1G/_O/[QXO1G/aO/rQXO1G/bO0YQWO,59zO0_Q[O'#DOO0fQdO'#CoOOQP1G/Z1G/ZO$vQdO1G/ZO0mQpO,59]OOQS,59_,59_O$vQdO,59aO0uQWO1G/kOOQS,59c,59cO0zQ!bO,59eO1SQWO'#DhO1_QWO,5:TO1dQWO,5:ZO&TQ[O,5:VO&TQ[O'#EZO1lQWO,5;VO1wQWO,5:XO'yQ[O,5:[OOQS1G/x1G/xOOQS1G/z1G/zOOQS1G/|1G/|O2YQWO1G/|O2_QdO'#D|OOQS1G0P1G0POOQS1G0V1G0VOOQS1G0X1G0XO2mQtO1G/gOOQO,5:t,5:tO3TQ[O,5:tOOQO-E8W-E8WO3bQWO1G0pOOQP7+$Y7+$YOOQP7+$u7+$uO$vQdO7+$uOOQS1G/f1G/fO3mQXO'#EiO3tQWO,59jO3yQtO'#EUO4nQdO'#EfO4xQWO,59ZO4}QpO7+$uOOQS1G.w1G.wOOQS1G.{1G.{OOQS7+%V7+%VO5VQWO1G/PO$vQdO1G/oOOQO1G/u1G/uOOQO1G/q1G/qO5[QWO,5:uOOQO-E8X-E8XO5jQXO1G/vOOQS7+%h7+%hO5qQYO'#CsO(hQWO'#E[O5yQdO,5:hOOQS,5:h,5:hO6XQtO'#EXO$vQdO'#EXO7VQdO7+%ROOQO7+%R7+%ROOQO1G0`1G0`O7jQpO<<HaO7rQWO,5;TOOQP1G/U1G/UOOQS-E8S-E8SO$vQdO'#EVO7zQWO,5;QOOQT1G.u1G.uOOQP<<Ha<<HaOOQS7+$k7+$kO8SQdO7+%ZOOQO7+%b7+%bOOQS,5:v,5:vOOQS-E8Y-E8YOOQS1G0S1G0SO8ZQtO,5:sOOQS-E8V-E8VOOQO<<Hm<<HmOOQPAN={AN={O9XQdO,5:qOOQO-E8T-E8TOOQO<<Hu<<Hu",
stateData: "9i~O#UOSROS~OUXOXXO]UO^UOtVOxWO!Y`O!ZYO!gZO!i[O!k]O!n^O!t_O#SQO#XSO~OQeOUXOXXO]UO^UOtVOxWO!Y`O!ZYO!gZO!i[O!k]O!n^O!t_O#SdO#XSO~O#P#^P~P!ZO#SiO~O]nO^nOplOtoOxpO|qO!PsO#QrO#XkO~O!RtO~P#kO`zO#RwO#SvO~O#S{O~O#S}O~OQ!WOb!QOf!WOh!WOn!VO#R!TO#S!PO#[!RO~Ob!YO!b![O!e!]O#S!XO!R#_P~Oh!bOn!VO#S!aO~O#S!dO~Ob!YO!b![O!e!]O#S!XO~O!W#_P~P%bO]WX]!UX^WXpWXtWXxWX|WX!PWX!RWX#QWX#XWX~O]!iO~O!W!jO#P#^X!Q#^X~O#P#^X!Q#^X~P!ZOUXOXXO]UO^UOtVOxWO#SQO#XSO~OplO!RtO~O`!sO#RwO#SvO~O!Q#^P~P!ZOb!zO~Ob!{O~Ov!|Oz!}O~OP#PObgXjgX!WgX!bgX!egX#SgXagXQgXfgXhgXngXpgX!VgX#PgX#RgX#[gXvgX!QgX~Ob!YOj#QO!b![O!e!]O#S!XO!W#_P~Ob#TO~Ob!YO!b![O!e!]O#S#UO~Op#YO!`#XO!R#_X!W#_X~Ob#]O~Oj#QO!W#_O~O!W#`O~Oh#aOn!VO~O!R#bO~O!RtO!`#XO~O!RtO!W#eO~O!W!|X#P!|X!Q!|X~P!ZO!W!jO#P#^a!Q#^a~O]nO^nOtoOxpO|qO!PsO#QrO#XkO~Op!za!R!zaa!za~P-bOv#lOz#mO~O]nO^nOtoOxpO#XkO~Op{i|{i!P{i!R{i#Q{ia{i~P.cOp}i|}i!P}i!R}i#Q}ia}i~P.cOp!Oi|!Oi!P!Oi!R!Oi#Q!Oia!Oi~P.cO!Q#nO~Oa#]P~P'yOa#YP~P$vOa#uOj#QO~O!W#wO~Oh#xOo#xO~O]!^Xa![X!`![X~O]#yO~Oa#zO!`#XO~Op#YO!R#_a!W#_a~O!`#XOp!aa!R!aa!W!aaa!aa~O!W$PO~O!Q$TO!q$RO!r$RO#[$QO~Oj#QOp$VO!V$XO!W!Ti#P!Ti!Q!Ti~P$vO!W!|a#P!|a!Q!|a~P!ZO!W!jO#P#^i!Q#^i~Oa#]X~P#kOa$]O~Oj#QOQ!xXa!xXb!xXf!xXh!xXn!xXp!xX#R!xX#S!xX#[!xX~Op$_Oa#YX~P$vOa$aO~Oj#QOv$bO~Oa$cO~O!`#XOp!}a!R!}a!W!}a~Oa$eO~P-bOP#PO!RgX~O!Q$hO!q$RO!r$RO#[$QO~Oj#QOQ!{Xb!{Xf!{Xh!{Xn!{Xp!{X!V!{X!W!{X#P!{X#R!{X#S!{X#[!{X!Q!{X~Op$VO!V$kO!W!Tq#P!Tq!Q!Tq~P$vOj#QOv$lO~OplOa#]a~Op$_Oa#Ya~Oa$oO~P$vOj#QOQ!{ab!{af!{ah!{an!{ap!{a!V!{a!W!{a#P!{a#R!{a#S!{a#[!{a!Q!{a~Oa!yap!ya~P$vOo#[j!Pj~",
goto: ",`#aPPPPP#bP#k#zP#k$Z#kPP$aPPP$g$p$pP%SP$pP$p%j%|PPP&f&l#kP&rP#kP&xP#kP#k#kPPP'O'b'oPP#bPP'v'v(Q'vP'vP'v'vP#bP#bP#bP(T#bP(W(ZPP#bP#bP(^(m({)R)])c)m)sPPPPPP)y*SP*o*rP+h+k+q+z_aOPcgt!j#hkXOPcglqrst!j!z#]#hkROPcglqrst!j!z#]#hQjSR!mkQxUR!qnQ!qzQ#S!UR#k!sq!WY[!Q!i!{!}#Q#f#m#r#y$V$W$_$d$mp!WY[!Q!i!{!}#Q#f#m#r#y$V$W$_$d$mT$R#b$Sq!UY[!Q!i!{!}#Q#f#m#r#y$V$W$_$d$mp!WY[!Q!i!{!}#Q#f#m#r#y$V$W$_$d$mQ!b]R#a!cQyUR!rnQ!qyR#k!rQ|VR!toQ!OWR!upQuTQ!pmQ#^!_Q#d!fQ#e!gR$f$RSfPtQ!lgQ#g!jR$Y#hZePgt!j#ha!^Z_`!S!Y![#X#YR#V!YR!c]R!e^R#c!eQcOSgPtU!hcg#hR#h!jQ#r!{U$^#r$d$mQ$d#yR$m$_Q$`#rR$n$`QmTS!om$[R$[#oQ$W#fR$j$WQ!kfS#i!k#jR#j!lQ#Z!ZR#}#ZQ$S#bR$g$S_bOPcgt!j#h^TOPcgt!j#hQ!nlQ!vqQ!wrQ!xsQ#o!zR$O#]R#s!{Q!SYQ!`[Q#O!QQ#f!i[#q!{#r#y$_$d$mQ#t!}Q#v#QS$U#f$WQ$Z#mR$i$VR#p!zQhPR!ytQ!_ZQ!g`R#R!SU!ZZ`!SQ!f_Q#W!YQ#[![Q#{#XR#|#Y",
nodeNames: "\u26A0 Unit VariableName Comment StyleSheet RuleSet UniversalSelector TagSelector TagName NestingSelector ClassSelector ClassName PseudoClassSelector : :: PseudoClassName PseudoClassName ) ( ArgList ValueName ParenthesizedValue ColorLiteral NumberLiteral StringLiteral BinaryExpression BinOp CallExpression Callee CallLiteral CallTag ParenthesizedContent , PseudoClassName ArgList IdSelector # IdName ] AttributeSelector [ AttributeName MatchOp ChildSelector ChildOp DescendantSelector SiblingSelector SiblingOp } { Block Declaration PropertyName Important ; ImportStatement AtKeyword import KeywordQuery FeatureQuery FeatureName BinaryQuery LogicOp UnaryQuery UnaryQueryOp ParenthesizedQuery SelectorQuery selector MediaStatement media CharsetStatement charset NamespaceStatement namespace NamespaceName KeyframesStatement keyframes KeyframeName KeyframeList from to SupportsStatement supports AtRule Styles",
maxTerm: 108,
nodeProps: [
["openedBy", 17, "(", 48, "{"],
["closedBy", 18, ")", 49, "}"]
],
propSources: [cssHighlighting],
skippedNodes: [0, 3],
repeatNodeCount: 8,
tokenData: "Lq~R!^OX$}X^%u^p$}pq%uqr)Xrs.Rst/utu6duv$}vw7^wx7oxy9^yz9oz{9t{|:_|}?Q}!O?c!O!P@Q!P!Q@i!Q![Cu![!]Dp!]!^El!^!_$}!_!`E}!`!aF`!a!b$}!b!cG[!c!}$}!}#OHt#O#P$}#P#QIV#Q#R6d#R#T$}#T#UIh#U#c$}#c#dJy#d#o$}#o#pK`#p#q6d#q#rKq#r#sLS#s#y$}#y#z%u#z$f$}$f$g%u$g#BY$}#BY#BZ%u#BZ$IS$}$IS$I_%u$I_$I|$}$I|$JO%u$JO$JT$}$JT$JU%u$JU$KV$}$KV$KW%u$KW&FU$}&FU&FV%u&FV;'S$};'S;=`Lk<%lO$}W%QSOy%^z;'S%^;'S;=`%o<%lO%^W%cSoWOy%^z;'S%^;'S;=`%o<%lO%^W%rP;=`<%l%^~%zh#U~OX%^X^'f^p%^pq'fqy%^z#y%^#y#z'f#z$f%^$f$g'f$g#BY%^#BY#BZ'f#BZ$IS%^$IS$I_'f$I_$I|%^$I|$JO'f$JO$JT%^$JT$JU'f$JU$KV%^$KV$KW'f$KW&FU%^&FU&FV'f&FV;'S%^;'S;=`%o<%lO%^~'mh#U~oWOX%^X^'f^p%^pq'fqy%^z#y%^#y#z'f#z$f%^$f$g'f$g#BY%^#BY#BZ'f#BZ$IS%^$IS$I_'f$I_$I|%^$I|$JO'f$JO$JT%^$JT$JU'f$JU$KV%^$KV$KW'f$KW&FU%^&FU&FV'f&FV;'S%^;'S;=`%o<%lO%^^)[UOy%^z#]%^#]#^)n#^;'S%^;'S;=`%o<%lO%^^)sUoWOy%^z#a%^#a#b*V#b;'S%^;'S;=`%o<%lO%^^*[UoWOy%^z#d%^#d#e*n#e;'S%^;'S;=`%o<%lO%^^*sUoWOy%^z#c%^#c#d+V#d;'S%^;'S;=`%o<%lO%^^+[UoWOy%^z#f%^#f#g+n#g;'S%^;'S;=`%o<%lO%^^+sUoWOy%^z#h%^#h#i,V#i;'S%^;'S;=`%o<%lO%^^,[UoWOy%^z#T%^#T#U,n#U;'S%^;'S;=`%o<%lO%^^,sUoWOy%^z#b%^#b#c-V#c;'S%^;'S;=`%o<%lO%^^-[UoWOy%^z#h%^#h#i-n#i;'S%^;'S;=`%o<%lO%^^-uS!VUoWOy%^z;'S%^;'S;=`%o<%lO%^~.UWOY.RZr.Rrs.ns#O.R#O#P.s#P;'S.R;'S;=`/o<%lO.R~.sOh~~.vRO;'S.R;'S;=`/P;=`O.R~/SXOY.RZr.Rrs.ns#O.R#O#P.s#P;'S.R;'S;=`/o;=`<%l.R<%lO.R~/rP;=`<%l.R_/zYtPOy%^z!Q%^!Q![0j![!c%^!c!i0j!i#T%^#T#Z0j#Z;'S%^;'S;=`%o<%lO%^^0oYoWOy%^z!Q%^!Q![1_![!c%^!c!i1_!i#T%^#T#Z1_#Z;'S%^;'S;=`%o<%lO%^^1dYoWOy%^z!Q%^!Q![2S![!c%^!c!i2S!i#T%^#T#Z2S#Z;'S%^;'S;=`%o<%lO%^^2ZYfUoWOy%^z!Q%^!Q![2y![!c%^!c!i2y!i#T%^#T#Z2y#Z;'S%^;'S;=`%o<%lO%^^3QYfUoWOy%^z!Q%^!Q![3p![!c%^!c!i3p!i#T%^#T#Z3p#Z;'S%^;'S;=`%o<%lO%^^3uYoWOy%^z!Q%^!Q![4e![!c%^!c!i4e!i#T%^#T#Z4e#Z;'S%^;'S;=`%o<%lO%^^4lYfUoWOy%^z!Q%^!Q![5[![!c%^!c!i5[!i#T%^#T#Z5[#Z;'S%^;'S;=`%o<%lO%^^5aYoWOy%^z!Q%^!Q![6P![!c%^!c!i6P!i#T%^#T#Z6P#Z;'S%^;'S;=`%o<%lO%^^6WSfUoWOy%^z;'S%^;'S;=`%o<%lO%^Y6gUOy%^z!_%^!_!`6y!`;'S%^;'S;=`%o<%lO%^Y7QSzQoWOy%^z;'S%^;'S;=`%o<%lO%^X7cSXPOy%^z;'S%^;'S;=`%o<%lO%^~7rWOY7oZw7owx.nx#O7o#O#P8[#P;'S7o;'S;=`9W<%lO7o~8_RO;'S7o;'S;=`8h;=`O7o~8kXOY7oZw7owx.nx#O7o#O#P8[#P;'S7o;'S;=`9W;=`<%l7o<%lO7o~9ZP;=`<%l7o_9cSbVOy%^z;'S%^;'S;=`%o<%lO%^~9tOa~_9{UUPjSOy%^z!_%^!_!`6y!`;'S%^;'S;=`%o<%lO%^_:fWjS!PPOy%^z!O%^!O!P;O!P!Q%^!Q![>T![;'S%^;'S;=`%o<%lO%^^;TUoWOy%^z!Q%^!Q![;g![;'S%^;'S;=`%o<%lO%^^;nYoW#[UOy%^z!Q%^!Q![;g![!g%^!g!h<^!h#X%^#X#Y<^#Y;'S%^;'S;=`%o<%lO%^^<cYoWOy%^z{%^{|=R|}%^}!O=R!O!Q%^!Q![=j![;'S%^;'S;=`%o<%lO%^^=WUoWOy%^z!Q%^!Q![=j![;'S%^;'S;=`%o<%lO%^^=qUoW#[UOy%^z!Q%^!Q![=j![;'S%^;'S;=`%o<%lO%^^>[[oW#[UOy%^z!O%^!O!P;g!P!Q%^!Q![>T![!g%^!g!h<^!h#X%^#X#Y<^#Y;'S%^;'S;=`%o<%lO%^_?VSpVOy%^z;'S%^;'S;=`%o<%lO%^^?hWjSOy%^z!O%^!O!P;O!P!Q%^!Q![>T![;'S%^;'S;=`%o<%lO%^_@VU#XPOy%^z!Q%^!Q![;g![;'S%^;'S;=`%o<%lO%^~@nTjSOy%^z{@}{;'S%^;'S;=`%o<%lO%^~ASUoWOy@}yzAfz{Bm{;'S@};'S;=`Co<%lO@}~AiTOzAfz{Ax{;'SAf;'S;=`Bg<%lOAf~A{VOzAfz{Ax{!PAf!P!QBb!Q;'SAf;'S;=`Bg<%lOAf~BgOR~~BjP;=`<%lAf~BrWoWOy@}yzAfz{Bm{!P@}!P!QC[!Q;'S@};'S;=`Co<%lO@}~CcSoWR~Oy%^z;'S%^;'S;=`%o<%lO%^~CrP;=`<%l@}^Cz[#[UOy%^z!O%^!O!P;g!P!Q%^!Q![>T![!g%^!g!h<^!h#X%^#X#Y<^#Y;'S%^;'S;=`%o<%lO%^XDuU]POy%^z![%^![!]EX!];'S%^;'S;=`%o<%lO%^XE`S^PoWOy%^z;'S%^;'S;=`%o<%lO%^_EqS!WVOy%^z;'S%^;'S;=`%o<%lO%^YFSSzQOy%^z;'S%^;'S;=`%o<%lO%^XFeU|POy%^z!`%^!`!aFw!a;'S%^;'S;=`%o<%lO%^XGOS|PoWOy%^z;'S%^;'S;=`%o<%lO%^XG_WOy%^z!c%^!c!}Gw!}#T%^#T#oGw#o;'S%^;'S;=`%o<%lO%^XHO[!YPoWOy%^z}%^}!OGw!O!Q%^!Q![Gw![!c%^!c!}Gw!}#T%^#T#oGw#o;'S%^;'S;=`%o<%lO%^XHySxPOy%^z;'S%^;'S;=`%o<%lO%^^I[SvUOy%^z;'S%^;'S;=`%o<%lO%^XIkUOy%^z#b%^#b#cI}#c;'S%^;'S;=`%o<%lO%^XJSUoWOy%^z#W%^#W#XJf#X;'S%^;'S;=`%o<%lO%^XJmS!`PoWOy%^z;'S%^;'S;=`%o<%lO%^XJ|UOy%^z#f%^#f#gJf#g;'S%^;'S;=`%o<%lO%^XKeS!RPOy%^z;'S%^;'S;=`%o<%lO%^_KvS!QVOy%^z;'S%^;'S;=`%o<%lO%^ZLXU!PPOy%^z!_%^!_!`6y!`;'S%^;'S;=`%o<%lO%^WLnP;=`<%l$}",
tokenizers: [descendant, unitToken, identifiers, 0, 1, 2, 3],
topRules: { "StyleSheet": [0, 4], "Styles": [1, 84] },
specialized: [{ term: 95, get: (value) => spec_callee[value] || -1 }, { term: 56, get: (value) => spec_AtKeyword[value] || -1 }, { term: 96, get: (value) => spec_identifier[value] || -1 }],
tokenPrec: 1123
});
// node_modules/@codemirror/lang-css/dist/index.js
var import_language4 = require("@codemirror/language");
var import_common = require("@lezer/common");
var _properties = null;
function properties() {
if (!_properties && typeof document == "object" && document.body) {
let { style } = document.body, names = [], seen = /* @__PURE__ */ new Set();
for (let prop in style)
if (prop != "cssText" && prop != "cssFloat") {
if (typeof style[prop] == "string") {
if (/[A-Z]/.test(prop))
prop = prop.replace(/[A-Z]/g, (ch) => "-" + ch.toLowerCase());
if (!seen.has(prop)) {
names.push(prop);
seen.add(prop);
}
}
}
_properties = names.sort().map((name) => ({ type: "property", label: name }));
}
return _properties || [];
}
var pseudoClasses = /* @__PURE__ */ [
"active",
"after",
"any-link",
"autofill",
"backdrop",
"before",
"checked",
"cue",
"default",
"defined",
"disabled",
"empty",
"enabled",
"file-selector-button",
"first",
"first-child",
"first-letter",
"first-line",
"first-of-type",
"focus",
"focus-visible",
"focus-within",
"fullscreen",
"has",
"host",
"host-context",
"hover",
"in-range",
"indeterminate",
"invalid",
"is",
"lang",
"last-child",
"last-of-type",
"left",
"link",
"marker",
"modal",
"not",
"nth-child",
"nth-last-child",
"nth-last-of-type",
"nth-of-type",
"only-child",
"only-of-type",
"optional",
"out-of-range",
"part",
"placeholder",
"placeholder-shown",
"read-only",
"read-write",
"required",
"right",
"root",
"scope",
"selection",
"slotted",
"target",
"target-text",
"valid",
"visited",
"where"
].map((name) => ({ type: "class", label: name }));
var values = /* @__PURE__ */ [
"above",
"absolute",
"activeborder",
"additive",
"activecaption",
"after-white-space",
"ahead",
"alias",
"all",
"all-scroll",
"alphabetic",
"alternate",
"always",
"antialiased",
"appworkspace",
"asterisks",
"attr",
"auto",
"auto-flow",
"avoid",
"avoid-column",
"avoid-page",
"avoid-region",
"axis-pan",
"background",
"backwards",
"baseline",
"below",
"bidi-override",
"blink",
"block",
"block-axis",
"bold",
"bolder",
"border",
"border-box",
"both",
"bottom",
"break",
"break-all",
"break-word",
"bullets",
"button",
"button-bevel",
"buttonface",
"buttonhighlight",
"buttonshadow",
"buttontext",
"calc",
"capitalize",
"caps-lock-indicator",
"caption",
"captiontext",
"caret",
"cell",
"center",
"checkbox",
"circle",
"cjk-decimal",
"clear",
"clip",
"close-quote",
"col-resize",
"collapse",
"color",
"color-burn",
"color-dodge",
"column",
"column-reverse",
"compact",
"condensed",
"contain",
"content",
"contents",
"content-box",
"context-menu",
"continuous",
"copy",
"counter",
"counters",
"cover",
"crop",
"cross",
"crosshair",
"currentcolor",
"cursive",
"cyclic",
"darken",
"dashed",
"decimal",
"decimal-leading-zero",
"default",
"default-button",
"dense",
"destination-atop",
"destination-in",
"destination-out",
"destination-over",
"difference",
"disc",
"discard",
"disclosure-closed",
"disclosure-open",
"document",
"dot-dash",
"dot-dot-dash",
"dotted",
"double",
"down",
"e-resize",
"ease",
"ease-in",
"ease-in-out",
"ease-out",
"element",
"ellipse",
"ellipsis",
"embed",
"end",
"ethiopic-abegede-gez",
"ethiopic-halehame-aa-er",
"ethiopic-halehame-gez",
"ew-resize",
"exclusion",
"expanded",
"extends",
"extra-condensed",
"extra-expanded",
"fantasy",
"fast",
"fill",
"fill-box",
"fixed",
"flat",
"flex",
"flex-end",
"flex-start",
"footnotes",
"forwards",
"from",
"geometricPrecision",
"graytext",
"grid",
"groove",
"hand",
"hard-light",
"help",
"hidden",
"hide",
"higher",
"highlight",
"highlighttext",
"horizontal",
"hsl",
"hsla",
"hue",
"icon",
"ignore",
"inactiveborder",
"inactivecaption",
"inactivecaptiontext",
"infinite",
"infobackground",
"infotext",
"inherit",
"initial",
"inline",
"inline-axis",
"inline-block",
"inline-flex",
"inline-grid",
"inline-table",
"inset",
"inside",
"intrinsic",
"invert",
"italic",
"justify",
"keep-all",
"landscape",
"large",
"larger",
"left",
"level",
"lighter",
"lighten",
"line-through",
"linear",
"linear-gradient",
"lines",
"list-item",
"listbox",
"listitem",
"local",
"logical",
"loud",
"lower",
"lower-hexadecimal",
"lower-latin",
"lower-norwegian",
"lowercase",
"ltr",
"luminosity",
"manipulation",
"match",
"matrix",
"matrix3d",
"medium",
"menu",
"menutext",
"message-box",
"middle",
"min-intrinsic",
"mix",
"monospace",
"move",
"multiple",
"multiple_mask_images",
"multiply",
"n-resize",
"narrower",
"ne-resize",
"nesw-resize",
"no-close-quote",
"no-drop",
"no-open-quote",
"no-repeat",
"none",
"normal",
"not-allowed",
"nowrap",
"ns-resize",
"numbers",
"numeric",
"nw-resize",
"nwse-resize",
"oblique",
"opacity",
"open-quote",
"optimizeLegibility",
"optimizeSpeed",
"outset",
"outside",
"outside-shape",
"overlay",
"overline",
"padding",
"padding-box",
"painted",
"page",
"paused",
"perspective",
"pinch-zoom",
"plus-darker",
"plus-lighter",
"pointer",
"polygon",
"portrait",
"pre",
"pre-line",
"pre-wrap",
"preserve-3d",
"progress",
"push-button",
"radial-gradient",
"radio",
"read-only",
"read-write",
"read-write-plaintext-only",
"rectangle",
"region",
"relative",
"repeat",
"repeating-linear-gradient",
"repeating-radial-gradient",
"repeat-x",
"repeat-y",
"reset",
"reverse",
"rgb",
"rgba",
"ridge",
"right",
"rotate",
"rotate3d",
"rotateX",
"rotateY",
"rotateZ",
"round",
"row",
"row-resize",
"row-reverse",
"rtl",
"run-in",
"running",
"s-resize",
"sans-serif",
"saturation",
"scale",
"scale3d",
"scaleX",
"scaleY",
"scaleZ",
"screen",
"scroll",
"scrollbar",
"scroll-position",
"se-resize",
"self-start",
"self-end",
"semi-condensed",
"semi-expanded",
"separate",
"serif",
"show",
"single",
"skew",
"skewX",
"skewY",
"skip-white-space",
"slide",
"slider-horizontal",
"slider-vertical",
"sliderthumb-horizontal",
"sliderthumb-vertical",
"slow",
"small",
"small-caps",
"small-caption",
"smaller",
"soft-light",
"solid",
"source-atop",
"source-in",
"source-out",
"source-over",
"space",
"space-around",
"space-between",
"space-evenly",
"spell-out",
"square",
"start",
"static",
"status-bar",
"stretch",
"stroke",
"stroke-box",
"sub",
"subpixel-antialiased",
"svg_masks",
"super",
"sw-resize",
"symbolic",
"symbols",
"system-ui",
"table",
"table-caption",
"table-cell",
"table-column",
"table-column-group",
"table-footer-group",
"table-header-group",
"table-row",
"table-row-group",
"text",
"text-bottom",
"text-top",
"textarea",
"textfield",
"thick",
"thin",
"threeddarkshadow",
"threedface",
"threedhighlight",
"threedlightshadow",
"threedshadow",
"to",
"top",
"transform",
"translate",
"translate3d",
"translateX",
"translateY",
"translateZ",
"transparent",
"ultra-condensed",
"ultra-expanded",
"underline",
"unidirectional-pan",
"unset",
"up",
"upper-latin",
"uppercase",
"url",
"var",
"vertical",
"vertical-text",
"view-box",
"visible",
"visibleFill",
"visiblePainted",
"visibleStroke",
"visual",
"w-resize",
"wait",
"wave",
"wider",
"window",
"windowframe",
"windowtext",
"words",
"wrap",
"wrap-reverse",
"x-large",
"x-small",
"xor",
"xx-large",
"xx-small"
].map((name) => ({ type: "keyword", label: name })).concat(/* @__PURE__ */ [
"aliceblue",
"antiquewhite",
"aqua",
"aquamarine",
"azure",
"beige",
"bisque",
"black",
"blanchedalmond",
"blue",
"blueviolet",
"brown",
"burlywood",
"cadetblue",
"chartreuse",
"chocolate",
"coral",
"cornflowerblue",
"cornsilk",
"crimson",
"cyan",
"darkblue",
"darkcyan",
"darkgoldenrod",
"darkgray",
"darkgreen",
"darkkhaki",
"darkmagenta",
"darkolivegreen",
"darkorange",
"darkorchid",
"darkred",
"darksalmon",
"darkseagreen",
"darkslateblue",
"darkslategray",
"darkturquoise",
"darkviolet",
"deeppink",
"deepskyblue",
"dimgray",
"dodgerblue",
"firebrick",
"floralwhite",
"forestgreen",
"fuchsia",
"gainsboro",
"ghostwhite",
"gold",
"goldenrod",
"gray",
"grey",
"green",
"greenyellow",
"honeydew",
"hotpink",
"indianred",
"indigo",
"ivory",
"khaki",
"lavender",
"lavenderblush",
"lawngreen",
"lemonchiffon",
"lightblue",
"lightcoral",
"lightcyan",
"lightgoldenrodyellow",
"lightgray",
"lightgreen",
"lightpink",
"lightsalmon",
"lightseagreen",
"lightskyblue",
"lightslategray",
"lightsteelblue",
"lightyellow",
"lime",
"limegreen",
"linen",
"magenta",
"maroon",
"mediumaquamarine",
"mediumblue",
"mediumorchid",
"mediumpurple",
"mediumseagreen",
"mediumslateblue",
"mediumspringgreen",
"mediumturquoise",
"mediumvioletred",
"midnightblue",
"mintcream",
"mistyrose",
"moccasin",
"navajowhite",
"navy",
"oldlace",
"olive",
"olivedrab",
"orange",
"orangered",
"orchid",
"palegoldenrod",
"palegreen",
"paleturquoise",
"palevioletred",
"papayawhip",
"peachpuff",
"peru",
"pink",
"plum",
"powderblue",
"purple",
"rebeccapurple",
"red",
"rosybrown",
"royalblue",
"saddlebrown",
"salmon",
"sandybrown",
"seagreen",
"seashell",
"sienna",
"silver",
"skyblue",
"slateblue",
"slategray",
"snow",
"springgreen",
"steelblue",
"tan",
"teal",
"thistle",
"tomato",
"turquoise",
"violet",
"wheat",
"white",
"whitesmoke",
"yellow",
"yellowgreen"
].map((name) => ({ type: "constant", label: name })));
var tags2 = /* @__PURE__ */ [
"a",
"abbr",
"address",
"article",
"aside",
"b",
"bdi",
"bdo",
"blockquote",
"body",
"br",
"button",
"canvas",
"caption",
"cite",
"code",
"col",
"colgroup",
"dd",
"del",
"details",
"dfn",
"dialog",
"div",
"dl",
"dt",
"em",
"figcaption",
"figure",
"footer",
"form",
"header",
"hgroup",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"hr",
"html",
"i",
"iframe",
"img",
"input",
"ins",
"kbd",
"label",
"legend",
"li",
"main",
"meter",
"nav",
"ol",
"output",
"p",
"pre",
"ruby",
"section",
"select",
"small",
"source",
"span",
"strong",
"sub",
"summary",
"sup",
"table",
"tbody",
"td",
"template",
"textarea",
"tfoot",
"th",
"thead",
"tr",
"u",
"ul"
].map((name) => ({ type: "type", label: name }));
var identifier2 = /^(\w[\w-]*|-\w[\w-]*|)$/;
var variable = /^-(-[\w-]*)?$/;
function isVarArg(node, doc) {
var _a;
if (node.name == "(" || node.type.isError)
node = node.parent || node;
if (node.name != "ArgList")
return false;
let callee2 = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.firstChild;
if ((callee2 === null || callee2 === void 0 ? void 0 : callee2.name) != "Callee")
return false;
return doc.sliceString(callee2.from, callee2.to) == "var";
}
var VariablesByNode = /* @__PURE__ */ new import_common.NodeWeakMap();
var declSelector = ["Declaration"];
function astTop(node) {
for (let cur2 = node; ; ) {
if (cur2.type.isTop)
return cur2;
if (!(cur2 = cur2.parent))
return node;
}
}
function variableNames(doc, node, isVariable) {
if (node.to - node.from > 4096) {
let known = VariablesByNode.get(node);
if (known)
return known;
let result = [], seen = /* @__PURE__ */ new Set(), cursor = node.cursor(import_common.IterMode.IncludeAnonymous);
if (cursor.firstChild())
do {
for (let option of variableNames(doc, cursor.node, isVariable))
if (!seen.has(option.label)) {
seen.add(option.label);
result.push(option);
}
} while (cursor.nextSibling());
VariablesByNode.set(node, result);
return result;
} else {
let result = [], seen = /* @__PURE__ */ new Set();
node.cursor().iterate((node2) => {
var _a;
if (isVariable(node2) && node2.matchContext(declSelector) && ((_a = node2.node.nextSibling) === null || _a === void 0 ? void 0 : _a.name) == ":") {
let name = doc.sliceString(node2.from, node2.to);
if (!seen.has(name)) {
seen.add(name);
result.push({ label: name, type: "variable" });
}
}
});
return result;
}
}
var defineCSSCompletionSource = (isVariable) => (context) => {
let { state, pos } = context, node = (0, import_language4.syntaxTree)(state).resolveInner(pos, -1);
let isDash = node.type.isError && node.from == node.to - 1 && state.doc.sliceString(node.from, node.to) == "-";
if (node.name == "PropertyName" || (isDash || node.name == "TagName") && /^(Block|Styles)$/.test(node.resolve(node.to).name))
return { from: node.from, options: properties(), validFor: identifier2 };
if (node.name == "ValueName")
return { from: node.from, options: values, validFor: identifier2 };
if (node.name == "PseudoClassName")
return { from: node.from, options: pseudoClasses, validFor: identifier2 };
if (isVariable(node) || (context.explicit || isDash) && isVarArg(node, state.doc))
return {
from: isVariable(node) || isDash ? node.from : pos,
options: variableNames(state.doc, astTop(node), isVariable),
validFor: variable
};
if (node.name == "TagName") {
for (let { parent } = node; parent; parent = parent.parent)
if (parent.name == "Block")
return { from: node.from, options: properties(), validFor: identifier2 };
return { from: node.from, options: tags2, validFor: identifier2 };
}
if (!context.explicit)
return null;
let above = node.resolve(pos), before = above.childBefore(pos);
if (before && before.name == ":" && above.name == "PseudoClassSelector")
return { from: pos, options: pseudoClasses, validFor: identifier2 };
if (before && before.name == ":" && above.name == "Declaration" || above.name == "ArgList")
return { from: pos, options: values, validFor: identifier2 };
if (above.name == "Block" || above.name == "Styles")
return { from: pos, options: properties(), validFor: identifier2 };
return null;
};
var cssLanguage = /* @__PURE__ */ import_language4.LRLanguage.define({
name: "css",
parser: /* @__PURE__ */ parser.configure({
props: [
/* @__PURE__ */ import_language4.indentNodeProp.add({
Declaration: /* @__PURE__ */ (0, import_language4.continuedIndent)()
}),
/* @__PURE__ */ import_language4.foldNodeProp.add({
Block: import_language4.foldInside
})
]
}),
languageData: {
commentTokens: { block: { open: "/*", close: "*/" } },
indentOnInput: /^\s*\}$/,
wordChars: "-"
}
});
// src/codemirror-extensions/reconfigured-css.ts
var import_language5 = require("@codemirror/language");
var import_common2 = require("@lezer/common");
var ClassSelectorCtx = ["ClassSelector"];
var IdSelectorCtx = ["IdSelector"];
var SelectorsByNode = {
["class" /* CLASS */]: new import_common2.NodeWeakMap(),
["id" /* ID */]: new import_common2.NodeWeakMap()
};
var Identifier = /^(\w[\w-]*|-\w[\w-]*|)$/;
function getASTTop(node) {
for (let cur2 = node; ; ) {
if (cur2.type.isTop) return cur2;
if (!(cur2 = cur2.parent)) return node;
}
}
function isSelectorIdentifier(node) {
if (node.name == "ClassName") return "class" /* CLASS */;
if (node.name == "IdName") return "id" /* ID */;
return false;
}
function touchSelection(selection, range) {
return selection.ranges.findIndex(
(selRange) => selRange.from <= range.to && selRange.to >= range.from
) >= 0;
}
function getSelectorNames(state, node, type) {
if (node.to - node.from > 4096) {
const known = SelectorsByNode[type].get(node);
if (known) return known;
const result = [], seen = /* @__PURE__ */ new Set(), cursor = node.cursor(import_common2.IterMode.IncludeAnonymous);
if (cursor.firstChild())
do {
for (const option of getSelectorNames(state, cursor.node, type))
if (!seen.has(option.label)) {
seen.add(option.label);
result.push(option);
}
} while (cursor.nextSibling());
SelectorsByNode[type].set(node, result);
return result;
} else {
const result = [], seen = /* @__PURE__ */ new Set(), { doc, selection } = state;
node.cursor().iterate((node2) => {
if (type == isSelectorIdentifier(node2) && !touchSelection(selection, node2)) {
const name = doc.sliceString(node2.from, node2.to);
if (!seen.has(name)) {
seen.add(name);
result.push({ label: name, type: "variable" });
}
}
});
return result;
}
}
var cssCompletionSource = (context) => {
let result = defineCSSCompletionSource(
(node) => node.name == "VariableName"
)(context);
if (!result) {
const { state, pos } = context, node = (0, import_language5.syntaxTree)(state).resolveInner(pos, -1);
if (node.matchContext(ClassSelectorCtx)) {
const isDot = node.name == ".";
result = {
from: isDot ? node.to : node.from,
options: getSelectorNames(
state,
getASTTop(node),
"class" /* CLASS */
),
validFor: Identifier
};
} else if (node.matchContext(IdSelectorCtx)) {
const isHash = node.name == "#";
result = {
from: isHash ? node.to : node.from,
options: getSelectorNames(
state,
getASTTop(node),
"id" /* ID */
),
validFor: Identifier
};
}
}
return result;
};
var css = () => new import_language5.LanguageSupport(
cssLanguage,
cssLanguage.data.of({ autocomplete: cssCompletionSource })
);
// src/codemirror-extensions/highlight-active-line.ts
var import_view4 = require("@codemirror/view");
function highlightActiveLine() {
return activeLineLayer;
}
var activeLineLayer = (0, import_view4.layer)({
above: false,
class: "cm-activeLineLayer",
markers(view) {
const selection = view.state.selection, markers = [], paddingTop = view.documentPadding.top, { width, left: contentLeft } = view.contentDOM.getBoundingClientRect(), { left: scrollerLeft } = view.scrollDOM.getBoundingClientRect();
for (const range of selection.ranges) {
const { top, height } = view.lineBlockAt(range.head), layer2 = new import_view4.RectangleMarker(
"cm-activeLine",
contentLeft - scrollerLeft,
top + paddingTop,
width,
height
);
markers.push(layer2);
}
return markers;
},
update(update) {
return update.docChanged || update.selectionSet || update.viewportChanged || update.geometryChanged;
}
});
// src/codemirror-extensions/basic-extensions.ts
var basicExtensions = [
import_view5.keymap.of([
...closeBracketsKeymap,
// "{|}" -> backspace -> "|"
...import_commands2.defaultKeymap,
...import_search2.searchKeymap,
...import_commands2.historyKeymap,
import_commands2.indentWithTab,
...import_language6.foldKeymap,
...completionKeymap,
...import_lint.lintKeymap
]),
css(),
(0, import_view5.lineNumbers)(),
(0, import_language6.foldGutter)(),
(0, import_view5.highlightActiveLineGutter)(),
(0, import_view5.dropCursor)(),
(0, import_view5.drawSelection)({ drawRangeCursor: true }),
import_state3.EditorState.allowMultipleSelections.of(true),
highlightActiveLine(),
(0, import_language6.indentOnInput)(),
(0, import_language6.bracketMatching)(),
autocompletion(),
closeBrackets(),
(0, import_search2.highlightSelectionMatches)(),
obsidian
].filter((ext) => ext);
// src/views/CssEditorView.ts
var import_commands3 = require("@codemirror/commands");
// src/codemirror-extensions/compartments.ts
var import_state5 = require("@codemirror/state");
// src/codemirror-extensions/relative-line-numbers.ts
var import_view6 = require("@codemirror/view");
var import_state4 = require("@codemirror/state");
var import_language7 = require("@codemirror/language");
var relativeLineNumberGutter = new import_state4.Compartment();
var charLengthCache = /* @__PURE__ */ new WeakMap();
function relativeLineNumbersFormatter(lineNo, state) {
let charLength = charLengthCache.get(state);
if (!charLength) {
charLength = state.doc.lines.toString().length;
charLengthCache.set(state, charLength);
}
if (lineNo > state.doc.lines) {
return " ".padStart(charLength, " ");
}
const selection = state.selection.asSingle();
if (!selection.ranges[0]) {
return " ".padStart(charLength, " ");
}
const cursorLine = state.doc.lineAt(selection.ranges[0].to).number;
const folds = (0, import_language7.foldedRanges)(state);
if (lineNo === cursorLine) {
return lineNo.toString().padStart(charLength, " ");
}
const start = Math.min(cursorLine, lineNo);
const stop = Math.max(cursorLine, lineNo);
let foldedCount = 0;
folds.between(state.doc.line(start).from, state.doc.line(stop).to, () => {
foldedCount++;
});
const distance = Math.abs(cursorLine - lineNo) - foldedCount;
return distance.toString().padStart(charLength, " ");
}
function absoluteLineNumbers(lineNo, state) {
let charLength = charLengthCache.get(state);
if (!charLength) {
charLength = state.doc.lines.toString().length;
charLengthCache.set(state, charLength);
}
return lineNo.toString().padStart(charLength, " ");
}
// src/codemirror-extensions/compartments.ts
var lineWrap = new import_state5.Compartment();
var indentSize = new import_state5.Compartment();
var historyCompartment = new import_state5.Compartment();
// src/views/CssEditorView.ts
var import_language9 = require("@codemirror/language");
// src/modals/CssSnippetRenameModal.ts
var import_obsidian3 = require("obsidian");
// src/utils/handle-error.ts
var import_obsidian2 = require("obsidian");
function handleError(err, fallbackMessage = "Action failed. Reason unknown.") {
let message = fallbackMessage;
if (err instanceof Error) {
message = err.message;
}
new import_obsidian2.Notice(message);
console.error(`[CSS Editor]: ${message}`);
console.error(err);
}
// src/modals/CssSnippetRenameModal.ts
var CssSnippetRenameModal = class extends import_obsidian3.Modal {
constructor(app, file) {
super(app);
this.value = "";
this.file = file;
}
async onOpen() {
await super.onOpen();
this.titleEl.setText("Rename CSS snippet");
this.containerEl.addClass("css-editor-rename-modal");
this.buildForm();
}
buildForm() {
const textInput = new import_obsidian3.TextComponent(this.contentEl);
textInput.setPlaceholder("CSS snippet file name (ex: snippet.css)");
textInput.setValue(this.file.basename);
textInput.onChange((val) => this.value = val);
textInput.inputEl.addEventListener("keydown", (evt) => {
this.handleKeydown(evt);
});
const buttonContainer = this.contentEl.createDiv(
"modal-button-container"
);
new import_obsidian3.ButtonComponent(buttonContainer).setButtonText("Save").setCta().onClick(() => this.save());
new import_obsidian3.ButtonComponent(buttonContainer).setButtonText("Cancel").onClick(() => this.close());
}
handleKeydown(evt) {
if (evt.key === "Escape") {
this.close();
} else if (evt.key === "Enter") {
this.save().catch((err) => {
handleError(err, "Failed to rename CSS file.");
});
}
}
async save() {
try {
await renameSnippetFile(this.app, this.file, this.value);
this.close();
} catch (err) {
handleError(err, "Failed to rename CSS file.");
}
}
};
// src/obsidian/view-helpers.ts
function focusAndSelectElement(el) {
el.focus({ preventScroll: true });
const range = document.createRange();
range.selectNodeContents(el);
const selection = getSelection();
if (selection) {
selection.removeAllRanges();
selection.addRange(range);
}
}
// src/codemirror-extensions/color-picker.ts
var import_view7 = require("@codemirror/view");
var import_obsidian4 = require("obsidian");
// node_modules/color-string/node_modules/color-name/index.js
var color_name_default = {
aliceblue: [240, 248, 255],
antiquewhite: [250, 235, 215],
aqua: [0, 255, 255],
aquamarine: [127, 255, 212],
azure: [240, 255, 255],
beige: [245, 245, 220],
bisque: [255, 228, 196],
black: [0, 0, 0],
blanchedalmond: [255, 235, 205],
blue: [0, 0, 255],
blueviolet: [138, 43, 226],
brown: [165, 42, 42],
burlywood: [222, 184, 135],
cadetblue: [95, 158, 160],
chartreuse: [127, 255, 0],
chocolate: [210, 105, 30],
coral: [255, 127, 80],
cornflowerblue: [100, 149, 237],
cornsilk: [255, 248, 220],
crimson: [220, 20, 60],
cyan: [0, 255, 255],
darkblue: [0, 0, 139],
darkcyan: [0, 139, 139],
darkgoldenrod: [184, 134, 11],
darkgray: [169, 169, 169],
darkgreen: [0, 100, 0],
darkgrey: [169, 169, 169],
darkkhaki: [189, 183, 107],
darkmagenta: [139, 0, 139],
darkolivegreen: [85, 107, 47],
darkorange: [255, 140, 0],
darkorchid: [153, 50, 204],
darkred: [139, 0, 0],
darksalmon: [233, 150, 122],
darkseagreen: [143, 188, 143],
darkslateblue: [72, 61, 139],
darkslategray: [47, 79, 79],
darkslategrey: [47, 79, 79],
darkturquoise: [0, 206, 209],
darkviolet: [148, 0, 211],
deeppink: [255, 20, 147],
deepskyblue: [0, 191, 255],
dimgray: [105, 105, 105],
dimgrey: [105, 105, 105],
dodgerblue: [30, 144, 255],
firebrick: [178, 34, 34],
floralwhite: [255, 250, 240],
forestgreen: [34, 139, 34],
fuchsia: [255, 0, 255],
gainsboro: [220, 220, 220],
ghostwhite: [248, 248, 255],
gold: [255, 215, 0],
goldenrod: [218, 165, 32],
gray: [128, 128, 128],
green: [0, 128, 0],
greenyellow: [173, 255, 47],
grey: [128, 128, 128],
honeydew: [240, 255, 240],
hotpink: [255, 105, 180],
indianred: [205, 92, 92],
indigo: [75, 0, 130],
ivory: [255, 255, 240],
khaki: [240, 230, 140],
lavender: [230, 230, 250],
lavenderblush: [255, 240, 245],
lawngreen: [124, 252, 0],
lemonchiffon: [255, 250, 205],
lightblue: [173, 216, 230],
lightcoral: [240, 128, 128],
lightcyan: [224, 255, 255],
lightgoldenrodyellow: [250, 250, 210],
lightgray: [211, 211, 211],
lightgreen: [144, 238, 144],
lightgrey: [211, 211, 211],
lightpink: [255, 182, 193],
lightsalmon: [255, 160, 122],
lightseagreen: [32, 178, 170],
lightskyblue: [135, 206, 250],
lightslategray: [119, 136, 153],
lightslategrey: [119, 136, 153],
lightsteelblue: [176, 196, 222],
lightyellow: [255, 255, 224],
lime: [0, 255, 0],
limegreen: [50, 205, 50],
linen: [250, 240, 230],
magenta: [255, 0, 255],
maroon: [128, 0, 0],
mediumaquamarine: [102, 205, 170],
mediumblue: [0, 0, 205],
mediumorchid: [186, 85, 211],
mediumpurple: [147, 112, 219],
mediumseagreen: [60, 179, 113],
mediumslateblue: [123, 104, 238],
mediumspringgreen: [0, 250, 154],
mediumturquoise: [72, 209, 204],
mediumvioletred: [199, 21, 133],
midnightblue: [25, 25, 112],
mintcream: [245, 255, 250],
mistyrose: [255, 228, 225],
moccasin: [255, 228, 181],
navajowhite: [255, 222, 173],
navy: [0, 0, 128],
oldlace: [253, 245, 230],
olive: [128, 128, 0],
olivedrab: [107, 142, 35],
orange: [255, 165, 0],
orangered: [255, 69, 0],
orchid: [218, 112, 214],
palegoldenrod: [238, 232, 170],
palegreen: [152, 251, 152],
paleturquoise: [175, 238, 238],
palevioletred: [219, 112, 147],
papayawhip: [255, 239, 213],
peachpuff: [255, 218, 185],
peru: [205, 133, 63],
pink: [255, 192, 203],
plum: [221, 160, 221],
powderblue: [176, 224, 230],
purple: [128, 0, 128],
rebeccapurple: [102, 51, 153],
red: [255, 0, 0],
rosybrown: [188, 143, 143],
royalblue: [65, 105, 225],
saddlebrown: [139, 69, 19],
salmon: [250, 128, 114],
sandybrown: [244, 164, 96],
seagreen: [46, 139, 87],
seashell: [255, 245, 238],
sienna: [160, 82, 45],
silver: [192, 192, 192],
skyblue: [135, 206, 235],
slateblue: [106, 90, 205],
slategray: [112, 128, 144],
slategrey: [112, 128, 144],
snow: [255, 250, 250],
springgreen: [0, 255, 127],
steelblue: [70, 130, 180],
tan: [210, 180, 140],
teal: [0, 128, 128],
thistle: [216, 191, 216],
tomato: [255, 99, 71],
turquoise: [64, 224, 208],
violet: [238, 130, 238],
wheat: [245, 222, 179],
white: [255, 255, 255],
whitesmoke: [245, 245, 245],
yellow: [255, 255, 0],
yellowgreen: [154, 205, 50]
};
// node_modules/color-string/index.js
var reverseNames = /* @__PURE__ */ Object.create(null);
for (const name in color_name_default) {
if (Object.hasOwn(color_name_default, name)) {
reverseNames[color_name_default[name]] = name;
}
}
var cs = {
to: {},
get: {}
};
cs.get = function(string) {
const prefix = string.slice(0, 3).toLowerCase();
let value;
let model;
switch (prefix) {
case "hsl": {
value = cs.get.hsl(string);
model = "hsl";
break;
}
case "hwb": {
value = cs.get.hwb(string);
model = "hwb";
break;
}
default: {
value = cs.get.rgb(string);
model = "rgb";
break;
}
}
if (!value) {
return null;
}
return { model, value };
};
cs.get.rgb = function(string) {
if (!string) {
return null;
}
const abbr = /^#([a-f\d]{3,4})$/i;
const hex = /^#([a-f\d]{6})([a-f\d]{2})?$/i;
const rgba = /^rgba?\(\s*([+-]?\d+)(?=[\s,])\s*(?:,\s*)?([+-]?\d+)(?=[\s,])\s*(?:,\s*)?([+-]?\d+)\s*(?:[,|/]\s*([+-]?[\d.]+)(%?)\s*)?\)$/;
const per = /^rgba?\(\s*([+-]?[\d.]+)%\s*,?\s*([+-]?[\d.]+)%\s*,?\s*([+-]?[\d.]+)%\s*(?:[,|/]\s*([+-]?[\d.]+)(%?)\s*)?\)$/;
const keyword = /^(\w+)$/;
let rgb = [0, 0, 0, 1];
let match;
let i;
let hexAlpha;
if (match = string.match(hex)) {
hexAlpha = match[2];
match = match[1];
for (i = 0; i < 3; i++) {
const i2 = i * 2;
rgb[i] = Number.parseInt(match.slice(i2, i2 + 2), 16);
}
if (hexAlpha) {
rgb[3] = Number.parseInt(hexAlpha, 16) / 255;
}
} else if (match = string.match(abbr)) {
match = match[1];
hexAlpha = match[3];
for (i = 0; i < 3; i++) {
rgb[i] = Number.parseInt(match[i] + match[i], 16);
}
if (hexAlpha) {
rgb[3] = Number.parseInt(hexAlpha + hexAlpha, 16) / 255;
}
} else if (match = string.match(rgba)) {
for (i = 0; i < 3; i++) {
rgb[i] = Number.parseInt(match[i + 1], 10);
}
if (match[4]) {
rgb[3] = match[5] ? Number.parseFloat(match[4]) * 0.01 : Number.parseFloat(match[4]);
}
} else if (match = string.match(per)) {
for (i = 0; i < 3; i++) {
rgb[i] = Math.round(Number.parseFloat(match[i + 1]) * 2.55);
}
if (match[4]) {
rgb[3] = match[5] ? Number.parseFloat(match[4]) * 0.01 : Number.parseFloat(match[4]);
}
} else if (match = string.match(keyword)) {
if (match[1] === "transparent") {
return [0, 0, 0, 0];
}
if (!Object.hasOwn(color_name_default, match[1])) {
return null;
}
rgb = color_name_default[match[1]];
rgb[3] = 1;
return rgb;
} else {
return null;
}
for (i = 0; i < 3; i++) {
rgb[i] = clamp(rgb[i], 0, 255);
}
rgb[3] = clamp(rgb[3], 0, 1);
return rgb;
};
cs.get.hsl = function(string) {
if (!string) {
return null;
}
const hsl = /^hsla?\(\s*([+-]?(?:\d{0,3}\.)?\d+)(?:deg)?\s*,?\s*([+-]?[\d.]+)%\s*,?\s*([+-]?[\d.]+)%\s*(?:[,|/]\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/;
const match = string.match(hsl);
if (match) {
const alpha = Number.parseFloat(match[4]);
const h = (Number.parseFloat(match[1]) % 360 + 360) % 360;
const s = clamp(Number.parseFloat(match[2]), 0, 100);
const l = clamp(Number.parseFloat(match[3]), 0, 100);
const a = clamp(Number.isNaN(alpha) ? 1 : alpha, 0, 1);
return [h, s, l, a];
}
return null;
};
cs.get.hwb = function(string) {
if (!string) {
return null;
}
const hwb = /^hwb\(\s*([+-]?\d{0,3}(?:\.\d+)?)(?:deg)?\s*,\s*([+-]?[\d.]+)%\s*,\s*([+-]?[\d.]+)%\s*(?:,\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/;
const match = string.match(hwb);
if (match) {
const alpha = Number.parseFloat(match[4]);
const h = (Number.parseFloat(match[1]) % 360 + 360) % 360;
const w = clamp(Number.parseFloat(match[2]), 0, 100);
const b = clamp(Number.parseFloat(match[3]), 0, 100);
const a = clamp(Number.isNaN(alpha) ? 1 : alpha, 0, 1);
return [h, w, b, a];
}
return null;
};
cs.to.hex = function(...rgba) {
return "#" + hexDouble(rgba[0]) + hexDouble(rgba[1]) + hexDouble(rgba[2]) + (rgba[3] < 1 ? hexDouble(Math.round(rgba[3] * 255)) : "");
};
cs.to.rgb = function(...rgba) {
return rgba.length < 4 || rgba[3] === 1 ? "rgb(" + Math.round(rgba[0]) + ", " + Math.round(rgba[1]) + ", " + Math.round(rgba[2]) + ")" : "rgba(" + Math.round(rgba[0]) + ", " + Math.round(rgba[1]) + ", " + Math.round(rgba[2]) + ", " + rgba[3] + ")";
};
cs.to.rgb.percent = function(...rgba) {
const r = Math.round(rgba[0] / 255 * 100);
const g = Math.round(rgba[1] / 255 * 100);
const b = Math.round(rgba[2] / 255 * 100);
return rgba.length < 4 || rgba[3] === 1 ? "rgb(" + r + "%, " + g + "%, " + b + "%)" : "rgba(" + r + "%, " + g + "%, " + b + "%, " + rgba[3] + ")";
};
cs.to.hsl = function(...hsla) {
return hsla.length < 4 || hsla[3] === 1 ? "hsl(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%)" : "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, " + hsla[3] + ")";
};
cs.to.hwb = function(...hwba) {
let a = "";
if (hwba.length >= 4 && hwba[3] !== 1) {
a = ", " + hwba[3];
}
return "hwb(" + hwba[0] + ", " + hwba[1] + "%, " + hwba[2] + "%" + a + ")";
};
cs.to.keyword = function(...rgb) {
return reverseNames[rgb.slice(0, 3)];
};
function clamp(number_, min, max) {
return Math.min(Math.max(min, number_), max);
}
function hexDouble(number_) {
const string_ = Math.round(number_).toString(16).toUpperCase();
return string_.length < 2 ? "0" + string_ : string_;
}
var color_string_default = cs;
// node_modules/color/node_modules/color-name/index.js
var color_name_default2 = {
aliceblue: [240, 248, 255],
antiquewhite: [250, 235, 215],
aqua: [0, 255, 255],
aquamarine: [127, 255, 212],
azure: [240, 255, 255],
beige: [245, 245, 220],
bisque: [255, 228, 196],
black: [0, 0, 0],
blanchedalmond: [255, 235, 205],
blue: [0, 0, 255],
blueviolet: [138, 43, 226],
brown: [165, 42, 42],
burlywood: [222, 184, 135],
cadetblue: [95, 158, 160],
chartreuse: [127, 255, 0],
chocolate: [210, 105, 30],
coral: [255, 127, 80],
cornflowerblue: [100, 149, 237],
cornsilk: [255, 248, 220],
crimson: [220, 20, 60],
cyan: [0, 255, 255],
darkblue: [0, 0, 139],
darkcyan: [0, 139, 139],
darkgoldenrod: [184, 134, 11],
darkgray: [169, 169, 169],
darkgreen: [0, 100, 0],
darkgrey: [169, 169, 169],
darkkhaki: [189, 183, 107],
darkmagenta: [139, 0, 139],
darkolivegreen: [85, 107, 47],
darkorange: [255, 140, 0],
darkorchid: [153, 50, 204],
darkred: [139, 0, 0],
darksalmon: [233, 150, 122],
darkseagreen: [143, 188, 143],
darkslateblue: [72, 61, 139],
darkslategray: [47, 79, 79],
darkslategrey: [47, 79, 79],
darkturquoise: [0, 206, 209],
darkviolet: [148, 0, 211],
deeppink: [255, 20, 147],
deepskyblue: [0, 191, 255],
dimgray: [105, 105, 105],
dimgrey: [105, 105, 105],
dodgerblue: [30, 144, 255],
firebrick: [178, 34, 34],
floralwhite: [255, 250, 240],
forestgreen: [34, 139, 34],
fuchsia: [255, 0, 255],
gainsboro: [220, 220, 220],
ghostwhite: [248, 248, 255],
gold: [255, 215, 0],
goldenrod: [218, 165, 32],
gray: [128, 128, 128],
green: [0, 128, 0],
greenyellow: [173, 255, 47],
grey: [128, 128, 128],
honeydew: [240, 255, 240],
hotpink: [255, 105, 180],
indianred: [205, 92, 92],
indigo: [75, 0, 130],
ivory: [255, 255, 240],
khaki: [240, 230, 140],
lavender: [230, 230, 250],
lavenderblush: [255, 240, 245],
lawngreen: [124, 252, 0],
lemonchiffon: [255, 250, 205],
lightblue: [173, 216, 230],
lightcoral: [240, 128, 128],
lightcyan: [224, 255, 255],
lightgoldenrodyellow: [250, 250, 210],
lightgray: [211, 211, 211],
lightgreen: [144, 238, 144],
lightgrey: [211, 211, 211],
lightpink: [255, 182, 193],
lightsalmon: [255, 160, 122],
lightseagreen: [32, 178, 170],
lightskyblue: [135, 206, 250],
lightslategray: [119, 136, 153],
lightslategrey: [119, 136, 153],
lightsteelblue: [176, 196, 222],
lightyellow: [255, 255, 224],
lime: [0, 255, 0],
limegreen: [50, 205, 50],
linen: [250, 240, 230],
magenta: [255, 0, 255],
maroon: [128, 0, 0],
mediumaquamarine: [102, 205, 170],
mediumblue: [0, 0, 205],
mediumorchid: [186, 85, 211],
mediumpurple: [147, 112, 219],
mediumseagreen: [60, 179, 113],
mediumslateblue: [123, 104, 238],
mediumspringgreen: [0, 250, 154],
mediumturquoise: [72, 209, 204],
mediumvioletred: [199, 21, 133],
midnightblue: [25, 25, 112],
mintcream: [245, 255, 250],
mistyrose: [255, 228, 225],
moccasin: [255, 228, 181],
navajowhite: [255, 222, 173],
navy: [0, 0, 128],
oldlace: [253, 245, 230],
olive: [128, 128, 0],
olivedrab: [107, 142, 35],
orange: [255, 165, 0],
orangered: [255, 69, 0],
orchid: [218, 112, 214],
palegoldenrod: [238, 232, 170],
palegreen: [152, 251, 152],
paleturquoise: [175, 238, 238],
palevioletred: [219, 112, 147],
papayawhip: [255, 239, 213],
peachpuff: [255, 218, 185],
peru: [205, 133, 63],
pink: [255, 192, 203],
plum: [221, 160, 221],
powderblue: [176, 224, 230],
purple: [128, 0, 128],
rebeccapurple: [102, 51, 153],
red: [255, 0, 0],
rosybrown: [188, 143, 143],
royalblue: [65, 105, 225],
saddlebrown: [139, 69, 19],
salmon: [250, 128, 114],
sandybrown: [244, 164, 96],
seagreen: [46, 139, 87],
seashell: [255, 245, 238],
sienna: [160, 82, 45],
silver: [192, 192, 192],
skyblue: [135, 206, 235],
slateblue: [106, 90, 205],
slategray: [112, 128, 144],
slategrey: [112, 128, 144],
snow: [255, 250, 250],
springgreen: [0, 255, 127],
steelblue: [70, 130, 180],
tan: [210, 180, 140],
teal: [0, 128, 128],
thistle: [216, 191, 216],
tomato: [255, 99, 71],
turquoise: [64, 224, 208],
violet: [238, 130, 238],
wheat: [245, 222, 179],
white: [255, 255, 255],
whitesmoke: [245, 245, 245],
yellow: [255, 255, 0],
yellowgreen: [154, 205, 50]
};
// node_modules/color/node_modules/color-convert/conversions.js
var reverseKeywords = {};
for (const key of Object.keys(color_name_default2)) {
reverseKeywords[color_name_default2[key]] = key;
}
var convert = {
rgb: { channels: 3, labels: "rgb" },
hsl: { channels: 3, labels: "hsl" },
hsv: { channels: 3, labels: "hsv" },
hwb: { channels: 3, labels: "hwb" },
cmyk: { channels: 4, labels: "cmyk" },
xyz: { channels: 3, labels: "xyz" },
lab: { channels: 3, labels: "lab" },
oklab: { channels: 3, labels: ["okl", "oka", "okb"] },
lch: { channels: 3, labels: "lch" },
oklch: { channels: 3, labels: ["okl", "okc", "okh"] },
hex: { channels: 1, labels: ["hex"] },
keyword: { channels: 1, labels: ["keyword"] },
ansi16: { channels: 1, labels: ["ansi16"] },
ansi256: { channels: 1, labels: ["ansi256"] },
hcg: { channels: 3, labels: ["h", "c", "g"] },
apple: { channels: 3, labels: ["r16", "g16", "b16"] },
gray: { channels: 1, labels: ["gray"] }
};
var conversions_default = convert;
var LAB_FT = (6 / 29) ** 3;
function srgbNonlinearTransform(c) {
const cc = c > 31308e-7 ? 1.055 * c ** (1 / 2.4) - 0.055 : c * 12.92;
return Math.min(Math.max(0, cc), 1);
}
function srgbNonlinearTransformInv(c) {
return c > 0.04045 ? ((c + 0.055) / 1.055) ** 2.4 : c / 12.92;
}
for (const model of Object.keys(convert)) {
if (!("channels" in convert[model])) {
throw new Error("missing channels property: " + model);
}
if (!("labels" in convert[model])) {
throw new Error("missing channel labels property: " + model);
}
if (convert[model].labels.length !== convert[model].channels) {
throw new Error("channel and label counts mismatch: " + model);
}
const { channels, labels } = convert[model];
delete convert[model].channels;
delete convert[model].labels;
Object.defineProperty(convert[model], "channels", { value: channels });
Object.defineProperty(convert[model], "labels", { value: labels });
}
convert.rgb.hsl = function(rgb) {
const r = rgb[0] / 255;
const g = rgb[1] / 255;
const b = rgb[2] / 255;
const min = Math.min(r, g, b);
const max = Math.max(r, g, b);
const delta = max - min;
let h;
let s;
switch (max) {
case min: {
h = 0;
break;
}
case r: {
h = (g - b) / delta;
break;
}
case g: {
h = 2 + (b - r) / delta;
break;
}
case b: {
h = 4 + (r - g) / delta;
break;
}
}
h = Math.min(h * 60, 360);
if (h < 0) {
h += 360;
}
const l = (min + max) / 2;
if (max === min) {
s = 0;
} else if (l <= 0.5) {
s = delta / (max + min);
} else {
s = delta / (2 - max - min);
}
return [h, s * 100, l * 100];
};
convert.rgb.hsv = function(rgb) {
let rdif;
let gdif;
let bdif;
let h;
let s;
const r = rgb[0] / 255;
const g = rgb[1] / 255;
const b = rgb[2] / 255;
const v = Math.max(r, g, b);
const diff = v - Math.min(r, g, b);
const diffc = function(c) {
return (v - c) / 6 / diff + 1 / 2;
};
if (diff === 0) {
h = 0;
s = 0;
} else {
s = diff / v;
rdif = diffc(r);
gdif = diffc(g);
bdif = diffc(b);
switch (v) {
case r: {
h = bdif - gdif;
break;
}
case g: {
h = 1 / 3 + rdif - bdif;
break;
}
case b: {
h = 2 / 3 + gdif - rdif;
break;
}
}
if (h < 0) {
h += 1;
} else if (h > 1) {
h -= 1;
}
}
return [
h * 360,
s * 100,
v * 100
];
};
convert.rgb.hwb = function(rgb) {
const r = rgb[0];
const g = rgb[1];
let b = rgb[2];
const h = convert.rgb.hsl(rgb)[0];
const w = 1 / 255 * Math.min(r, Math.min(g, b));
b = 1 - 1 / 255 * Math.max(r, Math.max(g, b));
return [h, w * 100, b * 100];
};
convert.rgb.oklab = function(rgb) {
const r = srgbNonlinearTransformInv(rgb[0] / 255);
const g = srgbNonlinearTransformInv(rgb[1] / 255);
const b = srgbNonlinearTransformInv(rgb[2] / 255);
const lp = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
const mp = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
const sp = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
const l = 0.2104542553 * lp + 0.793617785 * mp - 0.0040720468 * sp;
const aa = 1.9779984951 * lp - 2.428592205 * mp + 0.4505937099 * sp;
const bb = 0.0259040371 * lp + 0.7827717662 * mp - 0.808675766 * sp;
return [l * 100, aa * 100, bb * 100];
};
convert.rgb.cmyk = function(rgb) {
const r = rgb[0] / 255;
const g = rgb[1] / 255;
const b = rgb[2] / 255;
const k = Math.min(1 - r, 1 - g, 1 - b);
const c = (1 - r - k) / (1 - k) || 0;
const m = (1 - g - k) / (1 - k) || 0;
const y = (1 - b - k) / (1 - k) || 0;
return [c * 100, m * 100, y * 100, k * 100];
};
function comparativeDistance(x, y) {
return (x[0] - y[0]) ** 2 + (x[1] - y[1]) ** 2 + (x[2] - y[2]) ** 2;
}
convert.rgb.keyword = function(rgb) {
const reversed = reverseKeywords[rgb];
if (reversed) {
return reversed;
}
let currentClosestDistance = Number.POSITIVE_INFINITY;
let currentClosestKeyword;
for (const keyword of Object.keys(color_name_default2)) {
const value = color_name_default2[keyword];
const distance = comparativeDistance(rgb, value);
if (distance < currentClosestDistance) {
currentClosestDistance = distance;
currentClosestKeyword = keyword;
}
}
return currentClosestKeyword;
};
convert.keyword.rgb = function(keyword) {
return color_name_default2[keyword];
};
convert.rgb.xyz = function(rgb) {
const r = srgbNonlinearTransformInv(rgb[0] / 255);
const g = srgbNonlinearTransformInv(rgb[1] / 255);
const b = srgbNonlinearTransformInv(rgb[2] / 255);
const x = r * 0.4124564 + g * 0.3575761 + b * 0.1804375;
const y = r * 0.2126729 + g * 0.7151522 + b * 0.072175;
const z = r * 0.0193339 + g * 0.119192 + b * 0.9503041;
return [x * 100, y * 100, z * 100];
};
convert.rgb.lab = function(rgb) {
const xyz = convert.rgb.xyz(rgb);
let x = xyz[0];
let y = xyz[1];
let z = xyz[2];
x /= 95.047;
y /= 100;
z /= 108.883;
x = x > LAB_FT ? x ** (1 / 3) : 7.787 * x + 16 / 116;
y = y > LAB_FT ? y ** (1 / 3) : 7.787 * y + 16 / 116;
z = z > LAB_FT ? z ** (1 / 3) : 7.787 * z + 16 / 116;
const l = 116 * y - 16;
const a = 500 * (x - y);
const b = 200 * (y - z);
return [l, a, b];
};
convert.hsl.rgb = function(hsl) {
const h = hsl[0] / 360;
const s = hsl[1] / 100;
const l = hsl[2] / 100;
let t3;
let value;
if (s === 0) {
value = l * 255;
return [value, value, value];
}
const t2 = l < 0.5 ? l * (1 + s) : l + s - l * s;
const t1 = 2 * l - t2;
const rgb = [0, 0, 0];
for (let i = 0; i < 3; i++) {
t3 = h + 1 / 3 * -(i - 1);
if (t3 < 0) {
t3++;
}
if (t3 > 1) {
t3--;
}
if (6 * t3 < 1) {
value = t1 + (t2 - t1) * 6 * t3;
} else if (2 * t3 < 1) {
value = t2;
} else if (3 * t3 < 2) {
value = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
} else {
value = t1;
}
rgb[i] = value * 255;
}
return rgb;
};
convert.hsl.hsv = function(hsl) {
const h = hsl[0];
let s = hsl[1] / 100;
let l = hsl[2] / 100;
let smin = s;
const lmin = Math.max(l, 0.01);
l *= 2;
s *= l <= 1 ? l : 2 - l;
smin *= lmin <= 1 ? lmin : 2 - lmin;
const v = (l + s) / 2;
const sv = l === 0 ? 2 * smin / (lmin + smin) : 2 * s / (l + s);
return [h, sv * 100, v * 100];
};
convert.hsv.rgb = function(hsv) {
const h = hsv[0] / 60;
const s = hsv[1] / 100;
let v = hsv[2] / 100;
const hi = Math.floor(h) % 6;
const f = h - Math.floor(h);
const p = 255 * v * (1 - s);
const q = 255 * v * (1 - s * f);
const t2 = 255 * v * (1 - s * (1 - f));
v *= 255;
switch (hi) {
case 0: {
return [v, t2, p];
}
case 1: {
return [q, v, p];
}
case 2: {
return [p, v, t2];
}
case 3: {
return [p, q, v];
}
case 4: {
return [t2, p, v];
}
case 5: {
return [v, p, q];
}
}
};
convert.hsv.hsl = function(hsv) {
const h = hsv[0];
const s = hsv[1] / 100;
const v = hsv[2] / 100;
const vmin = Math.max(v, 0.01);
let sl;
let l;
l = (2 - s) * v;
const lmin = (2 - s) * vmin;
sl = s * vmin;
sl /= lmin <= 1 ? lmin : 2 - lmin;
sl = sl || 0;
l /= 2;
return [h, sl * 100, l * 100];
};
convert.hwb.rgb = function(hwb) {
const h = hwb[0] / 360;
let wh = hwb[1] / 100;
let bl = hwb[2] / 100;
const ratio = wh + bl;
let f;
if (ratio > 1) {
wh /= ratio;
bl /= ratio;
}
const i = Math.floor(6 * h);
const v = 1 - bl;
f = 6 * h - i;
if ((i & 1) !== 0) {
f = 1 - f;
}
const n = wh + f * (v - wh);
let r;
let g;
let b;
switch (i) {
default:
case 6:
case 0: {
r = v;
g = n;
b = wh;
break;
}
case 1: {
r = n;
g = v;
b = wh;
break;
}
case 2: {
r = wh;
g = v;
b = n;
break;
}
case 3: {
r = wh;
g = n;
b = v;
break;
}
case 4: {
r = n;
g = wh;
b = v;
break;
}
case 5: {
r = v;
g = wh;
b = n;
break;
}
}
return [r * 255, g * 255, b * 255];
};
convert.cmyk.rgb = function(cmyk) {
const c = cmyk[0] / 100;
const m = cmyk[1] / 100;
const y = cmyk[2] / 100;
const k = cmyk[3] / 100;
const r = 1 - Math.min(1, c * (1 - k) + k);
const g = 1 - Math.min(1, m * (1 - k) + k);
const b = 1 - Math.min(1, y * (1 - k) + k);
return [r * 255, g * 255, b * 255];
};
convert.xyz.rgb = function(xyz) {
const x = xyz[0] / 100;
const y = xyz[1] / 100;
const z = xyz[2] / 100;
let r;
let g;
let b;
r = x * 3.2404542 + y * -1.5371385 + z * -0.4985314;
g = x * -0.969266 + y * 1.8760108 + z * 0.041556;
b = x * 0.0556434 + y * -0.2040259 + z * 1.0572252;
r = srgbNonlinearTransform(r);
g = srgbNonlinearTransform(g);
b = srgbNonlinearTransform(b);
return [r * 255, g * 255, b * 255];
};
convert.xyz.lab = function(xyz) {
let x = xyz[0];
let y = xyz[1];
let z = xyz[2];
x /= 95.047;
y /= 100;
z /= 108.883;
x = x > LAB_FT ? x ** (1 / 3) : 7.787 * x + 16 / 116;
y = y > LAB_FT ? y ** (1 / 3) : 7.787 * y + 16 / 116;
z = z > LAB_FT ? z ** (1 / 3) : 7.787 * z + 16 / 116;
const l = 116 * y - 16;
const a = 500 * (x - y);
const b = 200 * (y - z);
return [l, a, b];
};
convert.xyz.oklab = function(xyz) {
const x = xyz[0] / 100;
const y = xyz[1] / 100;
const z = xyz[2] / 100;
const lp = Math.cbrt(0.8189330101 * x + 0.3618667424 * y - 0.1288597137 * z);
const mp = Math.cbrt(0.0329845436 * x + 0.9293118715 * y + 0.0361456387 * z);
const sp = Math.cbrt(0.0482003018 * x + 0.2643662691 * y + 0.633851707 * z);
const l = 0.2104542553 * lp + 0.793617785 * mp - 0.0040720468 * sp;
const a = 1.9779984951 * lp - 2.428592205 * mp + 0.4505937099 * sp;
const b = 0.0259040371 * lp + 0.7827717662 * mp - 0.808675766 * sp;
return [l * 100, a * 100, b * 100];
};
convert.oklab.oklch = function(oklab) {
return convert.lab.lch(oklab);
};
convert.oklab.xyz = function(oklab) {
const ll = oklab[0] / 100;
const a = oklab[1] / 100;
const b = oklab[2] / 100;
const l = (0.999999998 * ll + 0.396337792 * a + 0.215803758 * b) ** 3;
const m = (1.000000008 * ll - 0.105561342 * a - 0.063854175 * b) ** 3;
const s = (1.000000055 * ll - 0.089484182 * a - 1.291485538 * b) ** 3;
const x = 1.227013851 * l - 0.55779998 * m + 0.281256149 * s;
const y = -0.040580178 * l + 1.11225687 * m - 0.071676679 * s;
const z = -0.076381285 * l - 0.421481978 * m + 1.58616322 * s;
return [x * 100, y * 100, z * 100];
};
convert.oklab.rgb = function(oklab) {
const ll = oklab[0] / 100;
const aa = oklab[1] / 100;
const bb = oklab[2] / 100;
const l = (ll + 0.3963377774 * aa + 0.2158037573 * bb) ** 3;
const m = (ll - 0.1055613458 * aa - 0.0638541728 * bb) ** 3;
const s = (ll - 0.0894841775 * aa - 1.291485548 * bb) ** 3;
const r = srgbNonlinearTransform(4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s);
const g = srgbNonlinearTransform(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s);
const b = srgbNonlinearTransform(-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s);
return [r * 255, g * 255, b * 255];
};
convert.oklch.oklab = function(oklch) {
return convert.lch.lab(oklch);
};
convert.lab.xyz = function(lab) {
const l = lab[0];
const a = lab[1];
const b = lab[2];
let x;
let y;
let z;
y = (l + 16) / 116;
x = a / 500 + y;
z = y - b / 200;
const y2 = y ** 3;
const x2 = x ** 3;
const z2 = z ** 3;
y = y2 > LAB_FT ? y2 : (y - 16 / 116) / 7.787;
x = x2 > LAB_FT ? x2 : (x - 16 / 116) / 7.787;
z = z2 > LAB_FT ? z2 : (z - 16 / 116) / 7.787;
x *= 95.047;
y *= 100;
z *= 108.883;
return [x, y, z];
};
convert.lab.lch = function(lab) {
const l = lab[0];
const a = lab[1];
const b = lab[2];
let h;
const hr = Math.atan2(b, a);
h = hr * 360 / 2 / Math.PI;
if (h < 0) {
h += 360;
}
const c = Math.sqrt(a * a + b * b);
return [l, c, h];
};
convert.lch.lab = function(lch) {
const l = lch[0];
const c = lch[1];
const h = lch[2];
const hr = h / 360 * 2 * Math.PI;
const a = c * Math.cos(hr);
const b = c * Math.sin(hr);
return [l, a, b];
};
convert.rgb.ansi16 = function(args, saturation = null) {
const [r, g, b] = args;
let value = saturation === null ? convert.rgb.hsv(args)[2] : saturation;
value = Math.round(value / 50);
if (value === 0) {
return 30;
}
let ansi = 30 + (Math.round(b / 255) << 2 | Math.round(g / 255) << 1 | Math.round(r / 255));
if (value === 2) {
ansi += 60;
}
return ansi;
};
convert.hsv.ansi16 = function(args) {
return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]);
};
convert.rgb.ansi256 = function(args) {
const r = args[0];
const g = args[1];
const b = args[2];
if (r >> 4 === g >> 4 && g >> 4 === b >> 4) {
if (r < 8) {
return 16;
}
if (r > 248) {
return 231;
}
return Math.round((r - 8) / 247 * 24) + 232;
}
const ansi = 16 + 36 * Math.round(r / 255 * 5) + 6 * Math.round(g / 255 * 5) + Math.round(b / 255 * 5);
return ansi;
};
convert.ansi16.rgb = function(args) {
args = args[0];
let color = args % 10;
if (color === 0 || color === 7) {
if (args > 50) {
color += 3.5;
}
color = color / 10.5 * 255;
return [color, color, color];
}
const mult = (Math.trunc(args > 50) + 1) * 0.5;
const r = (color & 1) * mult * 255;
const g = (color >> 1 & 1) * mult * 255;
const b = (color >> 2 & 1) * mult * 255;
return [r, g, b];
};
convert.ansi256.rgb = function(args) {
args = args[0];
if (args >= 232) {
const c = (args - 232) * 10 + 8;
return [c, c, c];
}
args -= 16;
let rem;
const r = Math.floor(args / 36) / 5 * 255;
const g = Math.floor((rem = args % 36) / 6) / 5 * 255;
const b = rem % 6 / 5 * 255;
return [r, g, b];
};
convert.rgb.hex = function(args) {
const integer = ((Math.round(args[0]) & 255) << 16) + ((Math.round(args[1]) & 255) << 8) + (Math.round(args[2]) & 255);
const string = integer.toString(16).toUpperCase();
return "000000".slice(string.length) + string;
};
convert.hex.rgb = function(args) {
const match = args.toString(16).match(/[a-f\d]{6}|[a-f\d]{3}/i);
if (!match) {
return [0, 0, 0];
}
let colorString = match[0];
if (match[0].length === 3) {
colorString = [...colorString].map((char) => char + char).join("");
}
const integer = Number.parseInt(colorString, 16);
const r = integer >> 16 & 255;
const g = integer >> 8 & 255;
const b = integer & 255;
return [r, g, b];
};
convert.rgb.hcg = function(rgb) {
const r = rgb[0] / 255;
const g = rgb[1] / 255;
const b = rgb[2] / 255;
const max = Math.max(Math.max(r, g), b);
const min = Math.min(Math.min(r, g), b);
const chroma = max - min;
let hue;
const grayscale = chroma < 1 ? min / (1 - chroma) : 0;
if (chroma <= 0) {
hue = 0;
} else if (max === r) {
hue = (g - b) / chroma % 6;
} else if (max === g) {
hue = 2 + (b - r) / chroma;
} else {
hue = 4 + (r - g) / chroma;
}
hue /= 6;
hue %= 1;
return [hue * 360, chroma * 100, grayscale * 100];
};
convert.hsl.hcg = function(hsl) {
const s = hsl[1] / 100;
const l = hsl[2] / 100;
const c = l < 0.5 ? 2 * s * l : 2 * s * (1 - l);
let f = 0;
if (c < 1) {
f = (l - 0.5 * c) / (1 - c);
}
return [hsl[0], c * 100, f * 100];
};
convert.hsv.hcg = function(hsv) {
const s = hsv[1] / 100;
const v = hsv[2] / 100;
const c = s * v;
let f = 0;
if (c < 1) {
f = (v - c) / (1 - c);
}
return [hsv[0], c * 100, f * 100];
};
convert.hcg.rgb = function(hcg) {
const h = hcg[0] / 360;
const c = hcg[1] / 100;
const g = hcg[2] / 100;
if (c === 0) {
return [g * 255, g * 255, g * 255];
}
const pure = [0, 0, 0];
const hi = h % 1 * 6;
const v = hi % 1;
const w = 1 - v;
let mg = 0;
switch (Math.floor(hi)) {
case 0: {
pure[0] = 1;
pure[1] = v;
pure[2] = 0;
break;
}
case 1: {
pure[0] = w;
pure[1] = 1;
pure[2] = 0;
break;
}
case 2: {
pure[0] = 0;
pure[1] = 1;
pure[2] = v;
break;
}
case 3: {
pure[0] = 0;
pure[1] = w;
pure[2] = 1;
break;
}
case 4: {
pure[0] = v;
pure[1] = 0;
pure[2] = 1;
break;
}
default: {
pure[0] = 1;
pure[1] = 0;
pure[2] = w;
}
}
mg = (1 - c) * g;
return [
(c * pure[0] + mg) * 255,
(c * pure[1] + mg) * 255,
(c * pure[2] + mg) * 255
];
};
convert.hcg.hsv = function(hcg) {
const c = hcg[1] / 100;
const g = hcg[2] / 100;
const v = c + g * (1 - c);
let f = 0;
if (v > 0) {
f = c / v;
}
return [hcg[0], f * 100, v * 100];
};
convert.hcg.hsl = function(hcg) {
const c = hcg[1] / 100;
const g = hcg[2] / 100;
const l = g * (1 - c) + 0.5 * c;
let s = 0;
if (l > 0 && l < 0.5) {
s = c / (2 * l);
} else if (l >= 0.5 && l < 1) {
s = c / (2 * (1 - l));
}
return [hcg[0], s * 100, l * 100];
};
convert.hcg.hwb = function(hcg) {
const c = hcg[1] / 100;
const g = hcg[2] / 100;
const v = c + g * (1 - c);
return [hcg[0], (v - c) * 100, (1 - v) * 100];
};
convert.hwb.hcg = function(hwb) {
const w = hwb[1] / 100;
const b = hwb[2] / 100;
const v = 1 - b;
const c = v - w;
let g = 0;
if (c < 1) {
g = (v - c) / (1 - c);
}
return [hwb[0], c * 100, g * 100];
};
convert.apple.rgb = function(apple) {
return [apple[0] / 65535 * 255, apple[1] / 65535 * 255, apple[2] / 65535 * 255];
};
convert.rgb.apple = function(rgb) {
return [rgb[0] / 255 * 65535, rgb[1] / 255 * 65535, rgb[2] / 255 * 65535];
};
convert.gray.rgb = function(args) {
return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255];
};
convert.gray.hsl = function(args) {
return [0, 0, args[0]];
};
convert.gray.hsv = convert.gray.hsl;
convert.gray.hwb = function(gray) {
return [0, 100, gray[0]];
};
convert.gray.cmyk = function(gray) {
return [0, 0, 0, gray[0]];
};
convert.gray.lab = function(gray) {
return [gray[0], 0, 0];
};
convert.gray.hex = function(gray) {
const value = Math.round(gray[0] / 100 * 255) & 255;
const integer = (value << 16) + (value << 8) + value;
const string = integer.toString(16).toUpperCase();
return "000000".slice(string.length) + string;
};
convert.rgb.gray = function(rgb) {
const value = (rgb[0] + rgb[1] + rgb[2]) / 3;
return [value / 255 * 100];
};
// node_modules/color/node_modules/color-convert/route.js
function buildGraph() {
const graph = {};
const models2 = Object.keys(conversions_default);
for (let { length } = models2, i = 0; i < length; i++) {
graph[models2[i]] = {
// http://jsperf.com/1-vs-infinity
// micro-opt, but this is simple.
distance: -1,
parent: null
};
}
return graph;
}
function deriveBFS(fromModel) {
const graph = buildGraph();
const queue = [fromModel];
graph[fromModel].distance = 0;
while (queue.length > 0) {
const current = queue.pop();
const adjacents = Object.keys(conversions_default[current]);
for (let { length } = adjacents, i = 0; i < length; i++) {
const adjacent = adjacents[i];
const node = graph[adjacent];
if (node.distance === -1) {
node.distance = graph[current].distance + 1;
node.parent = current;
queue.unshift(adjacent);
}
}
}
return graph;
}
function link(from, to) {
return function(args) {
return to(from(args));
};
}
function wrapConversion(toModel, graph) {
const path = [graph[toModel].parent, toModel];
let fn = conversions_default[graph[toModel].parent][toModel];
let cur2 = graph[toModel].parent;
while (graph[cur2].parent) {
path.unshift(graph[cur2].parent);
fn = link(conversions_default[graph[cur2].parent][cur2], fn);
cur2 = graph[cur2].parent;
}
fn.conversion = path;
return fn;
}
function route(fromModel) {
const graph = deriveBFS(fromModel);
const conversion = {};
const models2 = Object.keys(graph);
for (let { length } = models2, i = 0; i < length; i++) {
const toModel = models2[i];
const node = graph[toModel];
if (node.parent === null) {
continue;
}
conversion[toModel] = wrapConversion(toModel, graph);
}
return conversion;
}
var route_default = route;
// node_modules/color/node_modules/color-convert/index.js
var convert2 = {};
var models = Object.keys(conversions_default);
function wrapRaw(fn) {
const wrappedFn = function(...args) {
const arg0 = args[0];
if (arg0 === void 0 || arg0 === null) {
return arg0;
}
if (arg0.length > 1) {
args = arg0;
}
return fn(args);
};
if ("conversion" in fn) {
wrappedFn.conversion = fn.conversion;
}
return wrappedFn;
}
function wrapRounded(fn) {
const wrappedFn = function(...args) {
const arg0 = args[0];
if (arg0 === void 0 || arg0 === null) {
return arg0;
}
if (arg0.length > 1) {
args = arg0;
}
const result = fn(args);
if (typeof result === "object") {
for (let { length } = result, i = 0; i < length; i++) {
result[i] = Math.round(result[i]);
}
}
return result;
};
if ("conversion" in fn) {
wrappedFn.conversion = fn.conversion;
}
return wrappedFn;
}
for (const fromModel of models) {
convert2[fromModel] = {};
Object.defineProperty(convert2[fromModel], "channels", { value: conversions_default[fromModel].channels });
Object.defineProperty(convert2[fromModel], "labels", { value: conversions_default[fromModel].labels });
const routes = route_default(fromModel);
const routeModels = Object.keys(routes);
for (const toModel of routeModels) {
const fn = routes[toModel];
convert2[fromModel][toModel] = wrapRounded(fn);
convert2[fromModel][toModel].raw = wrapRaw(fn);
}
}
var color_convert_default = convert2;
// node_modules/color/index.js
var skippedModels = [
// To be honest, I don't really feel like keyword belongs in color convert, but eh.
"keyword",
// Gray conflicts with some method names, and has its own method defined.
"gray",
// Shouldn't really be in color-convert either...
"hex"
];
var hashedModelKeys = {};
for (const model of Object.keys(color_convert_default)) {
hashedModelKeys[[...color_convert_default[model].labels].sort().join("")] = model;
}
var limiters = {};
function Color(object, model) {
if (!(this instanceof Color)) {
return new Color(object, model);
}
if (model && model in skippedModels) {
model = null;
}
if (model && !(model in color_convert_default)) {
throw new Error("Unknown model: " + model);
}
let i;
let channels;
if (object == null) {
this.model = "rgb";
this.color = [0, 0, 0];
this.valpha = 1;
} else if (object instanceof Color) {
this.model = object.model;
this.color = [...object.color];
this.valpha = object.valpha;
} else if (typeof object === "string") {
const result = color_string_default.get(object);
if (result === null) {
throw new Error("Unable to parse color from string: " + object);
}
this.model = result.model;
channels = color_convert_default[this.model].channels;
this.color = result.value.slice(0, channels);
this.valpha = typeof result.value[channels] === "number" ? result.value[channels] : 1;
} else if (object.length > 0) {
this.model = model || "rgb";
channels = color_convert_default[this.model].channels;
const newArray = Array.prototype.slice.call(object, 0, channels);
this.color = zeroArray(newArray, channels);
this.valpha = typeof object[channels] === "number" ? object[channels] : 1;
} else if (typeof object === "number") {
this.model = "rgb";
this.color = [
object >> 16 & 255,
object >> 8 & 255,
object & 255
];
this.valpha = 1;
} else {
this.valpha = 1;
const keys2 = Object.keys(object);
if ("alpha" in object) {
keys2.splice(keys2.indexOf("alpha"), 1);
this.valpha = typeof object.alpha === "number" ? object.alpha : 0;
}
const hashedKeys = keys2.sort().join("");
if (!(hashedKeys in hashedModelKeys)) {
throw new Error("Unable to parse color from object: " + JSON.stringify(object));
}
this.model = hashedModelKeys[hashedKeys];
const { labels } = color_convert_default[this.model];
const color = [];
for (i = 0; i < labels.length; i++) {
color.push(object[labels[i]]);
}
this.color = zeroArray(color);
}
if (limiters[this.model]) {
channels = color_convert_default[this.model].channels;
for (i = 0; i < channels; i++) {
const limit = limiters[this.model][i];
if (limit) {
this.color[i] = limit(this.color[i]);
}
}
}
this.valpha = Math.max(0, Math.min(1, this.valpha));
if (Object.freeze) {
Object.freeze(this);
}
}
Color.prototype = {
toString() {
return this.string();
},
toJSON() {
return this[this.model]();
},
string(places) {
let self = this.model in color_string_default.to ? this : this.rgb();
self = self.round(typeof places === "number" ? places : 1);
const arguments_ = self.valpha === 1 ? self.color : [...self.color, this.valpha];
return color_string_default.to[self.model](...arguments_);
},
percentString(places) {
const self = this.rgb().round(typeof places === "number" ? places : 1);
const arguments_ = self.valpha === 1 ? self.color : [...self.color, this.valpha];
return color_string_default.to.rgb.percent(...arguments_);
},
array() {
return this.valpha === 1 ? [...this.color] : [...this.color, this.valpha];
},
object() {
const result = {};
const { channels } = color_convert_default[this.model];
const { labels } = color_convert_default[this.model];
for (let i = 0; i < channels; i++) {
result[labels[i]] = this.color[i];
}
if (this.valpha !== 1) {
result.alpha = this.valpha;
}
return result;
},
unitArray() {
const rgb = this.rgb().color;
rgb[0] /= 255;
rgb[1] /= 255;
rgb[2] /= 255;
if (this.valpha !== 1) {
rgb.push(this.valpha);
}
return rgb;
},
unitObject() {
const rgb = this.rgb().object();
rgb.r /= 255;
rgb.g /= 255;
rgb.b /= 255;
if (this.valpha !== 1) {
rgb.alpha = this.valpha;
}
return rgb;
},
round(places) {
places = Math.max(places || 0, 0);
return new Color([...this.color.map(roundToPlace(places)), this.valpha], this.model);
},
alpha(value) {
if (value !== void 0) {
return new Color([...this.color, Math.max(0, Math.min(1, value))], this.model);
}
return this.valpha;
},
// Rgb
red: getset("rgb", 0, maxfn(255)),
green: getset("rgb", 1, maxfn(255)),
blue: getset("rgb", 2, maxfn(255)),
hue: getset(["hsl", "hsv", "hsl", "hwb", "hcg"], 0, (value) => (value % 360 + 360) % 360),
saturationl: getset("hsl", 1, maxfn(100)),
lightness: getset("hsl", 2, maxfn(100)),
saturationv: getset("hsv", 1, maxfn(100)),
value: getset("hsv", 2, maxfn(100)),
chroma: getset("hcg", 1, maxfn(100)),
gray: getset("hcg", 2, maxfn(100)),
white: getset("hwb", 1, maxfn(100)),
wblack: getset("hwb", 2, maxfn(100)),
cyan: getset("cmyk", 0, maxfn(100)),
magenta: getset("cmyk", 1, maxfn(100)),
yellow: getset("cmyk", 2, maxfn(100)),
black: getset("cmyk", 3, maxfn(100)),
x: getset("xyz", 0, maxfn(95.047)),
y: getset("xyz", 1, maxfn(100)),
z: getset("xyz", 2, maxfn(108.833)),
l: getset("lab", 0, maxfn(100)),
a: getset("lab", 1),
b: getset("lab", 2),
keyword(value) {
if (value !== void 0) {
return new Color(value);
}
return color_convert_default[this.model].keyword(this.color);
},
hex(value) {
if (value !== void 0) {
return new Color(value);
}
return color_string_default.to.hex(...this.rgb().round().color);
},
hexa(value) {
if (value !== void 0) {
return new Color(value);
}
const rgbArray = this.rgb().round().color;
let alphaHex = Math.round(this.valpha * 255).toString(16).toUpperCase();
if (alphaHex.length === 1) {
alphaHex = "0" + alphaHex;
}
return color_string_default.to.hex(...rgbArray) + alphaHex;
},
rgbNumber() {
const rgb = this.rgb().color;
return (rgb[0] & 255) << 16 | (rgb[1] & 255) << 8 | rgb[2] & 255;
},
luminosity() {
const rgb = this.rgb().color;
const lum = [];
for (const [i, element] of rgb.entries()) {
const chan = element / 255;
lum[i] = chan <= 0.04045 ? chan / 12.92 : ((chan + 0.055) / 1.055) ** 2.4;
}
return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2];
},
contrast(color2) {
const lum1 = this.luminosity();
const lum2 = color2.luminosity();
if (lum1 > lum2) {
return (lum1 + 0.05) / (lum2 + 0.05);
}
return (lum2 + 0.05) / (lum1 + 0.05);
},
level(color2) {
const contrastRatio = this.contrast(color2);
if (contrastRatio >= 7) {
return "AAA";
}
return contrastRatio >= 4.5 ? "AA" : "";
},
isDark() {
const rgb = this.rgb().color;
const yiq = (rgb[0] * 2126 + rgb[1] * 7152 + rgb[2] * 722) / 1e4;
return yiq < 128;
},
isLight() {
return !this.isDark();
},
negate() {
const rgb = this.rgb();
for (let i = 0; i < 3; i++) {
rgb.color[i] = 255 - rgb.color[i];
}
return rgb;
},
lighten(ratio) {
const hsl = this.hsl();
hsl.color[2] += hsl.color[2] * ratio;
return hsl;
},
darken(ratio) {
const hsl = this.hsl();
hsl.color[2] -= hsl.color[2] * ratio;
return hsl;
},
saturate(ratio) {
const hsl = this.hsl();
hsl.color[1] += hsl.color[1] * ratio;
return hsl;
},
desaturate(ratio) {
const hsl = this.hsl();
hsl.color[1] -= hsl.color[1] * ratio;
return hsl;
},
whiten(ratio) {
const hwb = this.hwb();
hwb.color[1] += hwb.color[1] * ratio;
return hwb;
},
blacken(ratio) {
const hwb = this.hwb();
hwb.color[2] += hwb.color[2] * ratio;
return hwb;
},
grayscale() {
const rgb = this.rgb().color;
const value = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11;
return Color.rgb(value, value, value);
},
fade(ratio) {
return this.alpha(this.valpha - this.valpha * ratio);
},
opaquer(ratio) {
return this.alpha(this.valpha + this.valpha * ratio);
},
rotate(degrees) {
const hsl = this.hsl();
let hue = hsl.color[0];
hue = (hue + degrees) % 360;
hue = hue < 0 ? 360 + hue : hue;
hsl.color[0] = hue;
return hsl;
},
mix(mixinColor, weight) {
if (!mixinColor || !mixinColor.rgb) {
throw new Error('Argument to "mix" was not a Color instance, but rather an instance of ' + typeof mixinColor);
}
const color1 = mixinColor.rgb();
const color2 = this.rgb();
const p = weight === void 0 ? 0.5 : weight;
const w = 2 * p - 1;
const a = color1.alpha() - color2.alpha();
const w1 = ((w * a === -1 ? w : (w + a) / (1 + w * a)) + 1) / 2;
const w2 = 1 - w1;
return Color.rgb(
w1 * color1.red() + w2 * color2.red(),
w1 * color1.green() + w2 * color2.green(),
w1 * color1.blue() + w2 * color2.blue(),
color1.alpha() * p + color2.alpha() * (1 - p)
);
}
};
for (const model of Object.keys(color_convert_default)) {
if (skippedModels.includes(model)) {
continue;
}
const { channels } = color_convert_default[model];
Color.prototype[model] = function(...arguments_) {
if (this.model === model) {
return new Color(this);
}
if (arguments_.length > 0) {
return new Color(arguments_, model);
}
return new Color([...assertArray(color_convert_default[this.model][model].raw(this.color)), this.valpha], model);
};
Color[model] = function(...arguments_) {
let color = arguments_[0];
if (typeof color === "number") {
color = zeroArray(arguments_, channels);
}
return new Color(color, model);
};
}
function roundTo(number, places) {
return Number(number.toFixed(places));
}
function roundToPlace(places) {
return function(number) {
return roundTo(number, places);
};
}
function getset(model, channel, modifier) {
model = Array.isArray(model) ? model : [model];
for (const m of model) {
(limiters[m] || (limiters[m] = []))[channel] = modifier;
}
model = model[0];
return function(value) {
let result;
if (value !== void 0) {
if (modifier) {
value = modifier(value);
}
result = this[model]();
result.color[channel] = value;
return result;
}
result = this[model]().color[channel];
if (modifier) {
result = modifier(result);
}
return result;
};
}
function maxfn(max) {
return function(v) {
return Math.max(0, Math.min(max, v));
};
}
function assertArray(value) {
return Array.isArray(value) ? value : [value];
}
function zeroArray(array, length) {
for (let i = 0; i < length; i++) {
if (typeof array[i] !== "number") {
array[i] = 0;
}
}
return array;
}
var color_default = Color;
// src/utils/colors.ts
var import_state6 = require("@codemirror/state");
var import_language8 = require("@codemirror/language");
// src/codemirror-extensions/inline-css.ts
var inlineCssLanguage = cssLanguage.configure({
top: "Styles"
});
// src/utils/colors.ts
function findColorValues(state) {
const matches = [];
const tree = (0, import_language8.syntaxTree)(state);
const doc = state.doc;
tree.cursor().iterate((nodeRef) => {
const { node } = nodeRef;
const nodeText = doc.sliceString(node.from, node.to);
if (isColorValue(node.name, nodeText)) {
matches.push({
from: node.from,
to: node.to,
color: nodeText
});
} else if (node.name === "Comment") {
const commentMatches = findColorsInComment(nodeText, node.from);
matches.push(...commentMatches);
}
});
return matches.sort((a, b) => a.from - b.from);
}
function convertToColorModel(color, model) {
switch (model) {
case "rgb":
return convertToRgb(color);
case "hsl":
return convertToHsl(color);
case "hex":
return convertToHex(color);
default:
return color;
}
}
function getColorModel(color) {
try {
if (color.startsWith("#")) return "hex";
if (isValidColorName(color)) return "hex";
return color_default(color).toJSON().model;
} catch (e) {
return "hex";
}
}
function convertToHex(color) {
try {
return color_default(color).hex().toLowerCase();
} catch (e) {
return color;
}
}
function convertToRgb(color) {
try {
return color_default(color).rgb().toString();
} catch (e) {
return color;
}
}
function convertToHsl(color) {
try {
return color_default(color).hsl().round().toString();
} catch (e) {
return color;
}
}
function isColorValue(nodeName, nodeText) {
switch (nodeName) {
case "ColorLiteral":
return true;
case "ValueName":
return isValidColorName(nodeText);
case "CallExpression":
return /^(rgb|rgba|hsl|hsla|hwb)\s*\(/.test(nodeText);
default:
return false;
}
}
var validColorNames = /* @__PURE__ */ new Set([
"aliceblue",
"antiquewhite",
"aqua",
"aquamarine",
"azure",
"beige",
"bisque",
"black",
"blanchedalmond",
"blue",
"blueviolet",
"brown",
"burlywood",
"cadetblue",
"chartreuse",
"chocolate",
"coral",
"cornflowerblue",
"cornsilk",
"crimson",
"cyan",
"darkblue",
"darkcyan",
"darkgoldenrod",
"darkgray",
"darkgreen",
"darkgrey",
"darkkhaki",
"darkmagenta",
"darkolivegreen",
"darkorange",
"darkorchid",
"darkred",
"darksalmon",
"darkseagreen",
"darkslateblue",
"darkslategray",
"darkslategrey",
"darkturquoise",
"darkviolet",
"deeppink",
"deepskyblue",
"dimgray",
"dimgrey",
"dodgerblue",
"firebrick",
"floralwhite",
"forestgreen",
"fuchsia",
"gainsboro",
"ghostwhite",
"gold",
"goldenrod",
"gray",
"green",
"greenyellow",
"grey",
"honeydew",
"hotpink",
"indianred",
"indigo",
"ivory",
"khaki",
"lavender",
"lavenderblush",
"lawngreen",
"lemonchiffon",
"lightblue",
"lightcoral",
"lightcyan",
"lightgoldenrodyellow",
"lightgray",
"lightgreen",
"lightgrey",
"lightpink",
"lightsalmon",
"lightseagreen",
"lightskyblue",
"lightslategray",
"lightslategrey",
"lightsteelblue",
"lightyellow",
"lime",
"limegreen",
"linen",
"magenta",
"maroon",
"mediumaquamarine",
"mediumblue",
"mediumorchid",
"mediumpurple",
"mediumseagreen",
"mediumslateblue",
"mediumspringgreen",
"mediumturquoise",
"mediumvioletred",
"midnightblue",
"mintcream",
"mistyrose",
"moccasin",
"navajowhite",
"navy",
"oldlace",
"olive",
"olivedrab",
"orange",
"orangered",
"orchid",
"palegoldenrod",
"palegreen",
"paleturquoise",
"palevioletred",
"papayawhip",
"peachpuff",
"peru",
"pink",
"plum",
"powderblue",
"purple",
"rebeccapurple",
"red",
"rosybrown",
"royalblue",
"saddlebrown",
"salmon",
"sandybrown",
"seagreen",
"seashell",
"sienna",
"silver",
"skyblue",
"slateblue",
"slategray",
"slategrey",
"snow",
"springgreen",
"steelblue",
"tan",
"teal",
"thistle",
"tomato",
"turquoise",
"violet",
"wheat",
"white",
"whitesmoke",
"yellow",
"yellowgreen"
]);
function isValidColorName(name) {
return validColorNames.has(name.toLowerCase());
}
function findColorsInComment(commentText, commentStart) {
var _a, _b;
const matches = [];
const withoutDelimiters = commentText.replace(/^\/\*|\*\/$/g, "");
const content = withoutDelimiters.trim();
if (!content) {
return matches;
}
const leadingWhitespaceMatch = withoutDelimiters.match(/^(\s*)/);
const leadingWhitespaceLength = leadingWhitespaceMatch ? (_b = (_a = leadingWhitespaceMatch[1]) == null ? void 0 : _a.length) != null ? _b : 0 : 0;
const totalOffset = 2 + leadingWhitespaceLength;
try {
const commentState = import_state6.EditorState.create({
doc: content,
extensions: [inlineCssLanguage]
});
const commentTree = (0, import_language8.syntaxTree)(commentState);
const commentDoc = commentState.doc;
commentTree.cursor().iterate((nodeRef) => {
const { node } = nodeRef;
const nodeText = commentDoc.sliceString(node.from, node.to);
if (isColorValue(node.name, nodeText)) {
const absoluteStart = commentStart + node.from + totalOffset;
const absoluteEnd = commentStart + node.to + totalOffset;
matches.push({
from: absoluteStart,
to: absoluteEnd,
color: nodeText
});
}
});
} catch (error) {
console.warn(
"Failed to parse comment as CSS, skipping color detection:",
error
);
}
return matches;
}
// src/codemirror-extensions/color-picker.ts
var ColorPickerWidget = class extends import_view7.WidgetType {
constructor(color, from, to, view) {
super();
this.color = color;
this.from = from;
this.to = to;
this.view = view;
}
eq(other) {
return this.color === other.color && this.from === other.from && this.to === other.to;
}
toDOM() {
const wrapper = document.createElement("span");
wrapper.className = "css-editor-color-picker-wrapper";
new import_obsidian4.ColorComponent(wrapper).setValue(convertToHex(this.color)).onChange((newColor) => {
const model = getColorModel(this.color);
this.view.dispatch({
changes: {
from: this.from,
to: this.to,
insert: convertToColorModel(newColor, model)
}
});
});
return wrapper;
}
};
var colorPickerPlugin = import_view7.ViewPlugin.fromClass(
class {
constructor(view) {
this.decorations = this.buildDecorations(view);
}
update(update) {
if (update.docChanged || update.viewportChanged) {
this.decorations = this.buildDecorations(update.view);
}
}
buildDecorations(view) {
const builder = new Array();
const doc = view.state.doc;
if (!doc || doc.length === 0) {
return import_view7.Decoration.set([]);
}
const colorMatches = findColorValues(view.state);
for (const match of colorMatches) {
if (match.from < 0 || match.to > doc.length || match.from >= match.to) {
continue;
}
const line = doc.lineAt(match.from);
if (view.viewport.from <= line.to && line.from <= view.viewport.to) {
const decoration = import_view7.Decoration.widget({
widget: new ColorPickerWidget(
match.color,
match.from,
match.to,
view
),
side: 1
});
builder.push(decoration.range(match.to));
}
}
return import_view7.Decoration.set(builder);
}
destroy() {
this.decorations = import_view7.Decoration.set([]);
}
},
{
decorations: (v) => v.decorations
}
);
// src/obsidian/workspace-helpers.ts
var import_obsidian5 = require("obsidian");
async function openView(workspace, type, openInNewTab, state) {
const leaf = workspace.getLeaf(openInNewTab);
await leaf.setViewState({
type,
state
});
workspace.setActiveLeaf(leaf);
}
async function detachCssFileLeaves(workspace, file) {
var _a;
const leaves = workspace.getLeavesOfType(VIEW_TYPE_CSS);
for (const leaf of leaves) {
if ((0, import_obsidian5.requireApiVersion)("1.7.2")) {
await leaf.loadIfDeferred();
}
if (((_a = leaf.getViewState().state) == null ? void 0 : _a.file) === file.name) {
leaf.detach();
}
}
}
// src/modals/CssSnippetDeleteConfirmModal.ts
var import_obsidian6 = require("obsidian");
var CssSnippetDeleteConfirmModal = class extends import_obsidian6.Modal {
constructor(app, plugin, file) {
super(app);
this.plugin = plugin;
this.file = file;
}
async onOpen() {
await super.onOpen();
this.titleEl.setText("Delete CSS snippet");
this.containerEl.addClass("css-editor-delete-confirm-modal");
this.buildForm();
}
buildForm() {
this.contentEl.createEl("p", {
text: `Are you sure you want to delete "${this.file.name}"?`
});
this.contentEl.createEl("p", {
text: "This action cannot be undone."
});
const buttonContainer = this.contentEl.createDiv(
"modal-button-container"
);
const dontAskAgainLabel = buttonContainer.createEl("label", {
cls: "mod-checkbox"
});
const dontAskAgainCheckbox = dontAskAgainLabel.createEl("input", {
type: "checkbox"
});
dontAskAgainCheckbox.insertAdjacentText("afterend", "Don't ask again");
new import_obsidian6.ButtonComponent(buttonContainer).setButtonText("Delete").setWarning().onClick(() => this.delete());
new import_obsidian6.ButtonComponent(buttonContainer).setButtonText("Cancel").onClick(() => this.close());
}
async delete() {
try {
const dontAskAgain = this.contentEl.querySelector(
'input[type="checkbox"]'
);
if (dontAskAgain == null ? void 0 : dontAskAgain.checked) {
this.plugin.settings.promptDelete = false;
await this.plugin.saveSettings();
}
await detachCssFileLeaves(this.app.workspace, this.file);
await deleteSnippetFile(this.app, this.file);
this.close();
} catch (err) {
handleError(err, "Failed to delete CSS file.");
}
}
};
// src/views/CssEditorView.ts
var VIEW_TYPE_CSS = "css-editor-view";
var CssEditorView = class extends import_obsidian7.ItemView {
constructor(leaf, plugin) {
var _a, _b;
super(leaf);
this.file = null;
this.isSavingTitle = false;
/** If the editor contents differ from the file contents on disk */
this.isEditorDirty = false;
this.requestSave = (0, import_obsidian7.debounce)(this.save.bind(this), 1e3);
this.plugin = plugin;
this.navigation = true;
this.editor = new import_view8.EditorView({
parent: this.contentEl,
extensions: [
basicExtensions,
lineWrap.of(
this.plugin.settings.lineWrap ? import_view8.EditorView.lineWrapping : []
),
indentSize.of(
import_language9.indentUnit.of("".padEnd(this.plugin.settings.indentSize))
),
historyCompartment.of((0, import_commands3.history)()),
colorPickerPlugin,
relativeLineNumberGutter.of(
(0, import_view8.lineNumbers)({
formatNumber: this.plugin.settings.relativeLineNumbers ? relativeLineNumbersFormatter : absoluteLineNumbers
})
),
((_b = (_a = this.app.vault).getConfig) == null ? void 0 : _b.call(_a, "vimMode")) ? vim() : [],
import_view8.EditorView.updateListener.of((update) => {
if (update.docChanged) {
this.isEditorDirty = true;
this.requestSave(update.state.doc.toString());
if (this.file) {
this.app.workspace.trigger(
"css-editor-change",
this.file,
update.state.doc.toString()
);
}
}
})
]
});
this.scope = new import_obsidian7.Scope(this.app.scope);
this.scope.register(null, "F2", () => {
if (!this.file) return;
if (this.titleEl.isShown()) {
focusAndSelectElement(this.titleEl);
} else {
new CssSnippetRenameModal(this.app, this.file).open();
}
});
}
getViewType() {
return VIEW_TYPE_CSS;
}
getIcon() {
return "file-code";
}
getDisplayText() {
var _a, _b;
return (_b = (_a = this.file) == null ? void 0 : _a.basename) != null ? _b : "No file open";
}
// eslint-disable-next-line @typescript-eslint/require-await
async onOpen() {
const timer = window.setInterval(() => {
this.editor.focus();
if (this.editor.hasFocus) clearInterval(timer);
}, 200);
this.registerInterval(timer);
if (import_obsidian7.Platform.isMobileApp) {
this.titleEl.addEventListener("touchstart", () => {
this.titleEl.contentEditable = "true";
});
} else {
this.titleEl.contentEditable = "true";
}
this.titleEl.addEventListener("focus", this.onTitleFocus.bind(this));
this.titleEl.addEventListener("blur", this.onTitleBlur.bind(this));
this.titleEl.addEventListener(
"keydown",
this.onTitleKeydown.bind(this)
);
this.registerEvent(
this.app.workspace.on("css-editor-change", (file, data) => {
var _a;
if (((_a = this.file) == null ? void 0 : _a.name) === file.name && this.getEditorData() !== data) {
this.dispatchEditorData(data);
}
})
);
this.registerEvent(
this.app.workspace.on("css-snippet-rename", (file, oldFileName) => {
var _a;
if (((_a = this.file) == null ? void 0 : _a.name) === oldFileName) {
this.file = file;
this.titleEl.setText(this.getDisplayText());
this.leaf.updateHeader();
this.app.workspace.requestSaveLayout();
}
})
);
this.registerEvent(
this.app.workspace.on("css-change", async (data) => {
if (!this.file) return;
if (typeof data === "object" && data !== null && "source" in data && (data == null ? void 0 : data.source) === "style-settings") {
return;
}
if (this.isEditorDirty) {
this.isEditorDirty = false;
return;
}
const contents = await readSnippetFile(this.app, this.file);
if (contents !== this.getEditorData()) {
this.dispatchEditorData(contents);
}
})
);
this.registerEvent(
this.app.workspace.on("leaf-menu", (menu, leaf) => {
if (leaf === this.leaf && !!this.file) {
menu.addItem((item) => {
item.setIcon("lucide-edit-3").setSection("action").setTitle("Rename...").onClick(() => {
if (this.file) {
new CssSnippetRenameModal(
this.app,
this.file
).open();
}
});
});
menu.addItem((item) => {
const isEnabled = this.isEnabled();
item.setIcon(
isEnabled ? "lucide-toggle-left" : "lucide-toggle-right"
).setSection("action").setTitle(
isEnabled ? "Disable snippet" : "Enable snippet"
).onClick(() => {
if (this.file) {
toggleSnippetFileState(this.app, this.file);
}
});
});
menu.addItem((item) => {
item.setIcon("lucide-trash-2").setSection("danger").setTitle("Delete snippet").setWarning(true).onClick(async () => {
if (this.file) {
if (this.plugin.settings.promptDelete) {
new CssSnippetDeleteConfirmModal(
this.app,
this.plugin,
this.file
).open();
} else {
try {
await detachCssFileLeaves(
this.app.workspace,
this.file
);
await deleteSnippetFile(
this.app,
this.file
);
} catch (err) {
handleError(
err,
"Failed to delete CSS file."
);
}
}
}
});
});
}
})
);
}
onTitleFocus() {
var _a, _b;
this.titleEl.spellcheck = ((_b = (_a = this.app.vault).getConfig) == null ? void 0 : _b.call(_a, "spellcheck")) === true;
}
onTitleBlur() {
this.saveTitle(this.titleEl).catch(handleError);
this.titleEl.spellcheck = false;
if (import_obsidian7.Platform.isMobileApp) {
this.titleEl.contentEditable = "false";
}
this.editor.focus();
}
onTitleKeydown(event) {
if (!this.file) return;
if (event.isComposing) return;
if (event.key === "Escape") {
this.titleEl.setText(this.getDisplayText());
this.titleEl.blur();
}
if (event.key === "Enter" || event.key === "Tab") {
event.preventDefault();
this.saveTitle(this.titleEl).catch(handleError);
this.titleEl.blur();
}
}
async saveTitle(el) {
if (!this.file) return;
const newTitle = el.getText().trim();
if (newTitle === this.file.basename) return;
if (this.isSavingTitle) return;
this.isSavingTitle = true;
await renameSnippetFile(this.app, this.file, newTitle);
this.isSavingTitle = false;
}
getEditorData() {
return this.editor.state.doc.toString();
}
dispatchEditorTransaction(...specs) {
this.editor.dispatch(...specs);
}
dispatchEditorData(data) {
this.editor.dispatch({
changes: {
from: 0,
to: this.editor.state.doc.length,
insert: data
}
});
}
getState() {
var _a;
return {
file: (_a = this.file) == null ? void 0 : _a.name
};
}
async setState(state, result) {
var _a;
let file = null;
if (state && typeof state === "object") {
if ("filename" in state && typeof state.filename === "string") {
file = new CssFile(state.filename);
}
if ("file" in state) {
if (state.file instanceof CssFile) {
file = state.file;
} else if (typeof state.file === "string") {
file = new CssFile(state.file);
}
}
}
if (file) {
if (file.name !== ((_a = this.file) == null ? void 0 : _a.name)) {
try {
await this.loadFile(file);
} catch (e) {
await this.loadFile(null);
}
}
} else {
await this.loadFile(null);
}
result.history = true;
return super.setState({ file: file == null ? void 0 : file.name }, result);
}
async loadFile(file) {
this.file = file;
this.titleEl.setText(this.getDisplayText());
this.leaf.updateHeader();
const data = file ? await readSnippetFile(this.app, file) : "";
this.dispatchEditorData(data);
this.resetHistory();
this.app.workspace.requestSaveLayout();
}
resetHistory() {
this.editor.dispatch({
effects: [historyCompartment.reconfigure([])]
});
this.editor.dispatch({
effects: [historyCompartment.reconfigure((0, import_commands3.history)())]
});
}
isEnabled() {
var _a, _b;
if (!this.file) return false;
const currentState = (_b = (_a = this.app.customCss) == null ? void 0 : _a.enabledSnippets) == null ? void 0 : _b.has(
this.file.basename
);
return currentState || false;
}
/**
* You should almost always call `requestSave` instead of `save` to debounce the saving.
*/
async save(data) {
if (this.file) {
await writeSnippetFile(this.app, this.file, data);
}
}
// eslint-disable-next-line @typescript-eslint/require-await
async onClose() {
this.editor.destroy();
}
};
// src/modals/CssSnippetFuzzySuggestModal.ts
var import_obsidian8 = require("obsidian");
var CssSnippetFuzzySuggestModal = class extends import_obsidian8.FuzzySuggestModal {
constructor(app, plugin) {
super(app);
this.plugin = plugin;
this.scope.register(["Mod"], "Enter", (evt) => {
var _a, _b;
if (!evt.isComposing && ((_b = (_a = this.chooser) == null ? void 0 : _a.useSelectedItem) == null ? void 0 : _b.call(_a, evt))) {
return false;
}
return true;
});
this.scope.register(["Shift"], "Enter", (evt) => {
this.selectSuggestion(
{
item: new CssFile(this.inputEl.value),
match: { score: 0, matches: [] }
},
evt
);
return false;
});
this.scope.register(["Mod"], "Delete", (evt) => {
var _a, _b;
if (!evt.isComposing && ((_b = (_a = this.chooser) == null ? void 0 : _a.useSelectedItem) == null ? void 0 : _b.call(_a, evt))) {
return false;
}
return true;
});
this.scope.register([], "Tab", (evt) => {
var _a, _b;
if (this.chooser) {
const selectedItem = this.chooser.selectedItem;
const file = (_a = this.chooser.values[selectedItem]) == null ? void 0 : _a.item;
if (!file) return false;
const isEnabled = toggleSnippetFileState(this.app, file);
const buttonEl = (_b = this.chooser.suggestions[selectedItem]) == null ? void 0 : _b.querySelector(
".css-editor-status"
);
buttonEl == null ? void 0 : buttonEl.setText(isEnabled ? "enabled" : "disabled");
buttonEl == null ? void 0 : buttonEl.toggleClass("mod-cta", isEnabled);
}
return false;
});
this.containerEl.addClass("css-editor-quick-switcher-modal");
this.setPlaceholder("Find or create a CSS snippet...");
this.setInstructions([
{ command: "\u2191\u2193", purpose: "to navigate" },
{
command: import_obsidian8.Platform.isMacOS ? "\u2318 \u21B5" : "ctrl \u21B5",
purpose: "to open in new tab"
},
{ command: "shift \u21B5", purpose: "to create" },
{
command: import_obsidian8.Platform.isMacOS ? "\u2318 del" : "ctrl del",
purpose: "to delete"
},
{ command: "tab", purpose: "to enable/disable" },
{ command: "esc", purpose: "to dismiss" }
]);
}
isEnabled(item) {
var _a, _b;
const currentState = (_b = (_a = this.app.customCss) == null ? void 0 : _a.enabledSnippets) == null ? void 0 : _b.has(
item.basename
);
return currentState || false;
}
getItems() {
var _a;
if ((_a = this.app.customCss) == null ? void 0 : _a.snippets) {
return this.app.customCss.snippets.map((x) => new CssFile(x));
}
return [];
}
getItemText(item) {
return item.name;
}
renderSuggestion(item, el) {
super.renderSuggestion(item, el);
el.addClass("mod-complex");
if (el.hasChildNodes()) {
const existingChildren = Array.from(el.childNodes);
el.childNodes.forEach((child) => {
el.removeChild(child);
});
el.appendChild(
createDiv(
{ cls: "suggestion-content" },
(suggestionContentEl) => {
suggestionContentEl.appendChild(
createDiv(
{ cls: "css-editor-suggestion-name" },
(nestedEl) => {
existingChildren.forEach((child) => {
nestedEl.appendChild(child);
});
}
)
);
suggestionContentEl.appendChild(
createDiv(
{ cls: "css-editor-suggestion-description" },
(el2) => el2.appendText(
`${getSnippetDirectory(this.app)}${item.item.name}`
)
)
);
}
)
);
const isEnabled = this.isEnabled(item.item);
const isNewElement = this.inputEl.value.trim().length > 0 && item.match.score === 0;
if (!isNewElement) {
const button = new import_obsidian8.ButtonComponent(el).setButtonText(isEnabled ? "enabled" : "disabled").setClass("css-editor-status").onClick((e) => {
e.stopPropagation();
const newState = toggleSnippetFileState(
this.app,
item.item
);
button.setButtonText(newState ? "enabled" : "disabled");
if (newState) {
button.setCta();
} else {
button.removeCta();
}
});
if (isEnabled) {
button.setCta();
}
}
}
if (this.inputEl.value.trim().length > 0 && item.match.score === 0) {
el.appendChild(
createDiv({ cls: "suggestion-aux" }, (el2) => {
el2.appendChild(
createSpan({ cls: "suggestion-hotkey" }, (el3) => {
el3.appendText("Enter to create");
})
);
})
);
}
}
selectSuggestion(value, evt) {
try {
this.onChooseSuggestion(value, evt);
this.close();
} catch (err) {
handleError(err, "Failed to open CSS file.");
}
}
onChooseSuggestion(item, evt) {
const isCreateNewDueToNoSuggestion = this.inputEl.value.trim().length > 0 && item.match.score === 0;
if (isCreateNewDueToNoSuggestion && item.item) {
const openInNewTab = evt.metaKey;
this.plugin.createAndOpenSnippet(item.item.name, openInNewTab).catch((err) => {
handleError(err, "Failed to create and open CSS file.");
});
} else {
this.onChooseItem(item.item, evt);
}
}
onNoSuggestion() {
var _a, _b, _c, _d, _e, _f, _g, _h;
const item = this.inputEl.value.trim();
if (item.length > 0) {
(_b = (_a = this.chooser) == null ? void 0 : _a.setSuggestions) == null ? void 0 : _b.call(_a, [
{ item: new CssFile(item), match: { score: 0, matches: [] } }
]);
(_d = (_c = this.chooser) == null ? void 0 : _c.addMessage) == null ? void 0 : _d.call(
_c,
"No CSS snippets found. Enter to create a new one."
);
} else {
(_f = (_e = this.chooser) == null ? void 0 : _e.setSuggestions) == null ? void 0 : _f.call(_e, []);
(_h = (_g = this.chooser) == null ? void 0 : _g.addMessage) == null ? void 0 : _h.call(
_g,
"No CSS snippets found. Type to search..."
);
}
}
onChooseItem(item, evt) {
if (!item) return;
if (evt instanceof KeyboardEvent) {
if (evt.key === "Enter") {
const openInNewTab = evt.metaKey;
if (evt.shiftKey) {
this.plugin.createAndOpenSnippet(item.name, openInNewTab).catch((err) => {
handleError(
err,
"Failed to create and open CSS file."
);
});
} else {
openView(this.app.workspace, VIEW_TYPE_CSS, openInNewTab, {
file: item
}).catch(handleError);
}
} else if (evt.key === "Delete") {
if (this.plugin.settings.promptDelete) {
new CssSnippetDeleteConfirmModal(
this.app,
this.plugin,
item
).open();
} else {
Promise.all([
detachCssFileLeaves(this.app.workspace, item),
deleteSnippetFile(this.app, item)
]).then(() => {
new import_obsidian8.Notice(`${item.name} was deleted.`);
}).catch((err) => {
handleError(err, "Failed to delete CSS file.");
});
}
}
} else {
const openInNewTab = evt.metaKey;
openView(this.app.workspace, VIEW_TYPE_CSS, openInNewTab, {
file: item
}).catch(handleError);
}
}
};
// node_modules/monkey-around/mjs/index.js
function around(obj, factories) {
const removers = Object.keys(factories).map((key) => around1(obj, key, factories[key]));
return removers.length === 1 ? removers[0] : function() {
removers.forEach((r) => r());
};
}
function around1(obj, method, createWrapper) {
const original = obj[method], hadOwn = obj.hasOwnProperty(method);
let current = createWrapper(original);
if (original)
Object.setPrototypeOf(current, original);
Object.setPrototypeOf(wrapper, current);
obj[method] = wrapper;
return remove;
function wrapper(...args) {
if (current === original && obj[method] === wrapper)
remove();
return current.apply(this, args);
}
function remove() {
if (obj[method] === wrapper) {
if (hadOwn)
obj[method] = original;
else
delete obj[method];
}
if (current === original)
return;
current = original;
Object.setPrototypeOf(wrapper, original || Function);
}
}
// src/obsidian/ignore-obsidian-hotkey.ts
function ignoreObsidianHotkey(scope, keymapInfo, checkCallback) {
const uninstallCommand = around(scope, {
handleKey(originalMethod) {
return function(...args) {
const invokedHotkey = args[1];
if (isKeymapInfo(invokedHotkey) && keymapInfo.key === invokedHotkey.key && keymapInfo.modifiers === invokedHotkey.modifiers && checkCallback()) {
return true;
}
const result = originalMethod && originalMethod.apply(this, args);
return result;
};
}
});
return uninstallCommand;
}
function isKeymapInfo(hotkey) {
return !!hotkey && typeof hotkey === "object" && "key" in hotkey && typeof hotkey.key === "string" && "modifiers" in hotkey;
}
// src/modals/CssSnippetCreateModal.ts
var import_obsidian9 = require("obsidian");
var CssSnippetCreateModal = class extends import_obsidian9.Modal {
constructor(app, plugin) {
super(app);
this.value = "";
this.plugin = plugin;
}
async onOpen() {
await super.onOpen();
this.titleEl.setText("Create CSS snippet");
this.containerEl.addClass("css-editor-create-modal");
this.buildForm();
}
buildForm() {
const textInput = new import_obsidian9.TextComponent(this.contentEl);
textInput.setPlaceholder("CSS snippet file name (ex: snippet.css)");
textInput.onChange((val) => this.value = val);
textInput.inputEl.addEventListener("keydown", (evt) => {
this.handleKeydown(evt).catch(handleError);
});
const buttonContainer = this.contentEl.createDiv(
"modal-button-container"
);
new import_obsidian9.ButtonComponent(buttonContainer).setButtonText("Save").setCta().onClick(() => this.save());
new import_obsidian9.ButtonComponent(buttonContainer).setButtonText("Cancel").onClick(() => this.close());
}
async handleKeydown(evt) {
if (evt.key === "Escape") {
this.close();
} else if (evt.key === "Enter") {
await this.save(evt.metaKey);
}
}
async save(openInNewTab = false) {
try {
await this.plugin.createAndOpenSnippet(this.value, openInNewTab);
this.close();
} catch (err) {
handleError(err, "Failed to create and open CSS file.");
}
}
};
// src/obsidian/setting-tab.ts
var import_language10 = require("@codemirror/language");
var import_view9 = require("@codemirror/view");
var import_obsidian10 = require("obsidian");
function updateCSSEditorView(app, spec) {
app.workspace.getLeavesOfType(VIEW_TYPE_CSS).forEach((leaf) => {
if (leaf.view instanceof CssEditorView) {
leaf.view.dispatchEditorTransaction(spec);
}
});
}
var CSSEditorSettingTab = class extends import_obsidian10.PluginSettingTab {
constructor(app, plugin) {
super(app, plugin);
this.plugin = plugin;
}
display() {
this.containerEl.empty();
new import_obsidian10.Setting(this.containerEl).setName("Confirm CSS snippet deletion").setDesc("Prompt before CSS snippet deletion.").addToggle((toggle) => {
toggle.setValue(this.plugin.settings.promptDelete);
toggle.onChange(async (val) => {
this.plugin.settings.promptDelete = val;
await this.plugin.saveSettings();
});
});
new import_obsidian10.Setting(this.containerEl).setName("Line wrap").setDesc("Toggle line wrap in the editor.").addToggle((toggle) => {
toggle.setValue(this.plugin.settings.lineWrap);
toggle.onChange(async (val) => {
this.plugin.settings.lineWrap = val;
await this.plugin.saveSettings();
updateCSSEditorView(this.app, {
effects: lineWrap.reconfigure(
val ? import_view9.EditorView.lineWrapping : []
)
});
});
});
new import_obsidian10.Setting(this.containerEl).setName("Indent size").setDesc("Adjust the amount of spaces used for indentation.").addText((field) => {
field.setPlaceholder("2");
field.setValue(this.plugin.settings.indentSize.toString());
field.onChange(async (val) => {
val = val.replace(/\D/g, "");
field.setValue(val);
const size = parseInt(val);
this.plugin.settings.indentSize = size;
await this.plugin.saveSettings();
updateCSSEditorView(this.app, {
effects: indentSize.reconfigure(
import_language10.indentUnit.of("".padEnd(size))
)
});
});
});
new import_obsidian10.Setting(this.containerEl).setName("Relative line numbers").setDesc("Show line numbers relative to cursor position.").addToggle((toggle) => {
toggle.setValue(this.plugin.settings.relativeLineNumbers);
toggle.onChange(async (val) => {
this.plugin.settings.relativeLineNumbers = val;
await this.plugin.saveSettings();
updateCSSEditorView(this.app, {
effects: relativeLineNumberGutter.reconfigure(
(0, import_view9.lineNumbers)({
formatNumber: val ? relativeLineNumbersFormatter : absoluteLineNumbers
})
)
});
});
});
}
};
// src/main.ts
var DEFAULT_SETTINGS = {
promptDelete: true,
lineWrap: true,
indentSize: 2,
relativeLineNumbers: false
};
var CssEditorPlugin = class extends import_obsidian11.Plugin {
async onload() {
await this.loadSettings();
this.addCommand({
id: "create-css-snippet",
name: "Create CSS snippet",
callback: () => {
new CssSnippetCreateModal(this.app, this).open();
}
});
this.addCommand({
id: "open-quick-switcher",
name: "Open quick switcher",
callback: () => {
new CssSnippetFuzzySuggestModal(this.app, this).open();
}
});
this.addCommand({
id: "delete-css-snippet",
name: "Delete CSS snippet",
checkCallback: (checking) => {
const activeCssEditorView = this.app.workspace.getActiveViewOfType(CssEditorView);
if (!activeCssEditorView) return false;
const { file } = activeCssEditorView.getState();
if (!file) return false;
if (checking) return true;
const cssFile = new CssFile(file);
if (this.settings.promptDelete) {
new CssSnippetDeleteConfirmModal(
this.app,
this,
cssFile
).open();
} else {
detachCssFileLeaves(this.app.workspace, cssFile).then(async () => {
await deleteSnippetFile(this.app, cssFile);
new import_obsidian11.Notice(`"${cssFile.name}" was deleted.`);
}).catch((err) => {
handleError(err, "Failed to delete CSS file.");
});
}
return true;
}
});
this.addCommand({
id: "toggle-css-snippet-enabled-status",
name: "Toggle the enabled/disabled state of CSS snippet",
checkCallback: (checking) => {
const activeCssEditorView = this.app.workspace.getActiveViewOfType(CssEditorView);
if (!activeCssEditorView) return false;
const { file } = activeCssEditorView.getState();
if (!file) return false;
if (checking) return true;
const cssFile = new CssFile(file);
const isEnabled = toggleSnippetFileState(this.app, cssFile);
new import_obsidian11.Notice(
`"${cssFile.name}" is now ${isEnabled ? "enabled" : "disabled"}.`
);
return true;
}
});
this.register(
ignoreObsidianHotkey(
this.app.scope,
{ key: "/", modifiers: "Meta" },
() => !!this.app.workspace.getActiveViewOfType(CssEditorView)
)
);
this.registerView(
VIEW_TYPE_CSS,
(leaf) => new CssEditorView(leaf, this)
);
this.settingTab = new CSSEditorSettingTab(this.app, this);
this.addSettingTab(this.settingTab);
}
onunload() {
}
async loadSettings() {
this.settings = Object.assign(
{},
DEFAULT_SETTINGS,
await this.loadData()
);
}
async saveSettings() {
await this.saveData(this.settings);
}
async createAndOpenSnippet(filename, openInNewTab) {
var _a, _b;
const file = await createSnippetFile(this.app, filename, "");
(_b = (_a = this.app.customCss) == null ? void 0 : _a.setCssEnabledStatus) == null ? void 0 : _b.call(_a, file.basename, true);
new import_obsidian11.Notice(`${file.name} was created.`);
await openView(this.app.workspace, VIEW_TYPE_CSS, openInNewTab, {
file
});
}
};
/* nosourcemap */