{"mappings":"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","names":["globalKey","prismGlobal","plainTextGrammar","rest","tokenize","languages","prismGlobal","plainTextGrammar","escapeHtml","string","pattern","replacement","doc","templateEl","createTemplate","html","node","addListener","target","type","listener","options","numLines","str","start","end","count","languageMap","preventDefault","selectionChange","doc","addListener","scrollToEl","editor","el","paddingTop","style","isChrome","getLineStart","text","position","getLineEnd","addListener2","element","type","listener","options","addListener","addTextareaListener","getStyleValue","prop","updateNode","node","text","voidlessLangs","prevSelection","regexEscape","str","getLineBefore","text","position","getLineStart","insertText","editor","text","start","end","newCursorStart","newCursorEnd","prevSelection","textarea","value","avoidBug","isChrome","removeListener","isWebKit","doc","escapeHtml","setSelection","direction","removeHandler","addListener2","e","target","userAgent","isMac","getModifierCode","addOverlay","overlay","mod","isMac","searchTemplate","createTemplate","matchTemplate","testBoundary","str","position","pattern","createSearchAPI","editor","container","nodes","matchPositions","stopSearch","regex","lastNode","caseSensitive","wholeWord","useRegExp","selection","filter","regexEscape","value","searchStr","offset","match","l","index","i","e","prevEnd","start","end","updateNode","addOverlay","createReplaceAPI","editor","getSelection","search","createSearchAPI","container","matches","closest","caretPos","l","i","toggleClasses","currentLine","currentMatch","removeSelection","hasSelected","removeHandler","addTextareaListener","cursor","match","index","scrollPadding","setSelection","scrollToEl","str","start","end","caretStart","caretEnd","insertText","value","newLen","newStart","newEnd","newValue","matchStart","matchEnd","lengthDiff","move","pos","highlightSelectionMatches","caseSensitive","minLength","maxLength","self","editor","searchAPI","createSearchAPI","container","start","end","value","l","mStart","mEnd","highlightCurrentWord","filter","includeHyphens","noHighlight","group","before","index","word","newFilter","shortcut","isMac","template","createTemplate","toggleAttr","el","name","searchWidget","prevLength","useRegExp","matchCase","wholeWord","searchSelection","isOpen","currentSelection","prevUserSelection","prevMargin","selectNext","marginTop","self","editor","textarea","wrapper","container","getSelection","replaceAPI","createReplaceAPI","startSearch","selectMatch","isWebKit","error","findInput","index","updateNode","current","total","findContainer","errorEl","open","focusInput","getStyleValue","addOverlay","searchContainer","updateMargin","resize","observer","close","focusTextarea","move","next","newMargin","search","newScroll","div","replace","replaceInput","replaceAll","keyCodeButtonMap","matchCaseEl","wholeWordEl","useRegExpEl","inSelectionEl","elementHandlerMap","nextEl","prevEl","closeEl","replaceEl","replaceAllEl","toggle","value","numLines","getLineStart","getLineEnd","getSelectedWord","start","end","word","getLineBefore","regexEscape","addListener","e","code","getModifierCode","keyCode","isF3","mod","preventDefault","doc","diff","selection","target","remove","isFind","rows","matchCount","showInvisibles","searchAPI","createSearchAPI","matches","nodes","tabs","update","i","l"],"sources":["../esm/npm/@cyfung1031/prism-code-editor@5.2.0-cdn-esm.2/node_modules/@cyfung1031/prism-code-editor/src/prism/core.js","../esm/npm/@cyfung1031/prism-code-editor@5.2.0-cdn-esm.2/node_modules/@cyfung1031/prism-code-editor/src/core.ts","../esm/npm/@cyfung1031/prism-code-editor@5.2.0-cdn-esm.2/node_modules/@cyfung1031/prism-code-editor/src/utils/local.ts","../esm/npm/@cyfung1031/prism-code-editor@5.2.0-cdn-esm.2/node_modules/@cyfung1031/prism-code-editor/src/utils/index.ts","../esm/npm/@cyfung1031/prism-code-editor@5.2.0-cdn-esm.2/node_modules/@cyfung1031/prism-code-editor/src/extensions/commands/utils.ts","../esm/npm/@cyfung1031/prism-code-editor@5.2.0-cdn-esm.2/node_modules/@cyfung1031/prism-code-editor/src/extensions/search/search.ts","../esm/npm/@cyfung1031/prism-code-editor@5.2.0-cdn-esm.2/node_modules/@cyfung1031/prism-code-editor/src/extensions/search/replace.ts","../esm/npm/@cyfung1031/prism-code-editor@5.2.0-cdn-esm.2/node_modules/@cyfung1031/prism-code-editor/src/extensions/search/selection.ts","../esm/npm/@cyfung1031/prism-code-editor@5.2.0-cdn-esm.2/node_modules/@cyfung1031/prism-code-editor/src/extensions/search/widget.ts","../esm/npm/@cyfung1031/prism-code-editor@5.2.0-cdn-esm.2/node_modules/@cyfung1031/prism-code-editor/src/extensions/search/invisibles.ts"],"sourcesContent":["// Slimmed down Prism core with most high level functions removed\n\nvar globalKey = Symbol.for(\"prism-code-editor.prism\");\nvar prismGlobal = globalThis[globalKey] || (globalThis[globalKey] = {});\n\nvar plainTextGrammar = prismGlobal.plainTextGrammar || (prismGlobal.plainTextGrammar = {});\nvar rest = prismGlobal.rest || (prismGlobal.rest = Symbol.for(\"prism-code-editor.prism.rest\"));\nvar tokenize =\n\tprismGlobal.tokenize || (prismGlobal.tokenize = Symbol.for(\"prism-code-editor.prism.tokenize\"));\n\n/** @param {*} id */\nvar resolve = id =\u003e typeof id == 'string' ? languages[id] : id;\n\n/** @type {Record\u003cstring, any\u003e} */\nvar languages =\n\tprismGlobal.languages ||\n\t(prismGlobal.languages = {\n\t\tplain: plainTextGrammar,\n\t\tplaintext: plainTextGrammar,\n\t\ttext: plainTextGrammar,\n\t\ttxt: plainTextGrammar,\n\t});\n\n/**\n * @param {string} text\n * @param {any} grammar\n */\nvar tokenizeText = (text, grammar) =\u003e (grammar[tokenize] || withoutTokenizer)(text, grammar);\n\n/**\n * @param {string} text\n * @param {any} grammar\n */\nvar withoutTokenizer = (text, grammar) =\u003e {\n\t/** @type {LinkedListNode} */\n\tvar startNode = [text];\n\tvar restGrammar;\n\t/** @type {(string | Token)[]} */\n\tvar array = [], i = 0;\n\twhile (restGrammar = resolve(grammar[rest])) {\n\t\tdelete grammar[rest];\n\t\tObject.assign(grammar, restGrammar);\n\t}\n\n\tmatchGrammar(text, grammar, startNode, 0);\n\n\twhile (array[i++] = startNode[0], startNode = startNode[1]);\n\treturn array;\n};\n\n/**\n * @param {string} string\n * @param {RegExp} pattern\n * @param {string} replacement\n */\nvar escapeHtml = (string, pattern, replacement) =\u003e {\n\treturn string.replace(/\u0026/g, '\u0026amp;').replace(pattern, replacement);\n};\n\nvar closingTag = '\u003c/span\u003e';\nvar openingTags = '';\nvar closingTags = '';\n\n/** @param {(string | Token)[]} tokens */\nvar highlightTokens = tokens =\u003e {\n\tvar str = '', token, i = 0;\n\twhile (token = tokens[i++]) str += stringify(token);\n\treturn str;\n};\n\n/**\n * @param {string | Token | (string | Token)[]} token\n * @returns {string}\n */\nvar stringify = token =\u003e {\n\tif (token instanceof Token) {\n\t\tvar { type, alias, content } = token;\n\t\tvar prevOpening = openingTags;\n\t\tvar prevClosing = closingTags;\n\t\tvar opening = `\u003cspan class=\"token ${\n\t\t\ttype + (alias ? ' ' + alias : '') +\n\t\t\t(type == 'keyword' \u0026\u0026 typeof content == 'string' ? ' keyword-' + content : '')\n\t\t}\"\u003e`;\n\n\t\tclosingTags += closingTag;\n\t\topeningTags += opening;\n\t\tvar contentStr = stringify(content);\n\t\topeningTags = prevOpening;\n\t\tclosingTags = prevClosing;\n\t\treturn opening + contentStr + closingTag;\n\t}\n\n\tif (typeof token != 'string') return highlightTokens(token);\n\n\ttoken = escapeHtml(token, /\u003c/g, '\u0026lt;');\n\tif (closingTags \u0026\u0026 token.includes('\\n')) {\n\t\treturn token.replace(/\\n/g, closingTags + '\\n' + openingTags);\n\t}\n\treturn token;\n};\n\n/**\n * @param {string} text\n * @param {*} ref\n */\nvar highlightText = (text, ref) =\u003e highlightTokens(tokenizeText(text, resolve(ref)));\n\n/**\n * @param {string} text\n * @param {any} grammar\n * @param {LinkedListNode} startNode\n * @param {number} startPos\n * @param {[string, number, number]} [rematch]\n *\n * @typedef {[string | Token, LinkedListNode?]} LinkedListNode\n */\nvar matchGrammar = (text, grammar, startNode, startPos, rematch) =\u003e {\n\tfor (var token in grammar) {\n\t\tif (grammar[token]) for (var j = 0, p = grammar[token], patternObj, patterns = Array.isArray(p) ? p : [p]; patternObj = patterns[j]; j++) {\n\t\t\tif (rematch \u0026\u0026 rematch[0] == token \u0026\u0026 rematch[1] == j) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t/** @type {RegExp} */\n\t\t\tvar pattern = patternObj.pattern || patternObj;\n\t\t\tvar inside = resolve(patternObj.inside);\n\t\t\tvar lookbehind = patternObj.lookbehind;\n\t\t\tvar greedy = pattern.global;\n\t\t\tvar alias = patternObj.alias;\n\n\t\t\tfor ( // iterate the token list and keep track of the current token/string position\n\t\t\t\tvar currentNode = startNode, pos = startPos;\n\t\t\t\tcurrentNode \u0026\u0026 (!rematch || pos \u003c rematch[2]);\n\t\t\t\tpos += currentNode[0].length, currentNode = currentNode[1]\n\t\t\t) {\n\t\t\t\tvar str = currentNode[0];\n\t\t\t\tvar removeCount = 0;\n\t\t\t\tvar match;\n\n\t\t\t\tif (str instanceof Token) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tpattern.lastIndex = greedy ? pos : 0;\n\t\t\t\tmatch = pattern.exec(greedy ? text : str);\n\n\t\t\t\tif (!match \u0026\u0026 greedy) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (!(match \u0026\u0026 match[0])) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// change the match to remove the text matched by the Prism lookbehind group\n\t\t\t\tvar lookbehindLength = lookbehind \u0026\u0026 match[1] ? match[1].length : 0;\n\t\t\t\tvar from = match.index + lookbehindLength;\n\t\t\t\tvar matchStr = match[0].slice(lookbehindLength);\n\t\t\t\tvar to = from + matchStr.length;\n\t\t\t\tvar k, p;\n\n\t\t\t\tif (greedy) {\n\t\t\t\t\t// find the node that contains the match\n\t\t\t\t\tfor (\n\t\t\t\t\t\t;\n\t\t\t\t\t\tp = pos + currentNode[0].length, from \u003e= p;\n\t\t\t\t\t\tcurrentNode = currentNode[1], pos = p\n\t\t\t\t\t);\n\n\t\t\t\t\t// the current node is a Token, then the match starts inside another Token, which is invalid\n\t\t\t\t\tif (currentNode[0] instanceof Token) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// find the last node which is affected by this match\n\t\t\t\t\tfor (\n\t\t\t\t\t\tk = currentNode, p = pos;\n\t\t\t\t\t\t(p += k[0].length) \u003c to;\n\t\t\t\t\t\tk = k[1], removeCount++\n\t\t\t\t\t);\n\n\t\t\t\t\t// replace with the new match\n\t\t\t\t\tstr = text.slice(pos, p);\n\t\t\t\t\tfrom -= pos;\n\t\t\t\t\tto -= pos;\n\t\t\t\t}\n\n\t\t\t\tvar after = str.slice(to);\n\t\t\t\tvar reach = pos + str.length;\n\t\t\t\tvar newToken = new Token(token, inside ? tokenizeText(matchStr, inside) : matchStr, matchStr, alias);\n\t\t\t\tvar next = currentNode, i = 0;\n\t\t\t\tvar nestedRematch;\n\n\t\t\t\twhile (next = next[1], i++ \u003c removeCount);\n\n\t\t\t\tif (after) {\n\t\t\t\t\tif (!next || next[0] instanceof Token) next = [after, next];\n\t\t\t\t\telse next[0] = after + next[0];\n\t\t\t\t};\n\n\t\t\t\tpos += from;\n\t\t\t\tcurrentNode[0] = from ? str.slice(0, from) : newToken;\n\n\t\t\t\tif (from) currentNode = currentNode[1] = [newToken, next];\n\t\t\t\telse currentNode[1] = next;\n\n\t\t\t\tif (removeCount) {\n\t\t\t\t\t// at least one Token object was removed, so we have to do some rematching\n\t\t\t\t\t// this can only happen if the current pattern is greedy\n\n\t\t\t\t\tmatchGrammar(text, grammar, currentNode, pos, nestedRematch = [token, j, reach]);\n\t\t\t\t\treach = nestedRematch[2];\n\t\t\t\t}\n\n\t\t\t\tif (rematch \u0026\u0026 reach \u003e rematch[2]) rematch[2] = reach;\n\t\t\t}\n\t\t}\n\t}\n};\n\n/**\n * Creates a new token.\n *\n * @param {string} type\n * @param {string | any[]} content\n * @param {string} matchedStr\n * @param {string} alias\n * @class\n */\nfunction Token(type, content, matchedStr, alias) {\n\tthis.type = type;\n\tthis.content = content;\n\tthis.alias = alias;\n\tthis.length = matchedStr.length;\n}\n\nexport {\n\trest,\n\ttokenize,\n\tToken,\n\tlanguages,\n\ttokenizeText,\n\twithoutTokenizer,\n\tresolve,\n\tescapeHtml,\n\thighlightTokens,\n\thighlightText\n};\n","import type {\r\n\tEditorOptions,\r\n\tPrismEditor,\r\n\tKeyCommandCallback,\r\n\tLanguage,\r\n\tInputCommandCallback,\r\n\tEditorEventMap,\r\n\tInputSelection,\r\n\tEditorExtension,\r\n} from \"./types.js\"\r\nimport { highlightTokens, languages, tokenizeText, TokenStream } from \"./prism/index.js\"\r\n\r\n/**\r\n * Creates a code editor using the specified container and options.\r\n * @param container Element to append the editor to or a selector.\r\n * This can also be a `ShadowRoot` or `DocumentFragment` for example.\r\n * If omitted, you must manually append `editor.container` to the DOM.\r\n * @param options Options the editor is initialized with.\r\n * If omitted, the editor won't function until you call `editor.setOptions`.\r\n * @param extensions Extensions added before the first render. You can still add extensions later.\r\n * @returns Object to interact with the created editor.\r\n */\r\nconst createEditor = \u003cT extends {} = {}\u003e(\r\n\tcontainer?: ParentNode | string | null,\r\n\toptions?: (Partial\u003cEditorOptions\u003cT\u003e\u003e \u0026 Omit\u003cT, keyof EditorOptions\u003e) | null,\r\n\t...extensions: EditorExtension\u003cT\u003e[]\r\n): PrismEditor\u003cT\u003e =\u003e {\r\n\tlet language: string\r\n\tlet prevLines: string[] = []\r\n\tlet activeLine: HTMLDivElement\r\n\tlet value = \"\"\r\n\tlet activeLineNumber: number\r\n\tlet focused = false\r\n\tlet handleSelectionChange = true\r\n\tlet tokens: TokenStream = []\r\n\tlet readOnly: boolean\r\n\tlet lineCount = 0\r\n\r\n\tconst scrollContainer = editorTemplate()\r\n\tconst wrapper = \u003cHTMLDivElement\u003escrollContainer.firstChild\r\n\tconst lines = \u003cHTMLCollectionOf\u003cHTMLDivElement\u003e\u003ewrapper.children\r\n\tconst overlays = lines[0]\r\n\tconst textarea = \u003cHTMLTextAreaElement\u003eoverlays.firstChild\r\n\tconst currentOptions = { language: \"text\", value } as EditorOptions \u0026 T\r\n\tconst currentExtensions = new Set(extensions)\r\n\tconst listeners: {\r\n\t\t[P in keyof EditorEventMap]?: Set\u003cEditorEventMap\u003cT\u003e[P]\u003e\r\n\t} = {}\r\n\r\n\tconst setOptions = (options: Partial\u003cEditorOptions\u003e \u0026 Partial\u003cOmit\u003cT, keyof EditorOptions\u003e\u003e) =\u003e {\r\n\t\tObject.assign(currentOptions, options)\r\n\t\tlet isNewVal = value != (value = options.value ?? value)\r\n\t\tlet isNewLang = language != (language = currentOptions.language)\r\n\r\n\t\treadOnly = !!currentOptions.readOnly\r\n\t\tscrollContainer.style.tabSize = \u003cany\u003ecurrentOptions.tabSize || 2\r\n\t\ttextarea.inputMode = readOnly ? \"none\" : \"\"\r\n\t\ttextarea.setAttribute(\"aria-readonly\", \u003cany\u003ereadOnly)\r\n\t\tupdateClassName()\r\n\t\tupdateExtensions()\r\n\r\n\t\tif (isNewVal) {\r\n\t\t\tif (!focused) textarea.remove()\r\n\t\t\ttextarea.value = value\r\n\t\t\ttextarea.selectionEnd = 0\r\n\t\t\tif (!focused) overlays.prepend(textarea)\r\n\t\t}\r\n\r\n\t\tif (isNewVal || isNewLang) {\r\n\t\t\tupdate()\r\n\t\t}\r\n\t}\r\n\r\n\tconst update = () =\u003e {\r\n\t\ttokens = tokenizeText((value = textarea.value), languages[language] || {})\r\n\t\tdispatchEvent(\"tokenize\", tokens, language, value)\r\n\r\n\t\tlet newLines = highlightTokens(tokens).split(\"\\n\")\r\n\t\tlet start = 0\r\n\t\tlet end2 = lineCount\r\n\t\tlet end1 = (lineCount = newLines.length)\r\n\r\n\t\twhile (newLines[start] == prevLines[start] \u0026\u0026 start \u003c end1) ++start\r\n\t\twhile (end1 \u0026\u0026 newLines[--end1] == prevLines[--end2]);\r\n\r\n\t\tif (start == end1 \u0026\u0026 start == end2) lines[start + 1].innerHTML = newLines[start] + \"\\n\"\r\n\t\telse {\r\n\t\t\tlet insertStart = end2 \u003c start ? end2 : start - 1\r\n\t\t\tlet i = insertStart\r\n\t\t\tlet newHTML = \"\"\r\n\r\n\t\t\twhile (i \u003c end1) newHTML += `\u003cdiv class=pce-line aria-hidden=true\u003e${newLines[++i]}\\n\u003c/div\u003e`\r\n\t\t\tfor (i = end1 \u003c start ? end1 : start - 1; i \u003c end2; i++) lines[start + 1].remove()\r\n\t\t\tif (newHTML) lines[insertStart + 1].insertAdjacentHTML(\"afterend\", newHTML)\r\n\t\t\tscrollContainer.style.setProperty(\r\n\t\t\t\t\"--number-width\",\r\n\t\t\t\t(0 | Math.log10(lineCount)) + 1 + \".001ch\",\r\n\t\t\t)\r\n\t\t}\r\n\r\n\t\tdispatchEvent(\"update\", value)\r\n\t\tdispatchSelection(true)\r\n\t\tif (handleSelectionChange) setTimeout(setTimeout, 0, () =\u003e (handleSelectionChange = true))\r\n\r\n\t\tprevLines = newLines\r\n\t\thandleSelectionChange = false\r\n\t}\r\n\r\n\tconst updateExtensions = (newExtensions?: EditorExtension\u003cT\u003e[]) =\u003e {\r\n\t\t;(newExtensions || currentExtensions).forEach(extension =\u003e {\r\n\t\t\tif (typeof extension == \"object\") {\r\n\t\t\t\textension.update(self, currentOptions)\r\n\t\t\t\tif (newExtensions) currentExtensions.add(extension)\r\n\t\t\t} else {\r\n\t\t\t\textension(self, currentOptions)\r\n\t\t\t\tif (!newExtensions) currentExtensions.delete(extension)\r\n\t\t\t}\r\n\t\t})\r\n\t}\r\n\r\n\tconst updateClassName = ([start, end] = getInputSelection()) =\u003e {\r\n\t\tscrollContainer.className = `prism-code-editor language-${language}${\r\n\t\t\tcurrentOptions.lineNumbers == false ? \"\" : \" show-line-numbers\"\r\n\t\t} pce-${currentOptions.wordWrap ? \"\" : \"no\"}wrap${currentOptions.rtl ? \" pce-rtl\" : \"\"} pce-${\r\n\t\t\tstart \u003c end ? \"has\" : \"no\"\r\n\t\t}-selection${focused ? \" pce-focus\" : \"\"}${readOnly ? \" pce-readonly\" : \"\"}${\r\n\t\t\tcurrentOptions.class ? \" \" + currentOptions.class : \"\"\r\n\t\t}`\r\n\t}\r\n\r\n\tconst getInputSelection = (): InputSelection =\u003e [\r\n\t\ttextarea.selectionStart,\r\n\t\ttextarea.selectionEnd,\r\n\t\ttextarea.selectionDirection,\r\n\t]\r\n\r\n\tconst keyCommandMap: Record\u003cstring, KeyCommandCallback | null\u003e = {\r\n\t\tEscape() {\r\n\t\t\ttextarea.blur()\r\n\t\t},\r\n\t}\r\n\r\n\tconst inputCommandMap: Record\u003cstring, InputCommandCallback | null\u003e = {}\r\n\r\n\tconst dispatchEvent = \u003cT extends keyof EditorEventMap\u003e(\r\n\t\tname: T,\r\n\t\t...args: Parameters\u003cEditorEventMap[T]\u003e\r\n\t) =\u003e {\r\n\t\t// @ts-expect-error\r\n\t\tlisteners[name]?.forEach(handler =\u003e handler.apply(self, args))\r\n\t\t// @ts-expect-error\r\n\t\tcurrentOptions[\"on\" + name[0].toUpperCase() + name.slice(1)]?.(...args, self)\r\n\t}\r\n\r\n\tconst dispatchSelection = (force?: boolean) =\u003e {\r\n\t\tif (force || handleSelectionChange) {\r\n\t\t\tconst selection = getInputSelection()\r\n\t\t\tconst newLine =\r\n\t\t\t\tlines[(activeLineNumber = numLines(value, 0, selection[selection[2] \u003c \"f\" ? 0 : 1]))]\r\n\r\n\t\t\tif (newLine != activeLine) {\r\n\t\t\t\tactiveLine?.classList.remove(\"active-line\")\r\n\t\t\t\tnewLine.classList.add(\"active-line\")\r\n\t\t\t\tactiveLine = newLine\r\n\t\t\t}\r\n\t\t\tupdateClassName(selection)\r\n\t\t\tdispatchEvent(\"selectionChange\", selection, value)\r\n\t\t}\r\n\t}\r\n\r\n\tconst self: PrismEditor\u003cT\u003e = {\r\n\t\tcontainer: scrollContainer,\r\n\t\twrapper,\r\n\t\tlines,\r\n\t\ttextarea,\r\n\t\tget activeLine() {\r\n\t\t\treturn activeLineNumber\r\n\t\t},\r\n\t\tget value() {\r\n\t\t\treturn value\r\n\t\t},\r\n\t\toptions: currentOptions,\r\n\t\tget focused() {\r\n\t\t\treturn focused\r\n\t\t},\r\n\t\tget tokens() {\r\n\t\t\treturn tokens\r\n\t\t},\r\n\t\tinputCommandMap,\r\n\t\tkeyCommandMap,\r\n\t\textensions: {},\r\n\t\tsetOptions,\r\n\t\tupdate,\r\n\t\tgetSelection: getInputSelection,\r\n\t\taddExtensions(...extensions) {\r\n\t\t\tupdateExtensions(extensions)\r\n\t\t},\r\n\t\ton: (name, handler) =\u003e {\r\n\t\t\t;(listeners[name] ||= new Set\u003cany\u003e()).add(handler)\r\n\t\t\treturn () =\u003e listeners[name]!.delete(handler)\r\n\t\t},\r\n\t\tremove() {\r\n\t\t\tscrollContainer.remove()\r\n\t\t},\r\n\t}\r\n\r\n\taddListener(textarea, \"keydown\", e =\u003e {\r\n\t\tkeyCommandMap[e.key]?.(e, getInputSelection(), value) \u0026\u0026 preventDefault(e)\r\n\t})\r\n\r\n\taddListener(textarea, \"beforeinput\", e =\u003e {\r\n\t\tif (\r\n\t\t\treadOnly ||\r\n\t\t\t(e.inputType == \"insertText\" \u0026\u0026 inputCommandMap[e.data!]?.(e, getInputSelection(), value))\r\n\t\t)\r\n\t\t\tpreventDefault(e)\r\n\t})\r\n\taddListener(textarea, \"input\", update)\r\n\taddListener(textarea, \"blur\", () =\u003e {\r\n\t\tselectionChange = null\r\n\t\tfocused = false\r\n\t\tupdateClassName()\r\n\t})\r\n\taddListener(textarea, \"focus\", () =\u003e {\r\n\t\tselectionChange = dispatchSelection\r\n\t\tfocused = true\r\n\t\tupdateClassName()\r\n\t})\r\n\t// For browsers that support selectionchange on textareas\r\n\taddListener(textarea, \"selectionchange\", e =\u003e {\r\n\t\tdispatchSelection(!e.isTrusted)\r\n\t\tpreventDefault(e)\r\n\t})\r\n\r\n\tgetElement(container)?.append(scrollContainer)\r\n\toptions \u0026\u0026 setOptions(options)\r\n\treturn self\r\n}\r\n\r\n/**\r\n * Almost identical to {@link createEditor}, but instead of appending the editor to your\r\n * element, the editor replaces it.\r\n *\r\n * The `textContent` of the placeholder will be the code in the editor unless `options.value` is defined.\r\n * @param placeholder Node or selector which will be replaced by the editor.\r\n * @param options Options the editor is initialized with.\r\n * @param extensions Extensions added before the first render. You can still add extensions later.\r\n * @returns Object to interact with the created editor.\r\n */\r\nconst editorFromPlaceholder = \u003cT extends {} = {}\u003e(\r\n\tplaceholder: string | ChildNode,\r\n\toptions: Partial\u003cEditorOptions\u003cT\u003e\u003e \u0026 Omit\u003cT, keyof EditorOptions\u003e,\r\n\t...extensions: EditorExtension\u003cT\u003e[]\r\n) =\u003e {\r\n\tconst el = getElement(placeholder)!\r\n\tconst editor = createEditor\u003cT\u003e(\r\n\t\tnull,\r\n\t\tObject.assign({ value: el.textContent }, options),\r\n\t\t...extensions,\r\n\t)\r\n\tel.replaceWith(editor.container)\r\n\treturn editor\r\n}\r\n\r\n/** Equivalent to `document` in a browser setting, `null` otherwise. */\r\nconst doc = \"u\" \u003e typeof window ? document : null\r\n\r\nconst templateEl = /* @__PURE__ */ doc?.createElement(\"div\")\r\n\r\nconst createTemplate = \u003cT extends Element = HTMLDivElement\u003e(html: string, node?: Node) =\u003e {\r\n\tif (templateEl) {\r\n\t\ttemplateEl.innerHTML = html\r\n\t\tnode = templateEl.firstChild!\r\n\t}\r\n\treturn () =\u003e \u003cT\u003enode!.cloneNode(true)\r\n}\r\n\r\nconst addListener = \u003cT extends keyof HTMLElementEventMap\u003e(\r\n\ttarget: HTMLElement,\r\n\ttype: T,\r\n\tlistener: (this: HTMLElement, ev: HTMLElementEventMap[T]) =\u003e any,\r\n\toptions?: boolean | AddEventListenerOptions,\r\n) =\u003e target.addEventListener(type, listener, options)\r\n\r\nconst getElement = \u003cT extends Node\u003e(el?: T | string | null) =\u003e\r\n\ttypeof el == \"string\" ? doc!.querySelector\u003cHTMLElement\u003e(el) : el\r\n\r\n/**\r\n * Counts number of lines in the string between `start` and `end`.\r\n * If start and end are omitted, the whole string is searched.\r\n */\r\nconst numLines = (str: string, start = 0, end = Infinity) =\u003e {\r\n\tlet count = 1\r\n\tfor (; (start = str.indexOf(\"\\n\", start) + 1) \u0026\u0026 start \u003c= end; count++);\r\n\treturn count\r\n}\r\n\r\n/** Object storing all language specific behavior. */\r\nconst languageMap: Record\u003cstring, Language\u003e =\r\n\t((globalThis as any)[Symbol.for(\"prism-code-editor.languageMap\")] ||= {})\r\n\r\nconst editorTemplate = /* @__PURE__ */ createTemplate(\r\n\t\"\u003cdiv\u003e\u003cdiv class=pce-wrapper\u003e\u003cdiv class=pce-overlays\u003e\u003ctextarea class=pce-textarea spellcheck=false autocapitalize=off autocomplete=off\u003e\",\r\n)\r\n\r\nconst preventDefault = (e: Event) =\u003e {\r\n\te.preventDefault()\r\n\te.stopImmediatePropagation()\r\n}\r\n\r\nconst setSelectionChange = (f?: (force?: boolean) =\u003e void) =\u003e (selectionChange = f)\r\n\r\nlet selectionChange: null | undefined | ((force?: boolean) =\u003e void)\r\n\r\n// @ts-expect-error Allow adding listener to document\r\nif (doc) addListener(doc, \"selectionchange\", () =\u003e selectionChange?.())\r\n\r\nexport {\r\n\tcreateEditor,\r\n\tlanguageMap,\r\n\tnumLines,\r\n\tcreateTemplate,\r\n\tgetElement,\r\n\tpreventDefault,\r\n\teditorFromPlaceholder,\r\n\taddListener,\r\n\tsetSelectionChange,\r\n\tdoc,\r\n}\r\n","import { PrismEditor } from \"../index.js\"\nimport { addListener } from \"../core.js\"\nimport { isChrome } from \"./index.js\"\nimport { PrismCodeBlock } from \"../client/code-block.js\"\n\nconst scrollToEl = (editor: PrismEditor, el: HTMLElement, paddingTop = 0) =\u003e {\n\tconst style = editor.container.style\n\n\tstyle.setProperty(\"--_sp\", \"var(--pce-scroll-padding, 2ch)\")\n\tstyle.scrollPaddingBlock = `calc(var(--_sp) + ${paddingTop}px) calc(var(--_sp) + ${\n\t\tisChrome \u0026\u0026 !el.offsetWidth ? el.offsetHeight : 0\n\t}px)`\n\n\tel.scrollIntoView({ block: \"nearest\" })\n\tstyle.scrollPaddingBlock = \"\"\n\tstyle.removeProperty(\"--_sp\")\n}\n\nconst getLineStart = (text: string, position: number) =\u003e\n\tposition ? text.lastIndexOf(\"\\n\", position - 1) + 1 : 0\n\nconst getLineEnd = (text: string, position: number) =\u003e\n\t(position = text.indexOf(\"\\n\", position)) + 1 ? position : text.length\n\nconst addListener2 = \u003cT extends keyof HTMLElementEventMap\u003e(\n\telement: HTMLElement,\n\ttype: T,\n\tlistener: (this: HTMLElement, ev: HTMLElementEventMap[T]) =\u003e any,\n\toptions?: boolean | AddEventListenerOptions,\n) =\u003e {\n\taddListener(element, type, listener, options)\n\treturn () =\u003e element.removeEventListener(type, listener, options)\n}\n\nconst addTextareaListener = \u003cT extends keyof HTMLElementEventMap\u003e(\n\teditor: PrismEditor,\n\ttype: T,\n\tlistener: (this: HTMLElement, ev: HTMLElementEventMap[T]) =\u003e any,\n\toptions?: boolean | AddEventListenerOptions,\n) =\u003e addListener2(editor.textarea, type, listener, options)\n\nconst getStyleValue = (el: HTMLElement, prop: keyof CSSStyleDeclaration) =\u003e\n\tparseFloat(\u003cstring\u003egetComputedStyle(el)[prop])\n\nconst getPosition = (editor: PrismEditor | PrismCodeBlock, el: HTMLElement) =\u003e {\n\tconst rect1 = el.getBoundingClientRect()\n\tconst rect2 = editor.lines[0].getBoundingClientRect()\n\n\treturn {\n\t\ttop: rect1.y - rect2.y,\n\t\tbottom: rect2.bottom - rect1.bottom,\n\t\tleft: rect1.x - rect2.x,\n\t\tright: rect2.right - rect1.right,\n\t\theight: rect1.height,\n\t}\n}\n\nconst updateNode = (node: Text, text: string) =\u003e {\n\tif (node.data != text) node.data = text\n}\n\nconst voidlessLangs = new Set(\"xml,rss,atom,jsx,tsx,xquery,xeora,xeoracube,actionscript\".split(\",\"))\nconst voidTags = /^(?:area|base|w?br|col|embed|hr|img|input|link|meta|source|track)$/\n\nexport {\n\tscrollToEl,\n\tgetLineStart,\n\tgetLineEnd,\n\tgetStyleValue,\n\taddListener2,\n\taddTextareaListener,\n\tgetPosition,\n\tupdateNode,\n\tvoidTags,\n\tvoidlessLangs,\n}\n","import { InputSelection, PrismEditor } from \"../index.js\"\nimport { numLines, doc } from \"../core.js\"\nimport { addListener2, getLineEnd, getLineStart } from \"./local.js\"\nimport { PrismCodeBlock } from \"../client/code-block.js\"\nimport { escapeHtml } from \"../prism/core.js\"\n\n/**\n * If {@link insertText} has been called, this variable stores the editor's selection\n * before the call. This variable is set to 0 right before {@link insertText} returns.\n * This can therefore be used inside a `beforeinput` handler to determine if\n * {@link insertText} fired the event, and if true, get the selection before the call.\n *\n * Intended for internal use only.\n */\nlet prevSelection: InputSelection | 0\n\n/**\n * Escapes all regex syntax characters with a backslash and returns the escaped string.\n *\n * The returned string is not safe inside a character class.\n */\nconst regexEscape = (str: string) =\u003e str.replace(/[$+?|.^*()[\\]{}\\\\]/g, \"\\\\$\u0026\")\n\n/** Returns the string between the position and the previous \\n. */\nconst getLineBefore = (text: string, position: number) =\u003e\n\ttext.slice(getLineStart(text, position), position)\n\n/**\n * Gets all lines that are at least partially between `start` and `end`.\n * @param text Text to search in.\n * @param start Start of the selection.\n * @param end End of the selection. Defaults to `start`.\n * @returns A tuple containing an array of lines, the starting position of the first line,\n * and the ending position of the last line.\n */\nconst getLines = (text: string, start: number, end = start) =\u003e\n\t[\n\t\ttext.slice((start = getLineStart(text, start)), (end = getLineEnd(text, end))).split(\"\\n\"),\n\t\tstart,\n\t\tend,\n\t] as const\n\n/**\n * Searches a full line for a token that matches a selector and contains `position`\n * within the specified margins. Tokens are searched in reverse document order which means\n * children are searched before their parents.\n * @param editor Editor you want to search in.\n * @param selector CSS selector for the tokens you want to search for.\n * @param marginLeft How far to the left of the token the position can be. Defaults to 0.\n * @param marginRight How far to the right of the token the position can be. Defaults to `marginLeft`.\n * @param position Position to search in. Defaults to `selectionStart`.\n * @returns A span element if one's found or undefined if not.\n * @example\n * This will return a string token if the cursor\n * is at least 1 character inside a string token\n * ```javascript\n * getClosestToken(editor, '.string', -1)\n * ```\n */\nconst getClosestToken = (\n\teditor: PrismEditor,\n\tselector: string,\n\tmarginLeft = 0,\n\tmarginRight = marginLeft,\n\tposition = editor.getSelection()[0],\n) =\u003e {\n\tconst value = editor.value\n\tconst line = editor.lines[numLines(value, 0, position)]\n\t// We unfortunitely have to include elements, else we can't get empty tokens\n\tconst walker = doc!.createTreeWalker(line, 5)\n\n\tlet node = walker.lastChild()\n\tlet offset = getLineEnd(value, position) + 1 - position - (\u003cText\u003enode).length\n\n\twhile (-offset \u003c= marginRight \u0026\u0026 (node = walker.previousNode())) {\n\t\tif (node.lastChild) continue\n\t\toffset -= (\u003cText\u003enode).length || 0\n\n\t\tif (offset \u003c= marginLeft) {\n\t\t\tfor (; node != line; node = node.parentNode!) {\n\t\t\t\tif ((\u003cElement\u003enode).matches?.(selector)) return \u003cHTMLSpanElement\u003enode\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Gets the current language at a position.\n * Useful if you want to run different logic based on the language.\n * @param editor Editor to search in.\n * @param position Position to search in. Defaults to `selectionStart`.\n */\nconst getLanguage = (editor: PrismEditor, position?: number) =\u003e\n\tgetClosestToken(editor, \"[class*=language-]\", 0, 0, position)?.className.match(\n\t\t/language-(\\S*)/,\n\t)![1] || editor.options.language\n\n/**\n * Inserts text into the editor (unless it's read-only) while keeping undo/redo history.\n * Focuses the `textarea` if it isn't already.\n * @param editor Target editor.\n * @param text Text to insert.\n * @param start Position to start the insertion. Defaults to `selectionStart`.\n * @param end Position to end the insertion. Defaults to `start` if specified, else `selectionEnd`.\n * @param newCursorStart New starting position for the cursor. Defaults to the end of the inserted text.\n * @param newCursorEnd New ending position for the cursor. Defaults to `newCursorStart`.\n */\nconst insertText = (\n\teditor: PrismEditor,\n\ttext: string,\n\tstart?: number | null,\n\tend?: number | null,\n\tnewCursorStart?: number | null,\n\tnewCursorEnd?: number | null,\n) =\u003e {\n\tif (editor.options.readOnly) return\n\tprevSelection = editor.getSelection()\n\tend ??= start\n\n\tlet textarea = editor.textarea\n\tlet value = editor.value\n\t// Bug inserting new lines at the end if the editor ends with an empty line\n\tlet avoidBug =\n\t\tisChrome \u0026\u0026 !value[end ?? prevSelection[1]] \u0026\u0026 /\\n$/.test(text) \u0026\u0026 /^$|\\n$/.test(value)\n\tlet removeListener: () =\u003e any\n\n\teditor.focused || textarea.focus()\n\tif (start != null) textarea.setSelectionRange(start, end!)\n\n\tif (newCursorStart != null) {\n\t\tremoveListener = editor.on(\"update\", () =\u003e {\n\t\t\ttextarea.setSelectionRange(\n\t\t\t\tnewCursorStart,\n\t\t\t\tnewCursorEnd ?? newCursorStart,\n\t\t\t\t(\u003cInputSelection\u003eprevSelection)[2],\n\t\t\t)\n\t\t\tremoveListener()\n\t\t})\n\t}\n\n\t// Only Safari dispatches a beforeinput event\n\tisWebKit || textarea.dispatchEvent(new InputEvent(\"beforeinput\", { data: text }))\n\n\t// Inserting escaped HTML in Chrome and Safari instead for much better performance\n\tif (isChrome || isWebKit) {\n\t\tif (avoidBug) {\n\t\t\t// This means the last new line won't be inserted if there's\n\t\t\t// no selection, but that's less annoying than the bug.\n\t\t\ttextarea.selectionEnd--\n\t\t\ttext = text.slice(0, -1)\n\t\t}\n\t\t// New line at the end is always ignored in Safari\n\t\tif (isWebKit) text += \"\\n\"\n\t\tdoc!.execCommand(text ? \"insertHTML\" : \"delete\", false, escapeHtml(text, /\u003c/g, \"\u0026lt;\"))\n\t\tif (avoidBug) textarea.selectionStart++\n\t} else doc!.execCommand(text ? \"insertText\" : \"delete\", false, text)\n\n\tprevSelection = 0\n}\n\n/**\n * Sets the selection for the `textarea` and synchronously runs the selectionChange listeners.\n * If you don't want to synchronously run the listeners, use `textarea.setSelectionRange` instead.\n * @param editor Editor you want to change the selection of.\n * @param start New selectionStart.\n * @param end New selectionEnd. Defaults to `start`.\n * @param direction New direction.\n */\nconst setSelection = (\n\teditor: PrismEditor,\n\tstart: number,\n\tend = start,\n\tdirection?: \"backward\" | \"forward\" | \"none\",\n) =\u003e {\n\tlet textarea = editor.textarea\n\t// Webkit 18.3 and earlier focuses the textarea when changing the selection\n\tlet removeHandler = addListener2(textarea, \"focus\", e =\u003e {\n\t\tlet target = e.relatedTarget as HTMLElement\n\t\ttarget ? target.focus() : textarea.blur()\n\t})\n\n\ttextarea.setSelectionRange(start, end, direction)\n\tremoveHandler()\n\ttextarea.dispatchEvent(new Event(\"selectionchange\"))\n}\n\nconst userAgent = doc ? navigator.userAgent : \"\"\n/** Whether the user is on an Apple-based system. */\nconst isMac = doc ? /Mac|iPhone|iP[ao]d/.test(navigator.platform) : false\n/** Whether the browser is Chromium based. */\nconst isChrome = /Chrome\\//.test(userAgent)\n/** Whether the browser uses the WebKit browser engine. */\nconst isWebKit = !isChrome \u0026\u0026 /AppleWebKit\\//.test(userAgent)\n\n/**\n * Returns a 4 bit integer where each bit represents whether\n * each modifier is pressed in the order Shift, Meta, Ctrl, Alt.\n *\n * ```javascript\n * e.shiftKey \u0026\u0026 !e.metaKey \u0026\u0026 e.ctrlKey \u0026\u0026 e.altKey\n * // is equivalent to\n * getModifierCode(e) == 0b1011\n * ```\n */\nconst getModifierCode = (\n\te: KeyboardEvent, // @ts-expect-error\n): number =\u003e e.altKey + e.ctrlKey * 2 + e.metaKey * 4 + e.shiftKey * 8\n\n/**\n * Adds an overlay by appending the element to the editor's overlays.\n * Equivalent to calling `editor.lines[0].append(overlay)`.\n * @param editor Editor or code block you want to add an overlay to.\n * @param overlay The overlay you want to add.\n */\nconst addOverlay = (editor: PrismEditor | PrismCodeBlock, overlay: HTMLElement) =\u003e\n\teditor.lines[0].append(overlay)\n\n/**\n * Gets the position of the cursor in the document. It returns a tuple with three numbers:\n *\n * 1. The line number of the cursor\n * 2. The 1-based column of the cursor\n * 3. Number of characters selected\n *\n * @example\n * const [line, col, selected] = getDocumentPosition(editor)\n */\nconst getDocumentPosition = (editor: PrismEditor): [number, number, number] =\u003e {\n\tlet [start, end, dir] = editor.getSelection()\n\tlet pos = dir \u003c \"f\" ? start : end\n\tlet value = editor.value\n\tlet col = 0\n\tlet chars = 0\n\tlet tabSize = editor.options.tabSize || 2\n\n\tfor (const char of getLineBefore(value, pos)) {\n\t\tcol += char == \"\\t\" ? tabSize - (col % tabSize) : 1\n\t}\n\n\tfor (const _ of value.slice(start, end)) chars++\n\n\treturn [editor.activeLine, col + 1, chars]\n}\n\nexport {\n\tregexEscape,\n\tgetLineBefore,\n\tgetLines,\n\tgetClosestToken,\n\tgetLanguage,\n\tinsertText,\n\tgetModifierCode,\n\tsetSelection,\n\taddOverlay,\n\tgetDocumentPosition,\n\tisMac,\n\tisChrome,\n\tisWebKit,\n\tprevSelection,\n}\n","import { PrismEditor } from \"../../index.js\"\nimport { preventDefault } from \"../../core.js\"\nimport { getModifierCode, isMac } from \"../../utils/index.js\"\nimport { addTextareaListener } from \"../../utils/local.js\"\nimport { HotkeyMap, EditorHotkey, HotkeySequenceOptions, Hotkey } from \"./types.js\"\n\n/**\n * Normalizes modifier keys to a bitmask that's used by {@link getKeysFromEvent}.\n * All keys are case insensitive.\n *\n * Rules:\n * - `alt` → `1`\n * - `ctrl` or `control` → `2`\n * - `meta` or `cmd` → `4`\n * - `shift` → `8`\n * - `mod` → `4` on Mac, `2` otherwise\n *\n * @param key Key to normalize.\n * @returns Normalized and lowercase key.\n * @example\n * normalizeKey(\"a\") // \"0+a\"\n * normalizeKey(\"+\") // \"0++\"\n * normalizeKey(\"ctrl+alt+a\") // \"3+a\"\n * normalizeKey(\"10+ALT+a\") // \"11+a\"\n * normalizeKey(\"shift+alt+12+a\") // \"13+a\"\n */\nconst normalizeKey = (key: string) =\u003e {\n\tlet code = 0\n\tlet parts = key.toLowerCase().split(\"+\")\n\tlet last = parts.pop() || \"+\"\n\tfor (const part of parts) {\n\t\tcode |= +part || modifierMap[part] || 0\n\t}\n\treturn code + \"+\" + last\n}\n\n/**\n * Gets a `Set` of keys that match a keyboard event.\n * @param e Keyboard event to get keys for.\n */\nconst getKeysFromEvent = (e: KeyboardEvent) =\u003e {\n\tif (!keyCodeMap[48]) {\n\t\t// Alphanumeric\n\t\tfor (let i = 48; i \u003c 91; i++) {\n\t\t\tkeyCodeMap[i] = String.fromCharCode(i \u003e 64 ? i + 32 : i)\n\t\t}\n\n\t\t// Numpad\n\t\tfor (let i = 96; i \u003c 112; i++) {\n\t\t\tkeyCodeMap[i] = String.fromCharCode(i \u003c 106 ? i - 48 : i - 64)\n\t\t}\n\t}\n\n\tconst key = e.key || \"\"\n\tconst code = getModifierCode(e)\n\tconst keyBase = keyCodeMap[e.keyCode]\n\tconst keyShift = keyCodeMapShift[e.keyCode]\n\tconst hasShift = code \u003e 7\n\n\tconst useKeyCode = (isMac \u0026\u0026 code == 12) || key == \"Dead\" || key == \"Unidentified\"\n\tconst keyName = (useKeyCode \u0026\u0026 ((hasShift \u0026\u0026 keyShift) || keyBase)) || key.toLowerCase()\n\n\tconst isNotChar = /\\w\\w| /.test(keyName.slice(0, 2))\n\tconst noShift = code \u0026 7\n\tconst commands = new Set([`${isNotChar || /\\p{L}/u.test(keyName) ? code : noShift}+${keyName}`])\n\n\tif (!isNotChar) {\n\t\tif (noShift \u0026\u0026 !(isMac \u0026\u0026 noShift == 1) \u0026\u0026 keyBase) {\n\t\t\tcommands.add(code + \"+\" + keyBase)\n\t\t\tif (hasShift \u0026\u0026 keyShift) {\n\t\t\t\tcommands.add(noShift + \"+\" + keyShift)\n\t\t\t}\n\t\t} else if (hasShift) commands.add(code + \"+\" + keyName)\n\t}\n\n\treturn commands\n}\n\nconst editorMap = new WeakMap\u003cPrismEditor, HotkeyMap\u003cPrismEditor\u003e\u003e()\n\n/**\n * Utility that runs all commands whose key matches the keyboard event until a command\n * returns a truthy value. In that case `preventDefault` and `stopImmediatePropagation`\n * are called.\n *\n * @param e Keyboard event to run commands for.\n * @param map Record mapping keys to a list of commands for that key.\n * @param data Argument to pass to the commands.\n * @returns `true` if a command returned a truthy value.\n *\n * @example\n * addEventListener(\"keydown\", e =\u003e {\n *   const handled = !!runHotkeys(e, map, data)\n * })\n */\nconst runHotkeys = \u003cT\u003e(e: KeyboardEvent, map: HotkeyMap\u003cT\u003e, data: T) =\u003e {\n\tlet seen = new Set\u003cHotkey\u003cT\u003e\u003e()\n\tlet firstKey: string\n\n\ttry {\n\t\tfor (const key of getKeysFromEvent(e)) {\n\t\t\tfirstKey ||= key\n\t\t\tfor (const set of map[key] || []) {\n\t\t\t\tfor (const cmd of set || []) {\n\t\t\t\t\tif (!seen.has(cmd)) {\n\t\t\t\t\t\tif (cmd(data, e, key)) {\n\t\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t}\n\t\t\t\t\t\tseen.add(cmd)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} finally {\n\t\tmap.any?.forEach(set =\u003e set?.forEach(cmd =\u003e cmd(data, e, firstKey)))\n\t}\n}\n\nconst getMap = \u003cT extends {}\u003e(editor: PrismEditor\u003cT\u003e) =\u003e {\n\tlet map = editorMap.get(editor) as HotkeyMap\u003cPrismEditor\u003cT\u003e\u003e\n\n\tif (!map) {\n\t\teditorMap.set(editor, (map = {}))\n\t\taddTextareaListener(editor, \"keydown\", e =\u003e {\n\t\t\trunHotkeys(e, map, editor)\n\t\t})\n\t}\n\n\treturn map\n}\n\n/**\n * Registers a command for the specified key.\n *\n * @param editor Editor to add the command to.\n * @param key Key the command will run for.\n * @param command Command for the specified key.\n * @param precedence Positive integer denoting the precedence of the command where `0`\n * is the highest precedence. Defaults to `2`.\n * @returns Function to remove the hotkey.\n */\nconst addEditorHotkey = \u003cT extends {}\u003e(\n\teditor: PrismEditor\u003cT\u003e,\n\tkey: string,\n\tcommand: EditorHotkey\u003cT\u003e,\n\tprecedence?: number,\n) =\u003e {\n\treturn addHotkey(getMap(editor), key, command, precedence)\n}\n\n/**\n * Registers a command for the specified key to the hotkey map.\n *\n * @param map Map to add the command to.\n * @param key Key the command will run for.\n * @param command Command for the specified key.\n * @param precedence Positive integer denoting the precedence of the command where `0`\n * is the highest precedence. Defaults to `2`.\n * @returns Function to remove the hotkey.\n */\nconst addHotkey = \u003cT\u003e(map: HotkeyMap\u003cT\u003e, key: string, command: Hotkey\u003cT\u003e, precedence = 2) =\u003e {\n\tlet set = ((map[key == \"any\" ? key : normalizeKey(key)] ||= [])[precedence] ||= new Set())\n\n\tset.add(command)\n\n\treturn () =\u003e {\n\t\tset.delete(command)\n\t}\n}\n\n/**\n * Registers a sequential hotkey to the specifed editor.\n *\n * @param editor Editor to add the sequence to.\n * @param sequence Sequence of keys to press for the command to be executed.\n * @param command Command to execute when the sequence is pressed.\n * @returns Function to remove the hotkey.\n */\nconst addEditorHotkeySequence = \u003cT extends {}\u003e(\n\teditor: PrismEditor\u003cT\u003e,\n\tsequence: string[],\n\tcommand: EditorHotkey\u003cT\u003e,\n\toptions?: HotkeySequenceOptions,\n) =\u003e {\n\treturn addHotkeySequence(getMap(editor), sequence, command, options)\n}\n\n/**\n * Registers a sequential hotkey to the specifed hotkey map.\n *\n * @param map Map to add the sequence to.\n * @param sequence Sequence of keys to press for the command to be executed.\n * @param command Command to execute when the sequence is pressed.\n * @returns Function to remove the hotkey.\n */\nconst addHotkeySequence = \u003cT\u003e(\n\tmap: HotkeyMap\u003cT\u003e,\n\tsequence: string[],\n\tcommand: Hotkey\u003cT\u003e,\n\toptions: HotkeySequenceOptions = {},\n) =\u003e {\n\tlet lastTimestamp: number\n\tlet handledEvent: KeyboardEvent\n\tlet current = 0\n\tlet last = sequence.length - 1\n\tlet removeHandler: () =\u003e void\n\n\tif (last \u003c 0) throw Error(\"Sequence must have a least one key\")\n\n\tconst { timeout = 2000, precedence, preventDefault = true } = options\n\n\tconst handleStep: Hotkey\u003cT\u003e = (data, e, key) =\u003e {\n\t\tif (current) removeHandler()\n\t\tif (lastTimestamp + timeout \u003c (lastTimestamp = Date.now())) {\n\t\t\treturn\n\t\t}\n\n\t\thandledEvent = e\n\n\t\tif (current == last) {\n\t\t\tcurrent = 0\n\t\t\treturn command(data, e, key)\n\t\t}\n\n\t\tif (preventDefault) e.preventDefault()\n\t\tremoveHandler = addHotkey(map, sequence[++current], handleStep, 0)\n\t}\n\n\tconst removeStart = addHotkey(\n\t\tmap,\n\t\tsequence[0],\n\t\t(data, e, key) =\u003e {\n\t\t\tif (handledEvent != e) {\n\t\t\t\tlastTimestamp = Date.now()\n\t\t\t\tcurrent = 0\n\t\t\t\thandleStep(data, e, key)\n\t\t\t}\n\t\t},\n\t\tprecedence,\n\t)\n\n\tconst removeAny = addHotkey(map, \"any\", (_, e) =\u003e {\n\t\tif (current \u0026\u0026 handledEvent != e \u0026\u0026 !isModifierKey(e)) {\n\t\t\tcurrent = 0\n\t\t\tremoveHandler()\n\t\t}\n\t})\n\n\treturn () =\u003e {\n\t\tremoveStart()\n\t\tremoveAny()\n\t\tremoveHandler?.()\n\t}\n}\n\n/**\n * Returns whether the key pressed is Alt, Shift, Control, or Meta.\n * @param e Keyboard event to check.\n */\nconst isModifierKey = (e: KeyboardEvent) =\u003e {\n\treturn modifierCodes.has(e.keyCode)\n}\n\nconst modifierCodes = new Set([16, 17, 18, 91, 92, 224, 225])\n\nconst mod = isMac ? 4 : 2\n\nconst keyCodeMap: Record\u003cnumber, string | undefined\u003e = {\n\t32: \" \",\n\t173: \"-\",\n\t186: \";\",\n\t187: \"=\",\n\t188: \",\",\n\t189: \"-\",\n\t190: \".\",\n\t191: \"/\",\n\t192: \"`\",\n\t219: \"[\",\n\t220: \"\\\\\",\n\t221: \"]\",\n\t222: \"'\",\n}\n\nconst keyCodeMapShift: Record\u003cnumber, string | undefined\u003e = {\n\t48: \")\",\n\t49: \"!\",\n\t50: \"@\",\n\t51: \"#\",\n\t52: \"$\",\n\t53: \"%\",\n\t54: \"^\",\n\t55: \"\u0026\",\n\t56: \"*\",\n\t57: \"(\",\n\t59: \":\",\n\t61: \"+\",\n\t173: \"_\",\n\t186: \":\",\n\t187: \"+\",\n\t188: \"\u003c\",\n\t189: \"_\",\n\t190: \"\u003e\",\n\t191: \"?\",\n\t192: \"~\",\n\t219: \"{\",\n\t220: \"|\",\n\t221: \"}\",\n\t222: '\"',\n}\n\nconst modifierMap: Record\u003cstring, number | undefined\u003e = {\n\talt: 1,\n\tcontrol: 2,\n\tctrl: 2,\n\tmeta: 4,\n\tcmd: 4,\n\tshift: 8,\n\tmod: isMac ? 4 : 2,\n}\n\nexport {\n\tnormalizeKey,\n\tgetKeysFromEvent,\n\taddEditorHotkey,\n\taddHotkey,\n\taddEditorHotkeySequence,\n\taddHotkeySequence,\n\trunHotkeys,\n\tisModifierKey,\n\tmod,\n}\n","import { addOverlay, regexEscape } from \"../../utils/index.js\"\r\nimport { createTemplate } from \"../../core.js\"\r\nimport { PrismEditor } from \"../../types.js\"\r\nimport { updateNode } from \"../../utils/local.js\"\r\n\r\nconst searchTemplate = /* @__PURE__ */ createTemplate(\r\n\t'\u003cdiv style=\"color:#0000;contain:strict;padding:0 var(--_pse) 0 var(--padding-left)\" aria-hidden=true\u003e ',\r\n)\r\n\r\nconst matchTemplate = /* @__PURE__ */ createTemplate(\"\u003cspan\u003e \")\r\n\r\nconst testBoundary = (str: string, position: number, pattern = /[_\\p{N}\\p{L}]{2}/u) =\u003e {\r\n\tif (!position) return false\r\n\treturn pattern.test(\r\n\t\tstr.slice(\r\n\t\t\tposition - (str.codePointAt(position - 2)! \u003e 0xffff ? 2 : 1),\r\n\t\t\tposition + (str.codePointAt(position)! \u003e 0xffff ? 2 : 1),\r\n\t\t),\r\n\t)\r\n}\r\n\r\nexport type SearchFilter = (start: number, end: number) =\u003e boolean\r\n\r\n/** Object with methods useful for performing a search and highlighting the matches. */\r\nexport interface SearchAPI {\r\n\t/**\r\n\t * Unhides the search container and highlights all matches of the specified string in the editor.\r\n\t * @param str String to search for.\r\n\t * @param caseSensitive Whether or not the search is case sensetive.\r\n\t * @param wholeWord Whether or not matches must be surrounded by word boundaries.\r\n\t * @param useRegExp If true, special characters won't be escaped when creating the RegExp.\r\n\t * @param selection Boundaries to search between. If excluded, all the code is searched.\r\n\t * @param filter A function called for each match with the start and end positions of the match.\r\n\t * If it returns false, the match won't be included.\r\n\t * @param wholeWordBoundry Pattern controlling the behavior of whole word search. Best left\r\n\t * undefined unless you know what you're doing. Does nothing if `wholeWord` isn't set to `true`.\r\n\t * Defaults to `/[_\\p{N}\\p{L}]{2}/u`.\r\n\t * @returns An error message if the RegExp was invalid.\r\n\t */\r\n\tsearch(\r\n\t\tstr: string,\r\n\t\tcaseSensitive?: boolean,\r\n\t\twholeWord?: boolean,\r\n\t\tuseRegExp?: boolean,\r\n\t\tselection?: [number, number],\r\n\t\tfilter?: SearchFilter,\r\n\t\twholeWordBoundry?: RegExp,\r\n\t): string | void\r\n\t/** Container that all the search results are appended to. */\r\n\treadonly container: HTMLDivElement\r\n\t/** Current regex used for searching. */\r\n\treadonly regex: RegExp\r\n\t/** Array of positions of all the matches. */\r\n\treadonly matches: [number, number][]\r\n\t/** Removes the search container and all matches. */\r\n\tstopSearch(): void\r\n}\r\n\r\n/** Function adding search functionality to an editor. */\r\nconst createSearchAPI = (editor: PrismEditor): SearchAPI =\u003e {\r\n\tconst container = searchTemplate()\r\n\tconst nodes: ChildNode[] = [container.firstChild!]\r\n\tconst matchPositions: [number, number][] = []\r\n\tconst stopSearch = () =\u003e {\r\n\t\tif (matchPositions[0]) {\r\n\t\t\tmatchPositions.length = 0\r\n\t\t\tcontainer.remove()\r\n\t\t}\r\n\t}\r\n\r\n\tlet regex: RegExp\r\n\tlet lastNode = 0\r\n\r\n\treturn {\r\n\t\tsearch(str, caseSensitive, wholeWord, useRegExp, selection, filter, pattern) {\r\n\t\t\tif (!str) return stopSearch()\r\n\t\t\tif (!useRegExp) str = regexEscape(str)\r\n\t\t\tconst value = editor.value\r\n\t\t\tconst searchStr = selection ? value.slice(...selection) : value\r\n\t\t\tconst offset = selection ? selection[0] : 0\r\n\r\n\t\t\tlet match: RegExpExecArray | null\r\n\t\t\tlet l: number\r\n\t\t\tlet index: number\r\n\t\t\tlet i = 0\r\n\r\n\t\t\ttry {\r\n\t\t\t\tregex = RegExp(str, caseSensitive ? \"gum\" : \"gumi\")\r\n\t\t\t\twhile ((match = regex.exec(searchStr))) {\r\n\t\t\t\t\tl = match[0].length\r\n\t\t\t\t\tindex = match.index + offset\r\n\t\t\t\t\tif (!l) regex.lastIndex += value.codePointAt(index)! \u003e 0xffff ? 2 : 1\r\n\t\t\t\t\tif (\r\n\t\t\t\t\t\twholeWord \u0026\u0026\r\n\t\t\t\t\t\t(testBoundary(value, index, pattern) || testBoundary(value, index + l, pattern))\r\n\t\t\t\t\t)\r\n\t\t\t\t\t\tcontinue\r\n\t\t\t\t\tif (!filter || filter(index, index + l)) matchPositions[i++] = [index, index + l]\r\n\t\t\t\t}\r\n\t\t\t} catch (e) {\r\n\t\t\t\tstopSearch()\r\n\t\t\t\treturn (\u003cError\u003ee).message\r\n\t\t\t}\r\n\r\n\t\t\tif (i) {\r\n\t\t\t\tmatchPositions.length = i\r\n\t\t\t\tl = Math.min(i * 2, 20000)\r\n\r\n\t\t\t\tfor (i = nodes.length; i \u003c= l; ) {\r\n\t\t\t\t\tnodes[i++] = matchTemplate()\r\n\t\t\t\t\tnodes[i++] = new Text()\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor (i = l; i \u003c lastNode; ) nodes[++i].remove()\r\n\t\t\t\tif (lastNode \u003c l) container.append(...nodes.slice(lastNode + 1, l + 1))\r\n\r\n\t\t\t\tlet prevEnd = 0\r\n\t\t\t\tfor (i = 0; i \u003c l; ) {\r\n\t\t\t\t\tconst [start, end] = matchPositions[i / 2]\r\n\t\t\t\t\tupdateNode(nodes[i++] as Text, value.slice(prevEnd, start))\r\n\t\t\t\t\tupdateNode(nodes[i++].firstChild as Text, value.slice(start, (prevEnd = end)))\r\n\t\t\t\t}\r\n\r\n\t\t\t\tupdateNode(nodes[l] as Text, value.slice(prevEnd))\r\n\t\t\t\tif (!container.parentNode) addOverlay(editor, container)\r\n\t\t\t\tlastNode = l\r\n\t\t\t} else stopSearch()\r\n\t\t},\r\n\t\tcontainer,\r\n\t\tget regex() {\r\n\t\t\treturn regex\r\n\t\t},\r\n\t\tmatches: matchPositions,\r\n\t\tstopSearch,\r\n\t}\r\n}\r\n\r\nexport { createSearchAPI, searchTemplate, matchTemplate }\r\n","import { PrismEditor } from \"../../index.js\"\r\nimport { insertText, setSelection } from \"../../utils/index.js\"\r\nimport { addTextareaListener, scrollToEl } from \"../../utils/local.js\"\r\nimport { SearchAPI, createSearchAPI } from \"./search.js\"\r\n\r\n/**\r\n * Object with methods useful for performing a search\r\n * and both highlighting and replacing the matches.\r\n */\r\nexport interface ReplaceAPI extends SearchAPI {\r\n\t/** Index of the match ahead of the cursor. */\r\n\tnext(): number\r\n\t/** Index of the match behind the cursor. */\r\n\tprev(): number\r\n\t/** Index of the closest match. */\r\n\tclosest(): number\r\n\t/**\r\n\t * Selects the match with the passed index and scrolls\r\n\t * it into view with the specified scroll padding.\r\n\t */\r\n\tselectMatch(index: number, scrollPadding?: number): void\r\n\t/**\r\n\t * If a match is selected and it's different to the provided string, it's replaced,\r\n\t * else the index of the closest match is returned.\r\n\t * If there's no selected match, the index of the closest match is returned.\r\n\t */\r\n\treplace(replacement: string): number | undefined\r\n\t/**\r\n\t * Replaces all search matches with the specified string.\r\n\t * @param replacement String to replace all matches with.\r\n\t * @param selection Does nothing. Kept for backwards compatibility.\r\n\t */\r\n\treplaceAll(replacement: string, selection?: [number, number]): void\r\n\t/** Removes the highlight container from the DOM and all potential event listeners. */\r\n\tdestroy(): void\r\n}\r\n\r\n/** Function adding both search and replace functionality to an editor. */\r\nconst createReplaceAPI = (editor: PrismEditor): ReplaceAPI =\u003e {\r\n\tconst getSelection = editor.getSelection\r\n\tconst search = createSearchAPI(editor)\r\n\tconst container = search.container\r\n\tconst matches = search.matches\r\n\tconst closest = () =\u003e {\r\n\t\tconst caretPos = getSelection()[0]\r\n\t\tconst l = matches.length\r\n\t\tfor (let i = l; i; ) {\r\n\t\t\tif (caretPos \u003e= matches[--i][1]) return (i + \u003cany\u003e(matches[i][0] \u003c caretPos)) % l\r\n\t\t}\r\n\t\treturn l ? 0 : -1\r\n\t}\r\n\r\n\tconst toggleClasses = () =\u003e {\r\n\t\tcurrentLine?.classList.toggle(\"match-highlight\")\r\n\t\tcurrentMatch?.classList.toggle(\"pce-match\")\r\n\t}\r\n\r\n\tconst removeSelection = () =\u003e {\r\n\t\tif (hasSelected) {\r\n\t\t\ttoggleClasses()\r\n\t\t\thasSelected = false\r\n\t\t}\r\n\t}\r\n\r\n\tconst removeHandler = addTextareaListener(editor, \"focus\", removeSelection)\r\n\r\n\tlet currentLine: HTMLDivElement\r\n\tlet currentMatch: HTMLSpanElement\r\n\tlet hasSelected = false\r\n\r\n\treturn Object.assign(search, {\r\n\t\tnext() {\r\n\t\t\tconst cursor = getSelection()[1]\r\n\t\t\tconst l = matches.length\r\n\t\t\tfor (let i = 0, match: [number, number]; i \u003c l; i++) {\r\n\t\t\t\tmatch = matches[i]\r\n\t\t\t\tif (match[0] - \u003cany\u003e(match[0] == match[1]) \u003e= cursor) return i\r\n\t\t\t}\r\n\t\t\treturn l ? 0 : -1\r\n\t\t},\r\n\t\tprev() {\r\n\t\t\tconst cursor = getSelection()[0]\r\n\t\t\tconst l = matches.length\r\n\t\t\tfor (let i = l, match: [number, number]; i; ) {\r\n\t\t\t\tmatch = matches[--i]\r\n\t\t\t\tif (match[1] + \u003cany\u003e(match[0] == match[1]) \u003c= cursor) return i\r\n\t\t\t}\r\n\t\t\treturn l - 1\r\n\t\t},\r\n\t\tclosest,\r\n\t\tselectMatch(index: number, scrollPadding?: number) {\r\n\t\t\tremoveSelection()\r\n\t\t\tif (matches[index]) {\r\n\t\t\t\tsetSelection(editor, ...matches[index])\r\n\t\t\t\tcurrentLine = editor.lines[editor.activeLine]\r\n\t\t\t\tcurrentMatch = \u003cHTMLSpanElement\u003econtainer.children[index]\r\n\t\t\t\thasSelected = true\r\n\t\t\t\ttoggleClasses()\r\n\t\t\t\tif (currentMatch) {\r\n\t\t\t\t\tscrollToEl(editor, currentMatch, scrollPadding)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\t\treplace(str: string) {\r\n\t\t\tif (matches[0]) {\r\n\t\t\t\tlet index = closest()\r\n\t\t\t\tlet [start, end] = matches[index]\r\n\t\t\t\tlet [caretStart, caretEnd] = getSelection()\r\n\t\t\t\tlet notSelected = start != caretStart || end != caretEnd\r\n\r\n\t\t\t\tif (notSelected) return index\r\n\t\t\t\tif (editor.value.slice(start, end) == str) return matches[++index] ? index : 0\r\n\t\t\t\treturn insertText(editor, str)!\r\n\t\t\t}\r\n\t\t},\r\n\t\treplaceAll(str: string) {\r\n\t\t\tif (!matches[0]) return\r\n\t\t\tlet value = editor.value\r\n\t\t\tlet [start, end] = getSelection()\r\n\t\t\tlet newLen = str.length\r\n\t\t\tlet newStart = start\r\n\t\t\tlet newEnd = end\r\n\t\t\tlet newValue = \"\"\r\n\t\t\tlet l = matches.length\r\n\r\n\t\t\tfor (let i = 0; i \u003c l; i++) {\r\n\t\t\t\tconst [matchStart, matchEnd] = matches[i]\r\n\t\t\t\tconst lengthDiff = newLen - matchEnd + matchStart\r\n\t\t\t\tconst move = (pos: number) =\u003e\r\n\t\t\t\t\tmatchStart \u003e pos\r\n\t\t\t\t\t\t? 0\r\n\t\t\t\t\t\t: pos \u003e= matchEnd\r\n\t\t\t\t\t\t? lengthDiff\r\n\t\t\t\t\t\t: lengthDiff \u003c 0 \u0026\u0026 pos \u003e matchStart + newLen\r\n\t\t\t\t\t\t? newLen + matchStart - pos\r\n\t\t\t\t\t\t: 0\r\n\r\n\t\t\t\tnewEnd += move(end)\r\n\t\t\t\tnewStart += move(start)\r\n\t\t\t\tnewValue += i ? value.slice(matches[i - 1][1], matchStart) + str : str\r\n\t\t\t}\r\n\r\n\t\t\tinsertText(editor, newValue, matches[0][0], matches[l - 1][1], newStart, newEnd)\r\n\t\t},\r\n\t\tdestroy() {\r\n\t\t\tremoveHandler()\r\n\t\t\tremoveSelection()\r\n\t\t\tcontainer.remove()\r\n\t\t},\r\n\t})\r\n}\r\n\r\nexport { createReplaceAPI }\r\n","import { BasicExtension } from \"../../index.js\"\r\nimport { SearchAPI, SearchFilter, createSearchAPI } from \"./search.js\"\r\n\r\nexport interface SelectionMatchHighlighter extends BasicExtension {\r\n\t/**\r\n\t * Search API used by the extension.\r\n\t * Can be used get the position of the matches for example.\r\n\t * This property is only present after the extension is added to an editor.\r\n\t */\r\n\tapi?: SearchAPI\r\n}\r\n\r\nexport interface WordHighlighter extends SelectionMatchHighlighter {\r\n\t/** Sets the search filter used. Useful for updating the filter after changing an editor's language. */\r\n\tsetFilter(newFilter: SearchFilter): void\r\n}\r\n\r\n/**\r\n * Extension that highlights selection matches in an editor.\r\n * @param caseSensitive Whether or not matches must have the same case. Defaults to false.\r\n * @param minLength Minimum length needed to perform a search. Defaults to 1.\r\n * @param maxLength Maximum length at which to perform a search. Defaults to 200.\r\n\r\n * Lower values of `minLength` and higher values of `maxLength` can impact performance.\r\n * \r\n * The CSS-selector `.selection-matches span` can be used to style the matches.\r\n */\r\nconst highlightSelectionMatches = (caseSensitive?: boolean, minLength = 1, maxLength = 200) =\u003e {\r\n\tconst self: SelectionMatchHighlighter = editor =\u003e {\r\n\t\tconst searchAPI = (self.api = createSearchAPI(editor))\r\n\t\tconst container = searchAPI.container\r\n\r\n\t\tcontainer.style.zIndex = \u003cany\u003e-1\r\n\t\tcontainer.className = \"selection-matches\"\r\n\r\n\t\teditor.on(\"selectionChange\", ([start, end], value) =\u003e {\r\n\t\t\tvalue = editor.focused ? value.slice(start, end) : \"\"\r\n\t\t\tstart += value.search(/\\S/)\r\n\t\t\tvalue = value.trim()\r\n\t\t\tlet l = value.length\r\n\r\n\t\t\tsearchAPI.search(\r\n\t\t\t\tminLength \u003e l || l \u003e maxLength ? \"\" : value,\r\n\t\t\t\tcaseSensitive,\r\n\t\t\t\tfalse,\r\n\t\t\t\tfalse,\r\n\t\t\t\tundefined,\r\n\t\t\t\t(mStart, mEnd) =\u003e mStart \u003e start || mEnd \u003c= start\r\n\t\t\t)\r\n\t\t})\r\n\t}\r\n\treturn self\r\n}\r\n\r\n/**\r\n * Extension that highlights all instances of the word the cursor is on if there's no selection.\r\n * @param filter Function that can filter away matches based on their position.\r\n * The filter can be changed later using the `setFilter` method.\r\n * @param includeHyphens A function returning whether or not hyphens should be included in the search.\r\n * For languages that don't commonly use hyphens as an operator (such as CSS), it makes sense to\r\n * return true. If this parameter is omitted, hyphens are not included.\r\n *\r\n * The CSS-selector `.word-matches span` can be used to style the matches.\r\n *\r\n * @example\r\n * This filters away all words that start inside a string, comment or keyword or regex token.\r\n * Different filter functions should be chosen based on the language.\r\n * ```\r\n * const selector = \".string, .comment, .keyword, .regex\"\r\n * const filter = start =\u003e !getClosestToken(editor, selector, 0, 0, start)\r\n * const includeHyphens = position =\u003e getLanguage(editor, position) == \"css\"\r\n *\r\n * editor.addExtensions(\r\n * \thighlightCurrentWord(filter, includeHyphens)\r\n * )\r\n * ```\r\n */\r\nconst highlightCurrentWord = (\r\n\tfilter?: SearchFilter,\r\n\tincludeHyphens?: (cursorPosition: number) =\u003e boolean,\r\n) =\u003e {\r\n\tconst self: WordHighlighter = editor =\u003e {\r\n\t\tlet noHighlight = false\r\n\t\tlet searchAPI = (self.api = createSearchAPI(editor))\r\n\t\tlet container = searchAPI.container\r\n\r\n\t\tcontainer.style.zIndex = \u003cany\u003e-1\r\n\t\tcontainer.className = \"word-matches\"\r\n\r\n\t\teditor.on(\"update\", () =\u003e (noHighlight = true))\r\n\t\teditor.on(\"selectionChange\", ([start, end], value) =\u003e {\r\n\t\t\tif (start \u003c end || !editor.focused || noHighlight) searchAPI.search(\"\")\r\n\t\t\telse {\r\n\t\t\t\tlet group = `[_$\\\\p{L}\\\\d${includeHyphens \u0026\u0026 includeHyphens(start) ? \"-\" : \"\"}]`\r\n\t\t\t\tlet before = value.slice(0, start).match(RegExp(group + \"*$\", \"u\"))!\r\n\t\t\t\tlet index = before.index!\r\n\t\t\t\tlet word = before[0] + value.slice(start).match(RegExp(\"^\" + group + \"*\", \"u\"))![0]\r\n\t\t\t\tsearchAPI.search(\r\n\t\t\t\t\t/^-*(\\d|$)/.test(word) || (filter \u0026\u0026 !filter(index, index + word.length)) ? \"\" : word,\r\n\t\t\t\t\ttrue,\r\n\t\t\t\t\ttrue,\r\n\t\t\t\t\tfalse,\r\n\t\t\t\t\tundefined,\r\n\t\t\t\t\tfilter,\r\n\t\t\t\t\tRegExp(group + \"{2}\", \"u\"),\r\n\t\t\t\t)\r\n\t\t\t}\r\n\t\t\tnoHighlight = false\r\n\t\t})\r\n\t}\r\n\tself.setFilter = newFilter =\u003e (filter = newFilter)\r\n\treturn self\r\n}\r\n\r\nexport { highlightSelectionMatches, highlightCurrentWord }\r\n","import { InputSelection, BasicExtension } from \"../../index.js\"\nimport { createTemplate, preventDefault, addListener, numLines, doc } from \"../../core.js\"\nimport {\n\tregexEscape,\n\tgetModifierCode,\n\tisMac,\n\tisWebKit,\n\taddOverlay,\n\tgetLineBefore,\n} from \"../../utils/index.js\"\nimport { createReplaceAPI } from \"./replace.js\"\nimport { getLineEnd, getLineStart, getStyleValue, updateNode } from \"../../utils/local.js\"\nimport { mod } from \"../commands/utils.js\"\n\nconst shortcut = ` (Alt+${isMac ? \"Cmd+\" : \"\"}`\n\nconst template = /* @__PURE__ */ createTemplate(\n\t`\u003cdiv class=prism-search-container style=display:flex;align-items:flex-start;justify-content:flex-end\u003e\u003cdiv dir=ltr class=prism-search\u003e\u003cbutton type=button aria-expanded=false title=\"Toggle Replace\" class=pce-expand\u003e\u003c/button\u003e\u003cdiv spellcheck=false\u003e\u003cdiv\u003e\u003cdiv class=\"pce-input pce-find\"\u003e\u003cinput autocorrect=off autocapitalize=off placeholder=Find aria-label=Find\u003e\u003cbutton type=button class=pce-prev title=\"Previous Match (Shift+Enter)\"\u003e\u003c/button\u003e\u003cbutton type=button class=pce-next title=\"Next Match (Enter)\"\u003e\u003c/button\u003e\u003cdiv class=search-error\u003e\u003c/div\u003e\u003c/div\u003e\u003cbutton type=button class=pce-close title=\"Close (Esc)\"\u003e\u003c/button\u003e\u003c/div\u003e\u003cdiv class=\"pce-input pce-replace\"\u003e\u003cinput autocorrect=off autocapitalize=off placeholder=Replace aria-label=Replace\u003e\u003cbutton type=button title=(Enter)\u003eReplace\u003c/button\u003e\u003cbutton type=button title=(${\n\t\tisMac ? \"Cmd\" : \"Ctrl+Alt\"\n\t}+Enter)\u003eAll\u003c/button\u003e\u003c/div\u003e\u003cdiv class=pce-options\u003e\u003cdiv class=pce-match-count\u003e0\u003cspan\u003e of \u003c/span\u003e0\u003c/div\u003e\u003cbutton type=button aria-pressed=false class=pce-regex title=\"RegExp Search${shortcut}R)\"\u003e\u003cspan aria-hidden=true\u003e\u003c/span\u003e\u003c/button\u003e\u003cbutton type=button aria-pressed=false title=\"Preserve Case${shortcut}P)\"\u003e\u003cspan aria-hidden=true\u003eAa\u003c/span\u003e\u003c/button\u003e\u003cbutton type=button aria-pressed=false class=pce-whole title=\"Match Whole Word${shortcut}W)\"\u003e\u003cspan aria-hidden=true\u003eab\u003c/span\u003e\u003c/button\u003e\u003cbutton type=button aria-pressed=false class=pce-in-selection title=\"Find in Selection${shortcut}L)\"\u003e`,\n)\n\nconst toggleAttr = (el: Element, name: string) =\u003e\n\tel.setAttribute(name, \u003cany\u003e(el.getAttribute(name) == \"false\"))\n\nexport interface SearchWidget extends BasicExtension {\n\t/** The search widget's outer element. */\n\treadonly element: HTMLDivElement\n\t/**\n\t * Hides the search widget and removes most event listeners.\n\t * @param focusTextarea Whether the editor's `textarea` should gain focus. Defaults to true.\n\t */\n\tclose: (focusTextarea?: boolean) =\u003e void\n\t/**\n\t * Opens the search widget.\n\t * @param focusInput Whether the widgets's search input should gain focus. Defaults to true.\n\t */\n\topen: (focusInput?: boolean) =\u003e void\n}\n\n/**\n * Extension that adds a widget for search and replace functionality.\n * This extension needs styles from `prism-code-editor/search.css`.\n *\n * Once added to an editor the widget can be opened/closed programmatically with the\n * `editor.extensions.searchWidget` object.\n */\nexport const searchWidget = (): SearchWidget =\u003e {\n\tlet prevLength: number\n\tlet useRegExp: boolean\n\tlet matchCase: boolean\n\tlet wholeWord: boolean\n\tlet searchSelection: [number, number] | undefined\n\tlet isOpen: boolean\n\tlet currentSelection: InputSelection\n\tlet prevUserSelection: InputSelection\n\tlet prevMargin: number\n\tlet selectNext = false\n\tlet marginTop: number\n\n\tconst self: SearchWidget = editor =\u003e {\n\t\teditor.extensions.searchWidget = self\n\n\t\tconst { textarea, wrapper, container, getSelection } = editor\n\t\tconst replaceAPI = createReplaceAPI(editor)\n\n\t\tconst startSearch = (selectMatch?: boolean) =\u003e {\n\t\t\tif (selectMatch \u0026\u0026 !isWebKit) textarea.setSelectionRange(...prevUserSelection)\n\t\t\tconst error = replaceAPI.search(\n\t\t\t\tfindInput.value,\n\t\t\t\tmatchCase,\n\t\t\t\twholeWord,\n\t\t\t\tuseRegExp,\n\t\t\t\tsearchSelection,\n\t\t\t)\n\t\t\tconst index = error ? -1 : selectNext ? replaceAPI.next() : replaceAPI.closest()\n\n\t\t\t// @ts-expect-error Allow type coercion\n\t\t\tupdateNode(current, index + 1)\n\t\t\t// @ts-expect-error Allow type coercion\n\t\t\tupdateNode(total, replaceAPI.matches.length)\n\t\t\tfindContainer.classList.toggle(\"pce-error\", !!error)\n\n\t\t\tif (error) errorEl.textContent = error\n\t\t\telse if (selectMatch || selectNext) replaceAPI.selectMatch(index, prevMargin)\n\t\t}\n\n\t\tconst open = (focusInput = true) =\u003e {\n\t\t\tif (!isOpen) {\n\t\t\t\tisOpen = true\n\t\t\t\tif (marginTop == null) prevMargin = marginTop = getStyleValue(wrapper, \"marginTop\")\n\t\t\t\tprevUserSelection = getSelection()\n\t\t\t\taddOverlay(editor, searchContainer)\n\t\t\t\tupdateMargin()\n\t\t\t\tresize()\n\t\t\t\tobserver?.observe(container)\n\t\t\t}\n\t\t\tif (focusInput) findInput.select()\n\t\t}\n\n\t\tconst close = (self.close = (focusTextarea = true) =\u003e {\n\t\t\tif (isOpen) {\n\t\t\t\tisOpen = false\n\t\t\t\treplaceAPI.stopSearch()\n\t\t\t\tsearchContainer.remove()\n\t\t\t\tupdateMargin()\n\t\t\t\tobserver?.disconnect()\n\t\t\t\tfocusTextarea \u0026\u0026 textarea.focus()\n\t\t\t}\n\t\t})\n\n\t\tconst move = (next?: boolean) =\u003e {\n\t\t\tif (replaceAPI.matches[0]) {\n\t\t\t\tconst index = replaceAPI[next ? \"next\" : \"prev\"]()\n\t\t\t\treplaceAPI.selectMatch(index, prevMargin)\n\t\t\t\t// @ts-expect-error Allow type coercion\n\t\t\t\tupdateNode(current, index + 1)\n\t\t\t}\n\t\t}\n\n\t\tconst updateMargin = () =\u003e {\n\t\t\tconst newMargin = isOpen\n\t\t\t\t? getStyleValue(search, \"top\") + getStyleValue(search, \"height\")\n\t\t\t\t: marginTop\n\t\t\tconst newScroll = container.scrollTop + newMargin - prevMargin\n\n\t\t\twrapper.style.marginTop = isOpen ? newMargin + \"px\" : \"\"\n\t\t\tcontainer.scrollTop = newScroll\n\t\t\tprevMargin = newMargin\n\t\t}\n\n\t\tconst resize = () =\u003e\n\t\t\tdiv.style.setProperty(\n\t\t\t\t\"--search-width\",\n\t\t\t\t`min(${container.clientWidth - 2}px - 2.4em - var(--padding-left),20em)`,\n\t\t\t)\n\n\t\tconst observer = window.ResizeObserver \u0026\u0026 new ResizeObserver(resize)\n\n\t\tconst replace = () =\u003e {\n\t\t\tselectNext = true\n\t\t\tconst index = replaceAPI.replace(replaceInput.value)\n\t\t\tif (index != null) {\n\t\t\t\t// @ts-expect-error Allow type coercion\n\t\t\t\tupdateNode(current, index + 1)\n\t\t\t\treplaceAPI.selectMatch(index, prevMargin)\n\t\t\t}\n\t\t\tselectNext = false\n\t\t}\n\n\t\tconst replaceAll = () =\u003e {\n\t\t\treplaceAPI.replaceAll(replaceInput.value)\n\t\t}\n\n\t\tconst keyCodeButtonMap: Record\u003cstring, HTMLButtonElement\u003e = {\n\t\t\t80 /* P */: matchCaseEl,\n\t\t\t87 /* W */: wholeWordEl,\n\t\t\t82 /* R */: useRegExpEl,\n\t\t\t76 /* L */: inSelectionEl,\n\t\t}\n\n\t\tconst elementHandlerMap = new Map\u003cHTMLElement, () =\u003e any\u003e([\n\t\t\t[nextEl, () =\u003e move(true)],\n\t\t\t[prevEl, move],\n\t\t\t[closeEl, close],\n\t\t\t[replaceEl, replace],\n\t\t\t[replaceAllEl, replaceAll],\n\t\t\t[\n\t\t\t\ttoggle,\n\t\t\t\t() =\u003e {\n\t\t\t\t\ttoggleAttr(toggle, \"aria-expanded\")\n\t\t\t\t\tupdateMargin()\n\t\t\t\t},\n\t\t\t],\n\t\t\t[matchCaseEl, () =\u003e (matchCase = !matchCase)],\n\t\t\t[useRegExpEl, () =\u003e (useRegExp = !useRegExp)],\n\t\t\t[wholeWordEl, () =\u003e (wholeWord = !wholeWord)],\n\t\t\t[\n\t\t\t\tinSelectionEl,\n\t\t\t\t() =\u003e {\n\t\t\t\t\tconst value = editor.value\n\t\t\t\t\tif (searchSelection) searchSelection = undefined\n\t\t\t\t\telse {\n\t\t\t\t\t\tsearchSelection = \u003c[number, number]\u003egetSelection().slice(0, 2)\n\n\t\t\t\t\t\tif (numLines(value, ...searchSelection) \u003e 1) {\n\t\t\t\t\t\t\tsearchSelection = [\n\t\t\t\t\t\t\t\tgetLineStart(value, searchSelection[0]),\n\t\t\t\t\t\t\t\tgetLineEnd(value, searchSelection[1]),\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tprevLength = value.length\n\t\t\t\t},\n\t\t\t],\n\t\t])\n\n\t\tconst getSelectedWord = () =\u003e {\n\t\t\tlet [start, end] = getSelection()\n\t\t\tlet value = editor.value\n\t\t\tlet word =\n\t\t\t\tvalue.slice(start, end) ||\n\t\t\t\t/[_\\p{N}\\p{L}]*$/u.exec(getLineBefore(value, start))![0] +\n\t\t\t\t\t/^[_\\p{N}\\p{L}]*/u.exec(value.slice(start))![0]\n\n\t\t\treturn word.includes(\"\\n\") ? \"\" : useRegExp ? regexEscape(word) : word\n\t\t}\n\n\t\taddListener(wrapper, \"keydown\", (e: KeyboardEvent) =\u003e {\n\t\t\tconst code = getModifierCode(e)\n\t\t\tconst keyCode = e.keyCode\n\t\t\tconst isF3 = keyCode == 114\n\n\t\t\t// Mod+F\n\t\t\tif (keyCode == 70 \u0026\u0026 code == mod) {\n\t\t\t\tpreventDefault(e)\n\t\t\t\topen()\n\t\t\t\tlet word = getSelectedWord()\n\n\t\t\t\tif (word) {\n\t\t\t\t\tdoc!.execCommand(\"insertText\", false, word)\n\t\t\t\t\tfindInput.select()\n\t\t\t\t} else {\n\t\t\t\t\tstartSearch()\n\t\t\t\t}\n\t\t\t\t// Shift?+F3 or Mod+Shift?+G\n\t\t\t} else if ((isF3 || keyCode == 71) \u0026\u0026 (code \u0026 7) == (isF3 ? 0 : mod)) {\n\t\t\t\tpreventDefault(e)\n\t\t\t\topen(false)\n\t\t\t\tfindInput.value ||= getSelectedWord()\n\t\t\t\tstartSearch()\n\t\t\t\tmove(code \u003c 8)\n\t\t\t}\n\t\t})\n\t\taddListener(textarea, \"beforeinput\", () =\u003e {\n\t\t\tif (isOpen \u0026\u0026 searchSelection) currentSelection = getSelection()\n\t\t})\n\t\teditor.on(\"update\", () =\u003e {\n\t\t\tif (!isOpen) return\n\t\t\tif (searchSelection \u0026\u0026 currentSelection) {\n\t\t\t\t// This preserves the selection well for normal typing,\n\t\t\t\t// but for indenting, toggling comments, etc. it doesn't\n\t\t\t\tconst diff = prevLength - (prevLength = editor.value.length)\n\t\t\t\tconst end = currentSelection[1]\n\n\t\t\t\tif (end \u003c= searchSelection[1]) {\n\t\t\t\t\tsearchSelection[1] -= diff\n\t\t\t\t\tif (end \u003c= searchSelection[0] - +(diff \u003c 0)) searchSelection[0] -= diff\n\t\t\t\t}\n\t\t\t}\n\t\t\tstartSearch()\n\t\t})\n\t\teditor.on(\"selectionChange\", selection =\u003e {\n\t\t\tif (isOpen \u0026\u0026 editor.focused) prevUserSelection = selection\n\t\t})\n\n\t\taddListener(searchContainer, \"click\", e =\u003e {\n\t\t\tconst target = \u003cHTMLElement\u003ee.target\n\t\t\tconst remove = editor.on(\"update\", () =\u003e target.focus())\n\t\t\telementHandlerMap.get(target)?.()\n\t\t\tif (target.matches(\".pce-options\u003ebutton\")) {\n\t\t\t\ttoggleAttr(target, \"aria-pressed\")\n\t\t\t\tstartSearch(true)\n\t\t\t}\n\t\t\tremove()\n\t\t})\n\n\t\taddListener(findInput, \"input\", () =\u003e isOpen \u0026\u0026 startSearch(true))\n\n\t\taddListener(searchContainer, \"keydown\", e =\u003e {\n\t\t\tconst shortcut = getModifierCode(e)\n\t\t\tconst target = \u003cHTMLElement\u003ee.target\n\t\t\tconst keyCode = e.keyCode\n\t\t\tconst isFind = target == findInput\n\t\t\tif (shortcut == (isMac ? 5 : 1)) {\n\t\t\t\tif (keyCodeButtonMap[keyCode]) {\n\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\tkeyCodeButtonMap[keyCode].click()\n\t\t\t\t}\n\t\t\t} else if (keyCode == 13 \u0026\u0026 target.tagName == \"INPUT\") {\n\t\t\t\tpreventDefault(e)\n\t\t\t\tif (!shortcut) isFind ? move(true) : replaceEl.click()\n\t\t\t\telse if (shortcut == 8 \u0026\u0026 isFind) move()\n\t\t\t\telse if (shortcut == (isMac ? 4 : 3) \u0026\u0026 !isFind) replaceAllEl.click()\n\t\t\t\ttarget.focus()\n\t\t\t} else if (!shortcut \u0026\u0026 keyCode == 27) close()\n\t\t})\n\n\t\tself.open = focusInput =\u003e {\n\t\t\topen(focusInput)\n\t\t\tstartSearch()\n\t\t}\n\n\t\treplaceAPI.container.className = \"pce-matches\"\n\t}\n\n\tconst searchContainer = \u003cHTMLDivElement\u003etemplate()\n\t// @ts-expect-error\n\tconst search = (self.element = \u003cHTMLDivElement\u003esearchContainer.firstChild)\n\tconst [toggle, div] = \u003c[HTMLButtonElement, HTMLDivElement]\u003e(\u003cunknown\u003esearch.children)\n\tconst rows = div.children\n\tconst [findContainer, closeEl] = \u003c[HTMLDivElement, HTMLButtonElement]\u003e(\u003cunknown\u003erows[0].children)\n\tconst [findInput, prevEl, nextEl, errorEl] = \u003c\n\t\t[HTMLInputElement, HTMLButtonElement, HTMLButtonElement, HTMLDivElement]\n\t\u003e(\u003cunknown\u003efindContainer.children)\n\tconst [replaceInput, replaceEl, replaceAllEl] = \u003c\n\t\t[HTMLInputElement, HTMLButtonElement, HTMLButtonElement]\n\t\u003e(\u003cunknown\u003erows[1].children)\n\tconst [matchCount, useRegExpEl, matchCaseEl, wholeWordEl, inSelectionEl] = \u003c\n\t\t[HTMLDivElement, HTMLButtonElement, HTMLButtonElement, HTMLButtonElement, HTMLButtonElement]\n\t\u003e(\u003cunknown\u003erows[2].children)\n\tconst [current, , total] = \u003cText[]\u003e(\u003cunknown\u003ematchCount.childNodes)\n\n\tself.open = self.close = () =\u003e {}\n\n\treturn self\n}\n","import { BasicExtension } from \"../../index.js\"\nimport { tokenizeInvisibles } from \"../../prism/utils/invisibles.js\"\nimport { createSearchAPI } from \"./search.js\"\n\n/**\n * Extension that highlights selected tabs and spaces as an overlay. To instead highlight\n * all spaces and tabs, use {@link tokenizeInvisibles}.\n *\n * Requires styling from `prism-code-editor/invisibles.css`.\n */\nconst showInvisibles = (): BasicExtension =\u003e {\n\treturn editor =\u003e {\n\t\tconst searchAPI = createSearchAPI(editor)\n\t\tconst matches = searchAPI.matches\n\t\tconst container = searchAPI.container\n\t\tconst nodes = container.children\n\t\tconst tabs: boolean[] = []\n\t\tconst update = () =\u003e {\n\t\t\tconst value = editor.value\n\t\t\tconst [start, end] = editor.getSelection()\n\n\t\t\tsearchAPI.search(\" |\\t\", true, false, true, [start, end])\n\t\t\tfor (let i = 0, l = matches.length; i \u003c l; i++) {\n\t\t\t\tif ((value[matches[i][0]] == \"\\t\") == !tabs[i]) {\n\t\t\t\t\tnodes[i].className = (tabs[i] = !tabs[i]) ? \"pce-tab\" : \"\"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tcontainer.className = \"pce-invisibles\"\n\t\tif (editor.value) update()\n\t\teditor.on(\"selectionChange\", update)\n\t}\n}\n\nexport { showInvisibles }\n"],"version":3}
