{"mappings":";AAyQA,IAAMA,EAAM,IAAM,OAAO,OAAS,SAAW,KAY7C,IAAMC,EAAA,CACLC,EACAC,EACAC,EACAC,IACIH,EAAO,iBAAiBC,EAAMC,EAAUC,CAAO,EAgBpD,IAAMC,EAAwC,CAAC,EAa/C,IAAIC,EAGAC,GAAKC,EAAYD,EAAK,kBAAA,IAAyBD,IAAkB,CAAC,ECxStE,IAAMG,EAAA,CAAgBC,EAAcC,IACnCA,EAAWD,EAAK,YAAY;EAAMC,EAAW,CAAC,EAAI,EAAI,EA0CvD,IAAMC,EAAgB,IAAI,IAAI,2DAA2D,MAAM,GAAG,CAAC,ECrCnG,IAAMC,EAAA,CAAiBC,EAAcC,IACpCD,EAAK,MAAME,EAAaF,EAAMC,CAAQ,EAAGA,CAAQ,EAiKlD,IAAME,EAAYC,EAAM,UAAU,UAAY,GAExCC,EAAQD,EAAM,qBAAqB,KAAK,UAAU,QAAQ,EAAI,GAE9DE,EAAW,WAAW,KAAKH,CAAS,EAEpCI,EAAW,CAACD,GAAY,gBAAgB,KAAKH,CAAS,EClJ5D,IAAIK,EAAW,CAAC,EAAE,SCvClB,IAAMC,EAAgB,cAItB,IAAMC,EAAc,iBAOpB,IAAMC,EAAA,CAAmB,CAACC,EAAOC,CAAA,EAAsBC,IAC/CC,EAAc,KAAKD,EAAMF,EAAQ,CAAA,EAAKE,EAAMD,CAAA,CAAI,EAGlDG,EAA8B,CACnC,KAAM,KACN,MAAO,CAAC,KAAM,IAAI,CACnB,EAyDA,IAAMC,EAAA,CAAoBC,EAAWC,EAAcC,EAAgBC,KAA2B,CAC7F,SAAAH,EACA,WAAY,CAAA,CACV,CAACI,CAAA,EAAQC,IAAUH,EAAc,KAAKI,EAAcD,EAAOD,CAAK,CAAC,EAClEG,CACD,CACD,GCrFAC,EAAY,GAAKA,EAAY,MAAQA,EAAY,KAAOC,EAAiB,CAAE,KAAM,GAAI,CAAC","names":["doc","addListener","target","type","listener","options","languageMap","selectionChange","doc","addListener","getLineStart","text","position","voidlessLangs","getLineBefore","text","position","getLineStart","userAgent","doc","isMac","isChrome","isWebKit","toString","isBracketPair","openBracket","testBracketPair","start","end","value","isBracketPair","clikeComment","bracketIndenting","comments","clikeComment","indentPattern","openBracket","start","value","getLineBefore","testBracketPair","languageMap","bracketIndenting"],"sources":["../esm/npm/prism-code-editor@5.2.0/node_modules/prism-code-editor/src/core.ts","../esm/npm/prism-code-editor@5.2.0/node_modules/prism-code-editor/src/utils/local.ts","../esm/npm/prism-code-editor@5.2.0/node_modules/prism-code-editor/src/utils/index.ts","../esm/npm/prism-code-editor@5.2.0/node_modules/prism-code-editor/src/prism/utils/language.js","../esm/npm/prism-code-editor@5.2.0/node_modules/prism-code-editor/src/languages/shared/index.ts","../esm/npm/prism-code-editor@5.2.0/node_modules/prism-code-editor/src/languages/bash.ts"],"sourcesContent":["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\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\"\r\nimport { addListener } from \"../core.js\"\r\nimport { isChrome } from \"./index.js\"\r\nimport { PrismCodeBlock } from \"../client/code-block.js\"\r\n\r\nconst scrollToEl = (editor: PrismEditor, el: HTMLElement, paddingTop = 0) =\u003e {\r\n\tconst style = editor.container.style\r\n\r\n\tstyle.setProperty(\"--_sp\", \"var(--pce-scroll-padding, 2ch)\")\r\n\tstyle.scrollPaddingBlock = `calc(var(--_sp) + ${paddingTop}px) calc(var(--_sp) + ${\r\n\t\tisChrome \u0026\u0026 !el.offsetWidth ? el.offsetHeight : 0\r\n\t}px)`\r\n\r\n\tel.scrollIntoView({ block: \"nearest\" })\r\n\tstyle.scrollPaddingBlock = \"\"\r\n\tstyle.removeProperty(\"--_sp\")\r\n}\r\n\r\nconst getLineStart = (text: string, position: number) =\u003e\r\n\tposition ? text.lastIndexOf(\"\\n\", position - 1) + 1 : 0\r\n\r\nconst getLineEnd = (text: string, position: number) =\u003e\r\n\t(position = text.indexOf(\"\\n\", position)) + 1 ? position : text.length\r\n\r\nconst addListener2 = \u003cT extends keyof HTMLElementEventMap\u003e(\r\n\telement: HTMLElement,\r\n\ttype: T,\r\n\tlistener: (this: HTMLElement, ev: HTMLElementEventMap[T]) =\u003e any,\r\n\toptions?: boolean | AddEventListenerOptions,\r\n) =\u003e {\r\n\taddListener(element, type, listener, options)\r\n\treturn () =\u003e element.removeEventListener(type, listener, options)\r\n}\r\n\r\nconst addTextareaListener = \u003cT extends keyof HTMLElementEventMap\u003e(\r\n\teditor: PrismEditor,\r\n\ttype: T,\r\n\tlistener: (this: HTMLElement, ev: HTMLElementEventMap[T]) =\u003e any,\r\n\toptions?: boolean | AddEventListenerOptions,\r\n) =\u003e addListener2(editor.textarea, type, listener, options)\r\n\r\nconst getStyleValue = (el: HTMLElement, prop: keyof CSSStyleDeclaration) =\u003e\r\n\tparseFloat(\u003cstring\u003egetComputedStyle(el)[prop])\r\n\r\nconst getPosition = (editor: PrismEditor | PrismCodeBlock, el: HTMLElement) =\u003e {\r\n\tconst rect1 = el.getBoundingClientRect()\r\n\tconst rect2 = editor.lines[0].getBoundingClientRect()\r\n\r\n\treturn {\r\n\t\ttop: rect1.y - rect2.y,\r\n\t\tbottom: rect2.bottom - rect1.bottom,\r\n\t\tleft: rect1.x - rect2.x,\r\n\t\tright: rect2.right - rect1.right,\r\n\t\theight: rect1.height,\r\n\t}\r\n}\r\n\r\nconst updateNode = (node: Text, text: string) =\u003e {\r\n\tif (node.data != text) node.data = text\r\n}\r\n\r\nconst voidlessLangs = new Set(\"xml,rss,atom,jsx,tsx,xquery,xeora,xeoracube,actionscript\".split(\",\"))\r\nconst voidTags = /^(?:area|base|w?br|col|embed|hr|img|input|link|meta|source|track)$/\r\n\r\nexport {\r\n\tscrollToEl,\r\n\tgetLineStart,\r\n\tgetLineEnd,\r\n\tgetStyleValue,\r\n\taddListener2,\r\n\taddTextareaListener,\r\n\tgetPosition,\r\n\tupdateNode,\r\n\tvoidTags,\r\n\tvoidlessLangs,\r\n}\r\n","import { InputSelection, PrismEditor } from \"../index.js\"\r\nimport { numLines, doc } from \"../core.js\"\r\nimport { addListener2, getLineEnd, getLineStart } from \"./local.js\"\r\nimport { PrismCodeBlock } from \"../client/code-block.js\"\r\nimport { escapeHtml } from \"../prism/core.js\"\r\n\r\n/**\r\n * If {@link insertText} has been called, this variable stores the editor's selection\r\n * before the call. This variable is set to 0 right before {@link insertText} returns.\r\n * This can therefore be used inside a `beforeinput` handler to determine if\r\n * {@link insertText} fired the event, and if true, get the selection before the call.\r\n *\r\n * Intended for internal use only.\r\n */\r\nlet prevSelection: InputSelection | 0\r\n\r\n/**\r\n * Escapes all regex syntax characters with a backslash and returns the escaped string.\r\n *\r\n * The returned string is not safe inside a character class.\r\n */\r\nconst regexEscape = (str: string) =\u003e str.replace(/[$+?|.^*()[\\]{}\\\\]/g, \"\\\\$\u0026\")\r\n\r\n/** Returns the string between the position and the previous \\n. */\r\nconst getLineBefore = (text: string, position: number) =\u003e\r\n\ttext.slice(getLineStart(text, position), position)\r\n\r\n/**\r\n * Gets all lines that are at least partially between `start` and `end`.\r\n * @param text Text to search in.\r\n * @param start Start of the selection.\r\n * @param end End of the selection. Defaults to `start`.\r\n * @returns A tuple containing an array of lines, the starting position of the first line,\r\n * and the ending position of the last line.\r\n */\r\nconst getLines = (text: string, start: number, end = start) =\u003e\r\n\t[\r\n\t\ttext.slice((start = getLineStart(text, start)), (end = getLineEnd(text, end))).split(\"\\n\"),\r\n\t\tstart,\r\n\t\tend,\r\n\t] as const\r\n\r\n/**\r\n * Searches a full line for a token that matches a selector and contains `position`\r\n * within the specified margins. Tokens are searched in reverse document order which means\r\n * children are searched before their parents.\r\n * @param editor Editor you want to search in.\r\n * @param selector CSS selector for the tokens you want to search for.\r\n * @param marginLeft How far to the left of the token the position can be. Defaults to 0.\r\n * @param marginRight How far to the right of the token the position can be. Defaults to `marginLeft`.\r\n * @param position Position to search in. Defaults to `selectionStart`.\r\n * @returns A span element if one's found or undefined if not.\r\n * @example\r\n * This will return a string token if the cursor\r\n * is at least 1 character inside a string token\r\n * ```javascript\r\n * getClosestToken(editor, '.string', -1)\r\n * ```\r\n */\r\nconst getClosestToken = (\r\n\teditor: PrismEditor,\r\n\tselector: string,\r\n\tmarginLeft = 0,\r\n\tmarginRight = marginLeft,\r\n\tposition = editor.getSelection()[0],\r\n) =\u003e {\r\n\tconst value = editor.value\r\n\tconst line = editor.lines[numLines(value, 0, position)]\r\n\t// We unfortunitely have to include elements, else we can't get empty tokens\r\n\tconst walker = doc!.createTreeWalker(line, 5)\r\n\r\n\tlet node = walker.lastChild()\r\n\tlet offset = getLineEnd(value, position) + 1 - position - (\u003cText\u003enode).length\r\n\r\n\twhile (-offset \u003c= marginRight \u0026\u0026 (node = walker.previousNode())) {\r\n\t\tif (node.lastChild) continue\r\n\t\toffset -= (\u003cText\u003enode).length || 0\r\n\r\n\t\tif (offset \u003c= marginLeft) {\r\n\t\t\tfor (; node != line; node = node.parentNode!) {\r\n\t\t\t\tif ((\u003cElement\u003enode).matches?.(selector)) return \u003cHTMLSpanElement\u003enode\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * Gets the current language at a position.\r\n * Useful if you want to run different logic based on the language.\r\n * @param editor Editor to search in.\r\n * @param position Position to search in. Defaults to `selectionStart`.\r\n */\r\nconst getLanguage = (editor: PrismEditor, position?: number) =\u003e\r\n\tgetClosestToken(editor, \"[class*=language-]\", 0, 0, position)?.className.match(\r\n\t\t/language-(\\S*)/,\r\n\t)![1] || editor.options.language\r\n\r\n/**\r\n * Inserts text into the editor (unless it's read-only) while keeping undo/redo history.\r\n * Focuses the `textarea` if it isn't already.\r\n * @param editor Target editor.\r\n * @param text Text to insert.\r\n * @param start Position to start the insertion. Defaults to `selectionStart`.\r\n * @param end Position to end the insertion. Defaults to `start` if specified, else `selectionEnd`.\r\n * @param newCursorStart New starting position for the cursor. Defaults to the end of the inserted text.\r\n * @param newCursorEnd New ending position for the cursor. Defaults to `newCursorStart`.\r\n */\r\nconst insertText = (\r\n\teditor: PrismEditor,\r\n\ttext: string,\r\n\tstart?: number | null,\r\n\tend?: number | null,\r\n\tnewCursorStart?: number | null,\r\n\tnewCursorEnd?: number | null,\r\n) =\u003e {\r\n\tif (editor.options.readOnly) return\r\n\tprevSelection = editor.getSelection()\r\n\tend ??= start\r\n\r\n\tlet textarea = editor.textarea\r\n\tlet value = editor.value\r\n\t// Bug inserting new lines at the end if the editor ends with an empty line\r\n\tlet avoidBug =\r\n\t\tisChrome \u0026\u0026 !value[end ?? prevSelection[1]] \u0026\u0026 /\\n$/.test(text) \u0026\u0026 /^$|\\n$/.test(value)\r\n\tlet removeListener: () =\u003e any\r\n\r\n\teditor.focused || textarea.focus()\r\n\tif (start != null) textarea.setSelectionRange(start, end!)\r\n\r\n\tif (newCursorStart != null) {\r\n\t\tremoveListener = editor.on(\"update\", () =\u003e {\r\n\t\t\ttextarea.setSelectionRange(\r\n\t\t\t\tnewCursorStart,\r\n\t\t\t\tnewCursorEnd ?? newCursorStart,\r\n\t\t\t\t(\u003cInputSelection\u003eprevSelection)[2],\r\n\t\t\t)\r\n\t\t\tremoveListener()\r\n\t\t})\r\n\t}\r\n\r\n\t// Only Safari dispatches a beforeinput event\r\n\tisWebKit || textarea.dispatchEvent(new InputEvent(\"beforeinput\", { data: text }))\r\n\r\n\t// Inserting escaped HTML in Chrome and Safari instead for much better performance\r\n\tif (isChrome || isWebKit) {\r\n\t\tif (avoidBug) {\r\n\t\t\t// This means the last new line won't be inserted if there's\r\n\t\t\t// no selection, but that's less annoying than the bug.\r\n\t\t\ttextarea.selectionEnd--\r\n\t\t\ttext = text.slice(0, -1)\r\n\t\t}\r\n\t\t// New line at the end is always ignored in Safari\r\n\t\tif (isWebKit) text += \"\\n\"\r\n\t\tdoc!.execCommand(text ? \"insertHTML\" : \"delete\", false, escapeHtml(text, /\u003c/g, \"\u0026lt;\"))\r\n\t\tif (avoidBug) textarea.selectionStart++\r\n\t} else doc!.execCommand(text ? \"insertText\" : \"delete\", false, text)\r\n\r\n\tprevSelection = 0\r\n}\r\n\r\n/**\r\n * Sets the selection for the `textarea` and synchronously runs the selectionChange listeners.\r\n * If you don't want to synchronously run the listeners, use `textarea.setSelectionRange` instead.\r\n * @param editor Editor you want to change the selection of.\r\n * @param start New selectionStart.\r\n * @param end New selectionEnd. Defaults to `start`.\r\n * @param direction New direction.\r\n */\r\nconst setSelection = (\r\n\teditor: PrismEditor,\r\n\tstart: number,\r\n\tend = start,\r\n\tdirection?: \"backward\" | \"forward\" | \"none\",\r\n) =\u003e {\r\n\tlet textarea = editor.textarea\r\n\t// Webkit 18.3 and earlier focuses the textarea when changing the selection\r\n\tlet removeHandler = addListener2(textarea, \"focus\", e =\u003e {\r\n\t\tlet target = e.relatedTarget as HTMLElement\r\n\t\ttarget ? target.focus() : textarea.blur()\r\n\t})\r\n\r\n\ttextarea.setSelectionRange(start, end, direction)\r\n\tremoveHandler()\r\n\ttextarea.dispatchEvent(new Event(\"selectionchange\"))\r\n}\r\n\r\nconst userAgent = doc ? navigator.userAgent : \"\"\r\n/** Whether the user is on an Apple-based system. */\r\nconst isMac = doc ? /Mac|iPhone|iP[ao]d/.test(navigator.platform) : false\r\n/** Whether the browser is Chromium based. */\r\nconst isChrome = /Chrome\\//.test(userAgent)\r\n/** Whether the browser uses the WebKit browser engine. */\r\nconst isWebKit = !isChrome \u0026\u0026 /AppleWebKit\\//.test(userAgent)\r\n\r\n/**\r\n * Returns a 4 bit integer where each bit represents whether\r\n * each modifier is pressed in the order Shift, Meta, Ctrl, Alt.\r\n *\r\n * ```javascript\r\n * e.shiftKey \u0026\u0026 !e.metaKey \u0026\u0026 e.ctrlKey \u0026\u0026 e.altKey\r\n * // is equivalent to\r\n * getModifierCode(e) == 0b1011\r\n * ```\r\n */\r\nconst getModifierCode = (\r\n\te: KeyboardEvent, // @ts-expect-error\r\n): number =\u003e e.altKey + e.ctrlKey * 2 + e.metaKey * 4 + e.shiftKey * 8\r\n\r\n/**\r\n * Adds an overlay by appending the element to the editor's overlays.\r\n * Equivalent to calling `editor.lines[0].append(overlay)`.\r\n * @param editor Editor or code block you want to add an overlay to.\r\n * @param overlay The overlay you want to add.\r\n */\r\nconst addOverlay = (editor: PrismEditor | PrismCodeBlock, overlay: HTMLElement) =\u003e\r\n\teditor.lines[0].append(overlay)\r\n\r\n/**\r\n * Gets the position of the cursor in the document. It returns a tuple with three numbers:\r\n *\r\n * 1. The line number of the cursor\r\n * 2. The 1-based column of the cursor\r\n * 3. Number of characters selected\r\n *\r\n * @example\r\n * const [line, col, selected] = getDocumentPosition(editor)\r\n */\r\nconst getDocumentPosition = (editor: PrismEditor): [number, number, number] =\u003e {\r\n\tlet [start, end, dir] = editor.getSelection()\r\n\tlet pos = dir \u003c \"f\" ? start : end\r\n\tlet value = editor.value\r\n\tlet col = 0\r\n\tlet chars = 0\r\n\tlet tabSize = editor.options.tabSize || 2\r\n\r\n\tfor (const char of getLineBefore(value, pos)) {\r\n\t\tcol += char == \"\\t\" ? tabSize - (col % tabSize) : 1\r\n\t}\r\n\r\n\tfor (const _ of value.slice(start, end)) chars++\r\n\r\n\treturn [editor.activeLine, col + 1, chars]\r\n}\r\n\r\nexport {\r\n\tregexEscape,\r\n\tgetLineBefore,\r\n\tgetLines,\r\n\tgetClosestToken,\r\n\tgetLanguage,\r\n\tinsertText,\r\n\tgetModifierCode,\r\n\tsetSelection,\r\n\taddOverlay,\r\n\tgetDocumentPosition,\r\n\tisMac,\r\n\tisChrome,\r\n\tisWebKit,\r\n\tprevSelection,\r\n}\r\n","import { languages, rest, tokenize } from \"../core.js\";\r\n\r\nvar _clone = (o, visited) =\u003e {\r\n\tif (visited.has(o)) return visited.get(o);\r\n\tvar copy = o, t = toString.call(o).slice(8, -1);\r\n\r\n\tif (t == \"Object\") {\r\n\t\tvisited.set(o, copy = {});\r\n\t\tfor (var key in o) {\r\n\t\t\tcopy[key] = _clone(o[key], visited);\r\n\t\t}\r\n\t\tif (o[rest]) copy[rest] = _clone(o[rest], visited);\r\n\t\tif (o[tokenize]) copy[tokenize] = o[tokenize];\r\n\t}\r\n\telse if (t == \"Array\") {\r\n\t\tvisited.set(o, copy = []);\r\n\t\tfor (var i = 0, l = o.length; i \u003c l; i++) {\r\n\t\t\tcopy[i] = _clone(o[i], visited);\r\n\t\t}\r\n\t}\r\n\r\n\treturn copy;\r\n}\r\n\r\nvar clone = o =\u003e _clone(o, new Map);\r\n\r\nvar extend = (id, redef) =\u003e Object.assign(clone(languages[id]), redef);\r\n\r\nvar insertBefore = (grammar, before, insert) =\u003e {\r\n\tvar temp = {};\r\n\r\n\tfor (var token in grammar) {\r\n\t\ttemp[token] = grammar[token];\r\n\t\tdelete grammar[token];\r\n\t}\r\n\r\n\tfor (var token in temp) {\r\n\t\tif (token == before) Object.assign(grammar, insert);\r\n\r\n\t\t// Do not insert token which also occur in insert. See #1525\r\n\t\tif (!insert.hasOwnProperty(token)) {\r\n\t\t\tgrammar[token] = temp[token];\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvar toString = {}.toString;\r\n\r\nexport { clone, insertBefore, extend }\r\n","import { CommentTokens, InputSelection, Language, PrismEditor, languageMap } from \"../../index.js\"\r\nimport { braces } from \"../../prism/utils/jsx-shared.js\"\r\nimport { re } from \"../../prism/utils/shared.js\"\r\nimport { getClosestToken, getLineBefore } from \"../../utils/index.js\"\r\nimport { voidTags } from \"../../utils/local.js\"\r\n\r\nconst clikeIndent = /[([{][^)\\]}]*$|^[^.]*\\b(?:case .+?|default):\\s*$/\r\nconst isBracketPair = /\\[]|\\(\\)|{}/\r\nconst xmlOpeningTag =\r\n\t/\u003c(?![\\d?!#@])([^\\s/=\u003e$\u003c%]+)(?:\\s(?:\\s*[^\\s/\"'=\u003e]+(?:\\s*=\\s*(?!\\s)(?:\"[^\"]*\"|'[^']*'|[^\\s\"'=\u003e]+(?=[\\s\u003e]))?|(?=[\\s/\u003e])))+)?\\s*\u003e[ \\t]*$/\r\nconst xmlClosingTag = /^\u003c\\/(?!\\d)[^\\s/=\u003e$\u003c%]+\\s*\u003e/\r\nconst openBracket = /[([{][^)\\]}]*$/\r\nconst astroOpeningTag = /* @__PURE__ */ re(\r\n\t/\u003c(?:(?![\\d!])([^\\s%=\u003c\u003e/]+)(?:\\s(?:\\s*(?:[^\\s{=\u003c\u003e/]+(?:\\s*=\\s*(?!\\s)(?:\"[^\"]*\"|'[^']*'|[^\\s{=\u003c\u003e/\"']+(?=[\\s/\u003e])|\u003c0\u003e)?|(?=[\\s/\u003e]))|\u003c0\u003e))*)?\\s*)?\u003e[ \\t]*$/\r\n\t\t.source,\r\n\t[braces],\r\n)\r\n\r\nconst testBracketPair = ([start, end]: InputSelection, value: string) =\u003e {\r\n\treturn isBracketPair.test(value[start - 1] + value[end])\r\n}\r\n\r\nconst clikeComment: CommentTokens = {\r\n\tline: \"//\",\r\n\tblock: [\"/*\", \"*/\"],\r\n}\r\n\r\nconst isOpen = (match: RegExpMatchArray | null, voidTags?: RegExp) =\u003e\r\n\t!!match \u0026\u0026 !voidTags?.test(match[1])\r\n\r\nconst htmlAutoIndent = (tagPattern: RegExp, voidTags?: RegExp): Language[\"autoIndent\"] =\u003e [\r\n\t([start], value) =\u003e\r\n\t\tisOpen(value.slice(0, start).match(tagPattern), voidTags) ||\r\n\t\topenBracket.test(getLineBefore(value, start)),\r\n\t(selection, value) =\u003e\r\n\t\ttestBracketPair(selection, value) ||\r\n\t\t(isOpen(value.slice(0, selection[0]).match(tagPattern), voidTags) \u0026\u0026\r\n\t\t\txmlClosingTag.test(value.slice(selection[1]))),\r\n]\r\n\r\nconst markupComment: CommentTokens = {\r\n\tblock: [\"\u003c!--\", \"--\u003e\"],\r\n}\r\n\r\nconst markupLanguage = (\r\n\tcomment = markupComment,\r\n\ttagPattern = xmlOpeningTag,\r\n\tvoidTags?: RegExp,\r\n): Language =\u003e ({\r\n\tcomments: comment,\r\n\tautoIndent: htmlAutoIndent(tagPattern, voidTags),\r\n\tautoCloseTags: ([start, end], value, editor) =\u003e {\r\n\t\treturn autoCloseTags(editor, start, end, value, tagPattern, voidTags)\r\n\t},\r\n})\r\n\r\nconst autoCloseTags = (\r\n\teditor: PrismEditor,\r\n\tstart: number,\r\n\tend: number,\r\n\tvalue: string,\r\n\ttagPattern: RegExp,\r\n\tvoidTags?: RegExp,\r\n) =\u003e {\r\n\tif (start == end) {\r\n\t\tlet match: string | RegExpExecArray | null = tagPattern.exec(value.slice(0, start) + \"\u003e\")\r\n\t\tlet tagMatcher = editor.extensions.matchTags\r\n\t\tif (match \u0026\u0026 ((match = match[1] || \"\"), !voidTags?.test(match))) {\r\n\t\t\tif (tagMatcher) {\r\n\t\t\t\tlet { pairs, tags } = tagMatcher\r\n\t\t\t\tfor (let i = tags.length; i; ) {\r\n\t\t\t\t\tlet tag = tags[--i]\r\n\t\t\t\t\tif (tag[1] \u003e= start \u0026\u0026 tag[4] \u0026\u0026 tag[5] \u0026\u0026 tag[3] == match \u0026\u0026 pairs[i] == null) {\r\n\t\t\t\t\t\treturn\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn `\u003c/${match}\u003e`\r\n\t\t}\r\n\t}\r\n}\r\n\r\nconst bracketIndenting = (comments = clikeComment, indentPattern = openBracket): Language =\u003e ({\r\n\tcomments,\r\n\tautoIndent: [\r\n\t\t([start], value) =\u003e indentPattern.test(getLineBefore(value, start)),\r\n\t\ttestBracketPair,\r\n\t],\r\n})\r\n\r\nconst markupTemplateLang = (name: string, comments: CommentTokens): Language =\u003e\r\n\t(languageMap[name] = {\r\n\t\tcomments,\r\n\t\tautoIndent: htmlAutoIndent(xmlOpeningTag, voidTags),\r\n\t\tautoCloseTags: ([start, end], value, editor) =\u003e {\r\n\t\t\treturn getClosestToken(editor, \".\" + name, 0, 0, start)\r\n\t\t\t\t? \"\"\r\n\t\t\t\t: autoCloseTags(editor, start, end, value, xmlOpeningTag, voidTags)\r\n\t\t},\r\n\t})\r\n\r\nexport {\r\n\tclikeIndent,\r\n\tisBracketPair,\r\n\txmlOpeningTag,\r\n\txmlClosingTag,\r\n\topenBracket,\r\n\tautoCloseTags,\r\n\ttestBracketPair,\r\n\tclikeComment,\r\n\tbracketIndenting,\r\n\thtmlAutoIndent,\r\n\tvoidTags,\r\n\tmarkupTemplateLang,\r\n\tmarkupLanguage,\r\n\tmarkupComment,\r\n\tastroOpeningTag,\r\n}\r\n","import { languageMap } from \"..\"\r\nimport { bracketIndenting } from \"./shared\"\r\n\r\nlanguageMap.sh = languageMap.shell = languageMap.bash = bracketIndenting({ line: \"#\" })\r\n"],"version":3}
