{"mappings":"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","names":["globalKey","prismGlobal","plainTextGrammar","rest","tokenize","languages","prismGlobal","plainTextGrammar","doc","addListener","target","type","listener","options","numLines","str","start","end","count","languageMap","selectionChange","doc","addListener","getLineEnd","text","position","addListener2","element","type","listener","options","addListener","addTextareaListener","editor","voidlessLangs","getClosestToken","editor","selector","marginLeft","marginRight","position","value","line","numLines","walker","doc","node","offset","getLineEnd","userAgent","doc","isMac","isChrome","isWebKit","highlightBracketPairs","editor","prev","els","selectionChange","matcher","start","end","brackets","pairs","opening","closing","i","bracket","toggleActive","getClosestToken","add","el","addTextareaListener"],"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/matchBrackets/highlight.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","/** @module highlight-brackets */\r\n\r\nimport { BasicExtension } from \"../../index.js\"\r\nimport { Bracket, BracketMatcher } from \"./index.js\"\r\nimport { getClosestToken } from \"../../utils/index.js\"\r\nimport { addTextareaListener } from \"../../utils/local.js\"\r\n\r\n/**\r\n * Extension adding a `selectionChange` handler to highlight the bracker pair closest to\r\n * the cursor.\r\n *\r\n * You must to add a {@link BracketMatcher} to your editor for this extension to work.\r\n *\r\n * The `.active-bracket` CSS selector can be used to highlight the brackets.\r\n */\r\nexport const highlightBracketPairs = (): BasicExtension =\u003e editor =\u003e {\r\n\tlet prev: Bracket\r\n\tlet els: HTMLSpanElement[] = []\r\n\tlet selectionChange = () =\u003e {\r\n\t\tlet matcher = editor.extensions.matchBrackets\r\n\t\tlet [start, end] = editor.getSelection()\r\n\r\n\t\tif (matcher) {\r\n\t\t\tlet brackets = matcher.brackets\r\n\t\t\tlet pairs = matcher.pairs\r\n\t\t\tlet opening!: Bracket\r\n\t\t\tlet closing!: Bracket\r\n\t\t\tif (editor.focused \u0026\u0026 start == end) {\r\n\t\t\t\tfor (let i = 0, bracket: Bracket; (bracket = brackets[++i]); ) {\r\n\t\t\t\t\tif (!bracket[5] \u0026\u0026 bracket[2] \u003e= end \u0026\u0026 brackets[pairs[i]!]?.[1] \u003c= end) {\r\n\t\t\t\t\t\topening = brackets[pairs[i]!]\r\n\t\t\t\t\t\tclosing = bracket\r\n\t\t\t\t\t\tbreak\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (closing != prev) {\r\n\t\t\t\ttoggleActive()\r\n\t\t\t\tif (closing) {\r\n\t\t\t\t\tels = [opening, closing].map(\r\n\t\t\t\t\t\tbracket =\u003e getClosestToken(editor, \".punctuation\", 0, -1, bracket[1])!,\r\n\t\t\t\t\t)\r\n\r\n\t\t\t\t\tif (els[0] != els[1] \u0026\u0026 opening[2] == closing[1]) {\r\n\t\t\t\t\t\tels[0].textContent += els[1].textContent!\r\n\t\t\t\t\t\tels[1].textContent = \"\"\r\n\t\t\t\t\t\tels[1] = els[0]\r\n\t\t\t\t\t}\r\n\t\t\t\t\ttoggleActive(true)\r\n\t\t\t\t} else els = []\r\n\t\t\t}\r\n\t\t\tprev = closing\r\n\t\t}\r\n\t}\r\n\tlet toggleActive = (add?: boolean) =\u003e\r\n\t\tels.forEach(el =\u003e el.classList.toggle(\"active-bracket\", !!add))\r\n\r\n\taddTextareaListener(editor, \"focus\", selectionChange)\r\n\taddTextareaListener(editor, \"blur\", selectionChange)\r\n\teditor.on(\"selectionChange\", selectionChange)\r\n}\r\n"],"version":3}
