(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(require("react"), require("react/jsx-runtime"), require("@codemirror/state"), require("@codemirror/theme-one-dark"), require("@codemirror/view")); else if(typeof define === 'function' && define.amd) define(["react", "react/jsx-runtime", , , ], factory); else if(typeof exports === 'object') exports["@uiw/codemirror"] = factory(require("react"), require("react/jsx-runtime"), require("@codemirror/state"), require("@codemirror/theme-one-dark"), require("@codemirror/view")); else root["@uiw/codemirror"] = factory(root["React"], root["ReactJSXRuntime"], root["CM"]["@codemirror/state"], root["CM"]["@codemirror/theme-one-dark"], root["CM"]["@codemirror/view"]); })(self, (__WEBPACK_EXTERNAL_MODULE__442__, __WEBPACK_EXTERNAL_MODULE__742__, __WEBPACK_EXTERNAL_MODULE__60__, __WEBPACK_EXTERNAL_MODULE__708__, __WEBPACK_EXTERNAL_MODULE__730__) => { return /******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ var __webpack_modules__ = ({ /***/ 368: /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { // EXPORTS __webpack_require__.d(__webpack_exports__, { o: () => (/* binding */ basicSetup), V: () => (/* binding */ minimalSetup) }); // EXTERNAL MODULE: external {"root":["CM","@codemirror/view"],"commonjs":"@codemirror/view","commonjs2":"@codemirror/view"} var view_ = __webpack_require__(730); // EXTERNAL MODULE: external {"root":["CM","@codemirror/state"],"commonjs":"@codemirror/state","commonjs2":"@codemirror/state"} var state_ = __webpack_require__(60); // EXTERNAL MODULE: ../node_modules/@codemirror/commands/dist/index.js var dist = __webpack_require__(720); ;// CONCATENATED MODULE: ../node_modules/crelt/index.js function crelt() { var elt = arguments[0] if (typeof elt == "string") elt = document.createElement(elt) var i = 1, next = arguments[1] if (next && typeof next == "object" && next.nodeType == null && !Array.isArray(next)) { for (var name in next) if (Object.prototype.hasOwnProperty.call(next, name)) { var value = next[name] if (typeof value == "string") elt.setAttribute(name, value) else if (value != null) elt[name] = value } i++ } for (; i < arguments.length; i++) add(elt, arguments[i]) return elt } function add(elt, child) { if (typeof child == "string") { elt.appendChild(document.createTextNode(child)) } else if (child == null) { } else if (child.nodeType != null) { elt.appendChild(child) } else if (Array.isArray(child)) { for (var i = 0; i < child.length; i++) add(elt, child[i]) } else { throw new RangeError("Unsupported child node: " + child) } } ;// CONCATENATED MODULE: ../node_modules/@codemirror/search/dist/index.js const basicNormalize = typeof String.prototype.normalize == "function" ? x => x.normalize("NFKD") : x => x; /** A search cursor provides an iterator over text matches in a document. */ class SearchCursor { /** Create a text cursor. The query is the search string, `from` to `to` provides the region to search. When `normalize` is given, it will be called, on both the query string and the content it is matched against, before comparing. You can, for example, create a case-insensitive search by passing `s => s.toLowerCase()`. Text is always normalized with [`.normalize("NFKD")`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize) (when supported). */ constructor(text, query, from = 0, to = text.length, normalize, test) { this.test = test; /** The current match (only holds a meaningful value after [`next`](https://codemirror.net/6/docs/ref/#search.SearchCursor.next) has been called and when `done` is false). */ this.value = { from: 0, to: 0 }; /** Whether the end of the iterated region has been reached. */ this.done = false; this.matches = []; this.buffer = ""; this.bufferPos = 0; this.iter = text.iterRange(from, to); this.bufferStart = from; this.normalize = normalize ? x => normalize(basicNormalize(x)) : basicNormalize; this.query = this.normalize(query); } peek() { if (this.bufferPos == this.buffer.length) { this.bufferStart += this.buffer.length; this.iter.next(); if (this.iter.done) return -1; this.bufferPos = 0; this.buffer = this.iter.value; } return (0,state_.codePointAt)(this.buffer, this.bufferPos); } /** Look for the next match. Updates the iterator's [`value`](https://codemirror.net/6/docs/ref/#search.SearchCursor.value) and [`done`](https://codemirror.net/6/docs/ref/#search.SearchCursor.done) properties. Should be called at least once before using the cursor. */ next() { while (this.matches.length) this.matches.pop(); return this.nextOverlapping(); } /** The `next` method will ignore matches that partially overlap a previous match. This method behaves like `next`, but includes such matches. */ nextOverlapping() { for (;;) { let next = this.peek(); if (next < 0) { this.done = true; return this; } let str = (0,state_.fromCodePoint)(next), start = this.bufferStart + this.bufferPos; this.bufferPos += (0,state_.codePointSize)(next); let norm = this.normalize(str); for (let i = 0, pos = start;; i++) { let code = norm.charCodeAt(i); let match = this.match(code, pos, this.bufferPos + this.bufferStart); if (i == norm.length - 1) { if (match) { this.value = match; return this; } break; } if (pos == start && i < str.length && str.charCodeAt(i) == code) pos++; } } } match(code, pos, end) { let match = null; for (let i = 0; i < this.matches.length; i += 2) { let index = this.matches[i], keep = false; if (this.query.charCodeAt(index) == code) { if (index == this.query.length - 1) { match = { from: this.matches[i + 1], to: end }; } else { this.matches[i]++; keep = true; } } if (!keep) { this.matches.splice(i, 2); i -= 2; } } if (this.query.charCodeAt(0) == code) { if (this.query.length == 1) match = { from: pos, to: end }; else this.matches.push(1, pos); } if (match && this.test && !this.test(match.from, match.to, this.buffer, this.bufferStart)) match = null; return match; } } if (typeof Symbol != "undefined") SearchCursor.prototype[Symbol.iterator] = function () { return this; }; const empty = { from: -1, to: -1, match: /*@__PURE__*//.*/.exec("") }; const baseFlags = "gm" + (/x/.unicode == null ? "" : "u"); /** This class is similar to [`SearchCursor`](https://codemirror.net/6/docs/ref/#search.SearchCursor) but searches for a regular expression pattern instead of a plain string. */ class RegExpCursor { /** Create a cursor that will search the given range in the given document. `query` should be the raw pattern (as you'd pass it to `new RegExp`). */ constructor(text, query, options, from = 0, to = text.length) { this.text = text; this.to = to; this.curLine = ""; /** Set to `true` when the cursor has reached the end of the search range. */ this.done = false; /** Will contain an object with the extent of the match and the match object when [`next`](https://codemirror.net/6/docs/ref/#search.RegExpCursor.next) sucessfully finds a match. */ this.value = empty; if (/\\[sWDnr]|\n|\r|\[\^/.test(query)) return new MultilineRegExpCursor(text, query, options, from, to); this.re = new RegExp(query, baseFlags + ((options === null || options === void 0 ? void 0 : options.ignoreCase) ? "i" : "")); this.test = options === null || options === void 0 ? void 0 : options.test; this.iter = text.iter(); let startLine = text.lineAt(from); this.curLineStart = startLine.from; this.matchPos = toCharEnd(text, from); this.getLine(this.curLineStart); } getLine(skip) { this.iter.next(skip); if (this.iter.lineBreak) { this.curLine = ""; } else { this.curLine = this.iter.value; if (this.curLineStart + this.curLine.length > this.to) this.curLine = this.curLine.slice(0, this.to - this.curLineStart); this.iter.next(); } } nextLine() { this.curLineStart = this.curLineStart + this.curLine.length + 1; if (this.curLineStart > this.to) this.curLine = ""; else this.getLine(0); } /** Move to the next match, if there is one. */ next() { for (let off = this.matchPos - this.curLineStart;;) { this.re.lastIndex = off; let match = this.matchPos <= this.to && this.re.exec(this.curLine); if (match) { let from = this.curLineStart + match.index, to = from + match[0].length; this.matchPos = toCharEnd(this.text, to + (from == to ? 1 : 0)); if (from == this.curLineStart + this.curLine.length) this.nextLine(); if ((from < to || from > this.value.to) && (!this.test || this.test(from, to, match))) { this.value = { from, to, match }; return this; } off = this.matchPos - this.curLineStart; } else if (this.curLineStart + this.curLine.length < this.to) { this.nextLine(); off = 0; } else { this.done = true; return this; } } } } const flattened = /*@__PURE__*/new WeakMap(); // Reusable (partially) flattened document strings class FlattenedDoc { constructor(from, text) { this.from = from; this.text = text; } get to() { return this.from + this.text.length; } static get(doc, from, to) { let cached = flattened.get(doc); if (!cached || cached.from >= to || cached.to <= from) { let flat = new FlattenedDoc(from, doc.sliceString(from, to)); flattened.set(doc, flat); return flat; } if (cached.from == from && cached.to == to) return cached; let { text, from: cachedFrom } = cached; if (cachedFrom > from) { text = doc.sliceString(from, cachedFrom) + text; cachedFrom = from; } if (cached.to < to) text += doc.sliceString(cached.to, to); flattened.set(doc, new FlattenedDoc(cachedFrom, text)); return new FlattenedDoc(from, text.slice(from - cachedFrom, to - cachedFrom)); } } class MultilineRegExpCursor { constructor(text, query, options, from, to) { this.text = text; this.to = to; this.done = false; this.value = empty; this.matchPos = toCharEnd(text, from); this.re = new RegExp(query, baseFlags + ((options === null || options === void 0 ? void 0 : options.ignoreCase) ? "i" : "")); this.test = options === null || options === void 0 ? void 0 : options.test; this.flat = FlattenedDoc.get(text, from, this.chunkEnd(from + 5000 /* Chunk.Base */)); } chunkEnd(pos) { return pos >= this.to ? this.to : this.text.lineAt(pos).to; } next() { for (;;) { let off = this.re.lastIndex = this.matchPos - this.flat.from; let match = this.re.exec(this.flat.text); // Skip empty matches directly after the last match if (match && !match[0] && match.index == off) { this.re.lastIndex = off + 1; match = this.re.exec(this.flat.text); } if (match) { let from = this.flat.from + match.index, to = from + match[0].length; // If a match goes almost to the end of a noncomplete chunk, try // again, since it'll likely be able to match more if ((this.flat.to >= this.to || match.index + match[0].length <= this.flat.text.length - 10) && (!this.test || this.test(from, to, match))) { this.value = { from, to, match }; this.matchPos = toCharEnd(this.text, to + (from == to ? 1 : 0)); return this; } } if (this.flat.to == this.to) { this.done = true; return this; } // Grow the flattened doc this.flat = FlattenedDoc.get(this.text, this.flat.from, this.chunkEnd(this.flat.from + this.flat.text.length * 2)); } } } if (typeof Symbol != "undefined") { RegExpCursor.prototype[Symbol.iterator] = MultilineRegExpCursor.prototype[Symbol.iterator] = function () { return this; }; } function validRegExp(source) { try { new RegExp(source, baseFlags); return true; } catch (_a) { return false; } } function toCharEnd(text, pos) { if (pos >= text.length) return pos; let line = text.lineAt(pos), next; while (pos < line.to && (next = line.text.charCodeAt(pos - line.from)) >= 0xDC00 && next < 0xE000) pos++; return pos; } function createLineDialog(view) { let line = String(view.state.doc.lineAt(view.state.selection.main.head).number); let input = crelt("input", { class: "cm-textfield", name: "line", value: line }); let dom = crelt("form", { class: "cm-gotoLine", onkeydown: (event) => { if (event.keyCode == 27) { // Escape event.preventDefault(); view.dispatch({ effects: dialogEffect.of(false) }); view.focus(); } else if (event.keyCode == 13) { // Enter event.preventDefault(); go(); } }, onsubmit: (event) => { event.preventDefault(); go(); } }, crelt("label", view.state.phrase("Go to line"), ": ", input), " ", crelt("button", { class: "cm-button", type: "submit" }, view.state.phrase("go"))); function go() { let match = /^([+-])?(\d+)?(:\d+)?(%)?$/.exec(input.value); if (!match) return; let { state } = view, startLine = state.doc.lineAt(state.selection.main.head); let [, sign, ln, cl, percent] = match; let col = cl ? +cl.slice(1) : 0; let line = ln ? +ln : startLine.number; if (ln && percent) { let pc = line / 100; if (sign) pc = pc * (sign == "-" ? -1 : 1) + (startLine.number / state.doc.lines); line = Math.round(state.doc.lines * pc); } else if (ln && sign) { line = line * (sign == "-" ? -1 : 1) + startLine.number; } let docLine = state.doc.line(Math.max(1, Math.min(state.doc.lines, line))); let selection = state_.EditorSelection.cursor(docLine.from + Math.max(0, Math.min(col, docLine.length))); view.dispatch({ effects: [dialogEffect.of(false), view_.EditorView.scrollIntoView(selection.from, { y: 'center' })], selection, }); view.focus(); } return { dom }; } const dialogEffect = /*@__PURE__*/state_.StateEffect.define(); const dialogField = /*@__PURE__*/state_.StateField.define({ create() { return true; }, update(value, tr) { for (let e of tr.effects) if (e.is(dialogEffect)) value = e.value; return value; }, provide: f => view_.showPanel.from(f, val => val ? createLineDialog : null) }); /** Command that shows a dialog asking the user for a line number, and when a valid position is provided, moves the cursor to that line. Supports line numbers, relative line offsets prefixed with `+` or `-`, document percentages suffixed with `%`, and an optional column position by adding `:` and a second number after the line number. */ const gotoLine = view => { let panel = (0,view_.getPanel)(view, createLineDialog); if (!panel) { let effects = [dialogEffect.of(true)]; if (view.state.field(dialogField, false) == null) effects.push(state_.StateEffect.appendConfig.of([dialogField, baseTheme$1])); view.dispatch({ effects }); panel = (0,view_.getPanel)(view, createLineDialog); } if (panel) panel.dom.querySelector("input").select(); return true; }; const baseTheme$1 = /*@__PURE__*/view_.EditorView.baseTheme({ ".cm-panel.cm-gotoLine": { padding: "2px 6px 4px", "& label": { fontSize: "80%" } } }); const defaultHighlightOptions = { highlightWordAroundCursor: false, minSelectionLength: 1, maxMatches: 100, wholeWords: false }; const highlightConfig = /*@__PURE__*/state_.Facet.define({ combine(options) { return (0,state_.combineConfig)(options, defaultHighlightOptions, { highlightWordAroundCursor: (a, b) => a || b, minSelectionLength: Math.min, maxMatches: Math.min }); } }); /** This extension highlights text that matches the selection. It uses the `"cm-selectionMatch"` class for the highlighting. When `highlightWordAroundCursor` is enabled, the word at the cursor itself will be highlighted with `"cm-selectionMatch-main"`. */ function highlightSelectionMatches(options) { let ext = [defaultTheme, matchHighlighter]; if (options) ext.push(highlightConfig.of(options)); return ext; } const matchDeco = /*@__PURE__*/view_.Decoration.mark({ class: "cm-selectionMatch" }); const mainMatchDeco = /*@__PURE__*/view_.Decoration.mark({ class: "cm-selectionMatch cm-selectionMatch-main" }); // Whether the characters directly outside the given positions are non-word characters function insideWordBoundaries(check, state, from, to) { return (from == 0 || check(state.sliceDoc(from - 1, from)) != state_.CharCategory.Word) && (to == state.doc.length || check(state.sliceDoc(to, to + 1)) != state_.CharCategory.Word); } // Whether the characters directly at the given positions are word characters function insideWord(check, state, from, to) { return check(state.sliceDoc(from, from + 1)) == state_.CharCategory.Word && check(state.sliceDoc(to - 1, to)) == state_.CharCategory.Word; } const matchHighlighter = /*@__PURE__*/view_.ViewPlugin.fromClass(class { constructor(view) { this.decorations = this.getDeco(view); } update(update) { if (update.selectionSet || update.docChanged || update.viewportChanged) this.decorations = this.getDeco(update.view); } getDeco(view) { let conf = view.state.facet(highlightConfig); let { state } = view, sel = state.selection; if (sel.ranges.length > 1) return view_.Decoration.none; let range = sel.main, query, check = null; if (range.empty) { if (!conf.highlightWordAroundCursor) return view_.Decoration.none; let word = state.wordAt(range.head); if (!word) return view_.Decoration.none; check = state.charCategorizer(range.head); query = state.sliceDoc(word.from, word.to); } else { let len = range.to - range.from; if (len < conf.minSelectionLength || len > 200) return view_.Decoration.none; if (conf.wholeWords) { query = state.sliceDoc(range.from, range.to); // TODO: allow and include leading/trailing space? check = state.charCategorizer(range.head); if (!(insideWordBoundaries(check, state, range.from, range.to) && insideWord(check, state, range.from, range.to))) return view_.Decoration.none; } else { query = state.sliceDoc(range.from, range.to); if (!query) return view_.Decoration.none; } } let deco = []; for (let part of view.visibleRanges) { let cursor = new SearchCursor(state.doc, query, part.from, part.to); while (!cursor.next().done) { let { from, to } = cursor.value; if (!check || insideWordBoundaries(check, state, from, to)) { if (range.empty && from <= range.from && to >= range.to) deco.push(mainMatchDeco.range(from, to)); else if (from >= range.to || to <= range.from) deco.push(matchDeco.range(from, to)); if (deco.length > conf.maxMatches) return view_.Decoration.none; } } } return view_.Decoration.set(deco); } }, { decorations: v => v.decorations }); const defaultTheme = /*@__PURE__*/view_.EditorView.baseTheme({ ".cm-selectionMatch": { backgroundColor: "#99ff7780" }, ".cm-searchMatch .cm-selectionMatch": { backgroundColor: "transparent" } }); // Select the words around the cursors. const selectWord = ({ state, dispatch }) => { let { selection } = state; let newSel = state_.EditorSelection.create(selection.ranges.map(range => state.wordAt(range.head) || state_.EditorSelection.cursor(range.head)), selection.mainIndex); if (newSel.eq(selection)) return false; dispatch(state.update({ selection: newSel })); return true; }; // Find next occurrence of query relative to last cursor. Wrap around // the document if there are no more matches. function findNextOccurrence(state, query) { let { main, ranges } = state.selection; let word = state.wordAt(main.head), fullWord = word && word.from == main.from && word.to == main.to; for (let cycled = false, cursor = new SearchCursor(state.doc, query, ranges[ranges.length - 1].to);;) { cursor.next(); if (cursor.done) { if (cycled) return null; cursor = new SearchCursor(state.doc, query, 0, Math.max(0, ranges[ranges.length - 1].from - 1)); cycled = true; } else { if (cycled && ranges.some(r => r.from == cursor.value.from)) continue; if (fullWord) { let word = state.wordAt(cursor.value.from); if (!word || word.from != cursor.value.from || word.to != cursor.value.to) continue; } return cursor.value; } } } /** Select next occurrence of the current selection. Expand selection to the surrounding word when the selection is empty. */ const selectNextOccurrence = ({ state, dispatch }) => { let { ranges } = state.selection; if (ranges.some(sel => sel.from === sel.to)) return selectWord({ state, dispatch }); let searchedText = state.sliceDoc(ranges[0].from, ranges[0].to); if (state.selection.ranges.some(r => state.sliceDoc(r.from, r.to) != searchedText)) return false; let range = findNextOccurrence(state, searchedText); if (!range) return false; dispatch(state.update({ selection: state.selection.addRange(state_.EditorSelection.range(range.from, range.to), false), effects: view_.EditorView.scrollIntoView(range.to) })); return true; }; const searchConfigFacet = /*@__PURE__*/state_.Facet.define({ combine(configs) { return (0,state_.combineConfig)(configs, { top: false, caseSensitive: false, literal: false, regexp: false, wholeWord: false, createPanel: view => new SearchPanel(view), scrollToMatch: range => view_.EditorView.scrollIntoView(range) }); } }); /** Add search state to the editor configuration, and optionally configure the search extension. ([`openSearchPanel`](https://codemirror.net/6/docs/ref/#search.openSearchPanel) will automatically enable this if it isn't already on). */ function search(config) { return config ? [searchConfigFacet.of(config), searchExtensions] : searchExtensions; } /** A search query. Part of the editor's search state. */ class SearchQuery { /** Create a query object. */ constructor(config) { this.search = config.search; this.caseSensitive = !!config.caseSensitive; this.literal = !!config.literal; this.regexp = !!config.regexp; this.replace = config.replace || ""; this.valid = !!this.search && (!this.regexp || validRegExp(this.search)); this.unquoted = this.unquote(this.search); this.wholeWord = !!config.wholeWord; } /** @internal */ unquote(text) { return this.literal ? text : text.replace(/\\([nrt\\])/g, (_, ch) => ch == "n" ? "\n" : ch == "r" ? "\r" : ch == "t" ? "\t" : "\\"); } /** Compare this query to another query. */ eq(other) { return this.search == other.search && this.replace == other.replace && this.caseSensitive == other.caseSensitive && this.regexp == other.regexp && this.wholeWord == other.wholeWord; } /** @internal */ create() { return this.regexp ? new RegExpQuery(this) : new StringQuery(this); } /** Get a search cursor for this query, searching through the given range in the given state. */ getCursor(state, from = 0, to) { let st = state.doc ? state : state_.EditorState.create({ doc: state }); if (to == null) to = st.doc.length; return this.regexp ? regexpCursor(this, st, from, to) : stringCursor(this, st, from, to); } } class QueryType { constructor(spec) { this.spec = spec; } } function stringCursor(spec, state, from, to) { return new SearchCursor(state.doc, spec.unquoted, from, to, spec.caseSensitive ? undefined : x => x.toLowerCase(), spec.wholeWord ? stringWordTest(state.doc, state.charCategorizer(state.selection.main.head)) : undefined); } function stringWordTest(doc, categorizer) { return (from, to, buf, bufPos) => { if (bufPos > from || bufPos + buf.length < to) { bufPos = Math.max(0, from - 2); buf = doc.sliceString(bufPos, Math.min(doc.length, to + 2)); } return (categorizer(charBefore(buf, from - bufPos)) != state_.CharCategory.Word || categorizer(charAfter(buf, from - bufPos)) != state_.CharCategory.Word) && (categorizer(charAfter(buf, to - bufPos)) != state_.CharCategory.Word || categorizer(charBefore(buf, to - bufPos)) != state_.CharCategory.Word); }; } class StringQuery extends QueryType { constructor(spec) { super(spec); } nextMatch(state, curFrom, curTo) { let cursor = stringCursor(this.spec, state, curTo, state.doc.length).nextOverlapping(); if (cursor.done) cursor = stringCursor(this.spec, state, 0, curFrom).nextOverlapping(); return cursor.done ? null : cursor.value; } // Searching in reverse is, rather than implementing an inverted search // cursor, done by scanning chunk after chunk forward. prevMatchInRange(state, from, to) { for (let pos = to;;) { let start = Math.max(from, pos - 10000 /* FindPrev.ChunkSize */ - this.spec.unquoted.length); let cursor = stringCursor(this.spec, state, start, pos), range = null; while (!cursor.nextOverlapping().done) range = cursor.value; if (range) return range; if (start == from) return null; pos -= 10000 /* FindPrev.ChunkSize */; } } prevMatch(state, curFrom, curTo) { return this.prevMatchInRange(state, 0, curFrom) || this.prevMatchInRange(state, curTo, state.doc.length); } getReplacement(_result) { return this.spec.unquote(this.spec.replace); } matchAll(state, limit) { let cursor = stringCursor(this.spec, state, 0, state.doc.length), ranges = []; while (!cursor.next().done) { if (ranges.length >= limit) return null; ranges.push(cursor.value); } return ranges; } highlight(state, from, to, add) { let cursor = stringCursor(this.spec, state, Math.max(0, from - this.spec.unquoted.length), Math.min(to + this.spec.unquoted.length, state.doc.length)); while (!cursor.next().done) add(cursor.value.from, cursor.value.to); } } function regexpCursor(spec, state, from, to) { return new RegExpCursor(state.doc, spec.search, { ignoreCase: !spec.caseSensitive, test: spec.wholeWord ? regexpWordTest(state.charCategorizer(state.selection.main.head)) : undefined }, from, to); } function charBefore(str, index) { return str.slice((0,state_.findClusterBreak)(str, index, false), index); } function charAfter(str, index) { return str.slice(index, (0,state_.findClusterBreak)(str, index)); } function regexpWordTest(categorizer) { return (_from, _to, match) => !match[0].length || (categorizer(charBefore(match.input, match.index)) != state_.CharCategory.Word || categorizer(charAfter(match.input, match.index)) != state_.CharCategory.Word) && (categorizer(charAfter(match.input, match.index + match[0].length)) != state_.CharCategory.Word || categorizer(charBefore(match.input, match.index + match[0].length)) != state_.CharCategory.Word); } class RegExpQuery extends QueryType { nextMatch(state, curFrom, curTo) { let cursor = regexpCursor(this.spec, state, curTo, state.doc.length).next(); if (cursor.done) cursor = regexpCursor(this.spec, state, 0, curFrom).next(); return cursor.done ? null : cursor.value; } prevMatchInRange(state, from, to) { for (let size = 1;; size++) { let start = Math.max(from, to - size * 10000 /* FindPrev.ChunkSize */); let cursor = regexpCursor(this.spec, state, start, to), range = null; while (!cursor.next().done) range = cursor.value; if (range && (start == from || range.from > start + 10)) return range; if (start == from) return null; } } prevMatch(state, curFrom, curTo) { return this.prevMatchInRange(state, 0, curFrom) || this.prevMatchInRange(state, curTo, state.doc.length); } getReplacement(result) { return this.spec.unquote(this.spec.replace).replace(/\$([$&\d+])/g, (m, i) => i == "$" ? "$" : i == "&" ? result.match[0] : i != "0" && +i < result.match.length ? result.match[i] : m); } matchAll(state, limit) { let cursor = regexpCursor(this.spec, state, 0, state.doc.length), ranges = []; while (!cursor.next().done) { if (ranges.length >= limit) return null; ranges.push(cursor.value); } return ranges; } highlight(state, from, to, add) { let cursor = regexpCursor(this.spec, state, Math.max(0, from - 250 /* RegExp.HighlightMargin */), Math.min(to + 250 /* RegExp.HighlightMargin */, state.doc.length)); while (!cursor.next().done) add(cursor.value.from, cursor.value.to); } } /** A state effect that updates the current search query. Note that this only has an effect if the search state has been initialized (by including [`search`](https://codemirror.net/6/docs/ref/#search.search) in your configuration or by running [`openSearchPanel`](https://codemirror.net/6/docs/ref/#search.openSearchPanel) at least once). */ const setSearchQuery = /*@__PURE__*/state_.StateEffect.define(); const togglePanel = /*@__PURE__*/state_.StateEffect.define(); const searchState = /*@__PURE__*/state_.StateField.define({ create(state) { return new SearchState(defaultQuery(state).create(), null); }, update(value, tr) { for (let effect of tr.effects) { if (effect.is(setSearchQuery)) value = new SearchState(effect.value.create(), value.panel); else if (effect.is(togglePanel)) value = new SearchState(value.query, effect.value ? createSearchPanel : null); } return value; }, provide: f => view_.showPanel.from(f, val => val.panel) }); /** Get the current search query from an editor state. */ function getSearchQuery(state) { let curState = state.field(searchState, false); return curState ? curState.query.spec : defaultQuery(state); } /** Query whether the search panel is open in the given editor state. */ function searchPanelOpen(state) { var _a; return ((_a = state.field(searchState, false)) === null || _a === void 0 ? void 0 : _a.panel) != null; } class SearchState { constructor(query, panel) { this.query = query; this.panel = panel; } } const matchMark = /*@__PURE__*/view_.Decoration.mark({ class: "cm-searchMatch" }), selectedMatchMark = /*@__PURE__*/view_.Decoration.mark({ class: "cm-searchMatch cm-searchMatch-selected" }); const searchHighlighter = /*@__PURE__*/view_.ViewPlugin.fromClass(class { constructor(view) { this.view = view; this.decorations = this.highlight(view.state.field(searchState)); } update(update) { let state = update.state.field(searchState); if (state != update.startState.field(searchState) || update.docChanged || update.selectionSet || update.viewportChanged) this.decorations = this.highlight(state); } highlight({ query, panel }) { if (!panel || !query.spec.valid) return view_.Decoration.none; let { view } = this; let builder = new state_.RangeSetBuilder(); for (let i = 0, ranges = view.visibleRanges, l = ranges.length; i < l; i++) { let { from, to } = ranges[i]; while (i < l - 1 && to > ranges[i + 1].from - 2 * 250 /* RegExp.HighlightMargin */) to = ranges[++i].to; query.highlight(view.state, from, to, (from, to) => { let selected = view.state.selection.ranges.some(r => r.from == from && r.to == to); builder.add(from, to, selected ? selectedMatchMark : matchMark); }); } return builder.finish(); } }, { decorations: v => v.decorations }); function searchCommand(f) { return view => { let state = view.state.field(searchState, false); return state && state.query.spec.valid ? f(view, state) : openSearchPanel(view); }; } /** Open the search panel if it isn't already open, and move the selection to the first match after the current main selection. Will wrap around to the start of the document when it reaches the end. */ const findNext = /*@__PURE__*/searchCommand((view, { query }) => { let { to } = view.state.selection.main; let next = query.nextMatch(view.state, to, to); if (!next) return false; let selection = state_.EditorSelection.single(next.from, next.to); let config = view.state.facet(searchConfigFacet); view.dispatch({ selection, effects: [announceMatch(view, next), config.scrollToMatch(selection.main, view)], userEvent: "select.search" }); selectSearchInput(view); return true; }); /** Move the selection to the previous instance of the search query, before the current main selection. Will wrap past the start of the document to start searching at the end again. */ const findPrevious = /*@__PURE__*/searchCommand((view, { query }) => { let { state } = view, { from } = state.selection.main; let prev = query.prevMatch(state, from, from); if (!prev) return false; let selection = state_.EditorSelection.single(prev.from, prev.to); let config = view.state.facet(searchConfigFacet); view.dispatch({ selection, effects: [announceMatch(view, prev), config.scrollToMatch(selection.main, view)], userEvent: "select.search" }); selectSearchInput(view); return true; }); /** Select all instances of the search query. */ const selectMatches = /*@__PURE__*/searchCommand((view, { query }) => { let ranges = query.matchAll(view.state, 1000); if (!ranges || !ranges.length) return false; view.dispatch({ selection: state_.EditorSelection.create(ranges.map(r => state_.EditorSelection.range(r.from, r.to))), userEvent: "select.search.matches" }); return true; }); /** Select all instances of the currently selected text. */ const selectSelectionMatches = ({ state, dispatch }) => { let sel = state.selection; if (sel.ranges.length > 1 || sel.main.empty) return false; let { from, to } = sel.main; let ranges = [], main = 0; for (let cur = new SearchCursor(state.doc, state.sliceDoc(from, to)); !cur.next().done;) { if (ranges.length > 1000) return false; if (cur.value.from == from) main = ranges.length; ranges.push(state_.EditorSelection.range(cur.value.from, cur.value.to)); } dispatch(state.update({ selection: state_.EditorSelection.create(ranges, main), userEvent: "select.search.matches" })); return true; }; /** Replace the current match of the search query. */ const replaceNext = /*@__PURE__*/searchCommand((view, { query }) => { let { state } = view, { from, to } = state.selection.main; if (state.readOnly) return false; let next = query.nextMatch(state, from, from); if (!next) return false; let changes = [], selection, replacement; let effects = []; if (next.from == from && next.to == to) { replacement = state.toText(query.getReplacement(next)); changes.push({ from: next.from, to: next.to, insert: replacement }); next = query.nextMatch(state, next.from, next.to); effects.push(view_.EditorView.announce.of(state.phrase("replaced match on line $", state.doc.lineAt(from).number) + ".")); } if (next) { let off = changes.length == 0 || changes[0].from >= next.to ? 0 : next.to - next.from - replacement.length; selection = state_.EditorSelection.single(next.from - off, next.to - off); effects.push(announceMatch(view, next)); effects.push(state.facet(searchConfigFacet).scrollToMatch(selection.main, view)); } view.dispatch({ changes, selection, effects, userEvent: "input.replace" }); return true; }); /** Replace all instances of the search query with the given replacement. */ const replaceAll = /*@__PURE__*/searchCommand((view, { query }) => { if (view.state.readOnly) return false; let changes = query.matchAll(view.state, 1e9).map(match => { let { from, to } = match; return { from, to, insert: query.getReplacement(match) }; }); if (!changes.length) return false; let announceText = view.state.phrase("replaced $ matches", changes.length) + "."; view.dispatch({ changes, effects: view_.EditorView.announce.of(announceText), userEvent: "input.replace.all" }); return true; }); function createSearchPanel(view) { return view.state.facet(searchConfigFacet).createPanel(view); } function defaultQuery(state, fallback) { var _a, _b, _c, _d, _e; let sel = state.selection.main; let selText = sel.empty || sel.to > sel.from + 100 ? "" : state.sliceDoc(sel.from, sel.to); if (fallback && !selText) return fallback; let config = state.facet(searchConfigFacet); return new SearchQuery({ search: ((_a = fallback === null || fallback === void 0 ? void 0 : fallback.literal) !== null && _a !== void 0 ? _a : config.literal) ? selText : selText.replace(/\n/g, "\\n"), caseSensitive: (_b = fallback === null || fallback === void 0 ? void 0 : fallback.caseSensitive) !== null && _b !== void 0 ? _b : config.caseSensitive, literal: (_c = fallback === null || fallback === void 0 ? void 0 : fallback.literal) !== null && _c !== void 0 ? _c : config.literal, regexp: (_d = fallback === null || fallback === void 0 ? void 0 : fallback.regexp) !== null && _d !== void 0 ? _d : config.regexp, wholeWord: (_e = fallback === null || fallback === void 0 ? void 0 : fallback.wholeWord) !== null && _e !== void 0 ? _e : config.wholeWord }); } function getSearchInput(view) { let panel = (0,view_.getPanel)(view, createSearchPanel); return panel && panel.dom.querySelector("[main-field]"); } function selectSearchInput(view) { let input = getSearchInput(view); if (input && input == view.root.activeElement) input.select(); } /** Make sure the search panel is open and focused. */ const openSearchPanel = view => { let state = view.state.field(searchState, false); if (state && state.panel) { let searchInput = getSearchInput(view); if (searchInput && searchInput != view.root.activeElement) { let query = defaultQuery(view.state, state.query.spec); if (query.valid) view.dispatch({ effects: setSearchQuery.of(query) }); searchInput.focus(); searchInput.select(); } } else { view.dispatch({ effects: [ togglePanel.of(true), state ? setSearchQuery.of(defaultQuery(view.state, state.query.spec)) : state_.StateEffect.appendConfig.of(searchExtensions) ] }); } return true; }; /** Close the search panel. */ const closeSearchPanel = view => { let state = view.state.field(searchState, false); if (!state || !state.panel) return false; let panel = (0,view_.getPanel)(view, createSearchPanel); if (panel && panel.dom.contains(view.root.activeElement)) view.focus(); view.dispatch({ effects: togglePanel.of(false) }); return true; }; /** Default search-related key bindings. - Mod-f: [`openSearchPanel`](https://codemirror.net/6/docs/ref/#search.openSearchPanel) - F3, Mod-g: [`findNext`](https://codemirror.net/6/docs/ref/#search.findNext) - Shift-F3, Shift-Mod-g: [`findPrevious`](https://codemirror.net/6/docs/ref/#search.findPrevious) - Mod-Alt-g: [`gotoLine`](https://codemirror.net/6/docs/ref/#search.gotoLine) - Mod-d: [`selectNextOccurrence`](https://codemirror.net/6/docs/ref/#search.selectNextOccurrence) */ const searchKeymap = [ { key: "Mod-f", run: openSearchPanel, scope: "editor search-panel" }, { key: "F3", run: findNext, shift: findPrevious, scope: "editor search-panel", preventDefault: true }, { key: "Mod-g", run: findNext, shift: findPrevious, scope: "editor search-panel", preventDefault: true }, { key: "Escape", run: closeSearchPanel, scope: "editor search-panel" }, { key: "Mod-Shift-l", run: selectSelectionMatches }, { key: "Mod-Alt-g", run: gotoLine }, { key: "Mod-d", run: selectNextOccurrence, preventDefault: true }, ]; class SearchPanel { constructor(view) { this.view = view; let query = this.query = view.state.field(searchState).query.spec; this.commit = this.commit.bind(this); this.searchField = crelt("input", { value: query.search, placeholder: phrase(view, "Find"), "aria-label": phrase(view, "Find"), class: "cm-textfield", name: "search", form: "", "main-field": "true", onchange: this.commit, onkeyup: this.commit }); this.replaceField = crelt("input", { value: query.replace, placeholder: phrase(view, "Replace"), "aria-label": phrase(view, "Replace"), class: "cm-textfield", name: "replace", form: "", onchange: this.commit, onkeyup: this.commit }); this.caseField = crelt("input", { type: "checkbox", name: "case", form: "", checked: query.caseSensitive, onchange: this.commit }); this.reField = crelt("input", { type: "checkbox", name: "re", form: "", checked: query.regexp, onchange: this.commit }); this.wordField = crelt("input", { type: "checkbox", name: "word", form: "", checked: query.wholeWord, onchange: this.commit }); function button(name, onclick, content) { return crelt("button", { class: "cm-button", name, onclick, type: "button" }, content); } this.dom = crelt("div", { onkeydown: (e) => this.keydown(e), class: "cm-search" }, [ this.searchField, button("next", () => findNext(view), [phrase(view, "next")]), button("prev", () => findPrevious(view), [phrase(view, "previous")]), button("select", () => selectMatches(view), [phrase(view, "all")]), crelt("label", null, [this.caseField, phrase(view, "match case")]), crelt("label", null, [this.reField, phrase(view, "regexp")]), crelt("label", null, [this.wordField, phrase(view, "by word")]), ...view.state.readOnly ? [] : [ crelt("br"), this.replaceField, button("replace", () => replaceNext(view), [phrase(view, "replace")]), button("replaceAll", () => replaceAll(view), [phrase(view, "replace all")]) ], crelt("button", { name: "close", onclick: () => closeSearchPanel(view), "aria-label": phrase(view, "close"), type: "button" }, ["×"]) ]); } commit() { let query = new SearchQuery({ search: this.searchField.value, caseSensitive: this.caseField.checked, regexp: this.reField.checked, wholeWord: this.wordField.checked, replace: this.replaceField.value, }); if (!query.eq(this.query)) { this.query = query; this.view.dispatch({ effects: setSearchQuery.of(query) }); } } keydown(e) { if ((0,view_.runScopeHandlers)(this.view, e, "search-panel")) { e.preventDefault(); } else if (e.keyCode == 13 && e.target == this.searchField) { e.preventDefault(); (e.shiftKey ? findPrevious : findNext)(this.view); } else if (e.keyCode == 13 && e.target == this.replaceField) { e.preventDefault(); replaceNext(this.view); } } update(update) { for (let tr of update.transactions) for (let effect of tr.effects) { if (effect.is(setSearchQuery) && !effect.value.eq(this.query)) this.setQuery(effect.value); } } setQuery(query) { this.query = query; this.searchField.value = query.search; this.replaceField.value = query.replace; this.caseField.checked = query.caseSensitive; this.reField.checked = query.regexp; this.wordField.checked = query.wholeWord; } mount() { this.searchField.select(); } get pos() { return 80; } get top() { return this.view.state.facet(searchConfigFacet).top; } } function phrase(view, phrase) { return view.state.phrase(phrase); } const AnnounceMargin = 30; const Break = /[\s\.,:;?!]/; function announceMatch(view, { from, to }) { let line = view.state.doc.lineAt(from), lineEnd = view.state.doc.lineAt(to).to; let start = Math.max(line.from, from - AnnounceMargin), end = Math.min(lineEnd, to + AnnounceMargin); let text = view.state.sliceDoc(start, end); if (start != line.from) { for (let i = 0; i < AnnounceMargin; i++) if (!Break.test(text[i + 1]) && Break.test(text[i])) { text = text.slice(i); break; } } if (end != lineEnd) { for (let i = text.length - 1; i > text.length - AnnounceMargin; i--) if (!Break.test(text[i - 1]) && Break.test(text[i])) { text = text.slice(0, i); break; } } return view_.EditorView.announce.of(`${view.state.phrase("current match")}. ${text} ${view.state.phrase("on line")} ${line.number}.`); } const baseTheme = /*@__PURE__*/view_.EditorView.baseTheme({ ".cm-panel.cm-search": { padding: "2px 6px 4px", position: "relative", "& [name=close]": { position: "absolute", top: "0", right: "4px", backgroundColor: "inherit", border: "none", font: "inherit", padding: 0, margin: 0 }, "& input, & button, & label": { margin: ".2em .6em .2em 0" }, "& input[type=checkbox]": { marginRight: ".2em" }, "& label": { fontSize: "80%", whiteSpace: "pre" } }, "&light .cm-searchMatch": { backgroundColor: "#ffff0054" }, "&dark .cm-searchMatch": { backgroundColor: "#00ffff8a" }, "&light .cm-searchMatch-selected": { backgroundColor: "#ff6a0054" }, "&dark .cm-searchMatch-selected": { backgroundColor: "#ff00ff8a" } }); const searchExtensions = [ searchState, /*@__PURE__*/state_.Prec.low(searchHighlighter), baseTheme ]; // EXTERNAL MODULE: ../node_modules/@codemirror/language/dist/index.js + 2 modules var language_dist = __webpack_require__(194); ;// CONCATENATED MODULE: ../node_modules/@codemirror/autocomplete/dist/index.js /** An instance of this is passed to completion source functions. */ class CompletionContext { /** Create a new completion context. (Mostly useful for testing completion sources—in the editor, the extension will create these for you.) */ constructor( /** The editor state that the completion happens in. */ state, /** The position at which the completion is happening. */ pos, /** Indicates whether completion was activated explicitly, or implicitly by typing. The usual way to respond to this is to only return completions when either there is part of a completable entity before the cursor, or `explicit` is true. */ explicit) { this.state = state; this.pos = pos; this.explicit = explicit; /** @internal */ this.abortListeners = []; } /** Get the extent, content, and (if there is a token) type of the token before `this.pos`. */ tokenBefore(types) { let token = (0,language_dist/* syntaxTree */.mv)(this.state).resolveInner(this.pos, -1); while (token && types.indexOf(token.name) < 0) token = token.parent; return token ? { from: token.from, to: this.pos, text: this.state.sliceDoc(token.from, this.pos), type: token.type } : null; } /** Get the match of the given expression directly before the cursor. */ matchBefore(expr) { let line = this.state.doc.lineAt(this.pos); let start = Math.max(line.from, this.pos - 250); let str = line.text.slice(start - line.from, this.pos - line.from); let found = str.search(ensureAnchor(expr, false)); return found < 0 ? null : { from: start + found, to: this.pos, text: str.slice(found) }; } /** Yields true when the query has been aborted. Can be useful in asynchronous queries to avoid doing work that will be ignored. */ get aborted() { return this.abortListeners == null; } /** Allows you to register abort handlers, which will be called when the query is [aborted](https://codemirror.net/6/docs/ref/#autocomplete.CompletionContext.aborted). */ addEventListener(type, listener) { if (type == "abort" && this.abortListeners) this.abortListeners.push(listener); } } function toSet(chars) { let flat = Object.keys(chars).join(""); let words = /\w/.test(flat); if (words) flat = flat.replace(/\w/g, ""); return `[${words ? "\\w" : ""}${flat.replace(/[^\w\s]/g, "\\$&")}]`; } function prefixMatch(options) { let first = Object.create(null), rest = Object.create(null); for (let { label } of options) { first[label[0]] = true; for (let i = 1; i < label.length; i++) rest[label[i]] = true; } let source = toSet(first) + toSet(rest) + "*$"; return [new RegExp("^" + source), new RegExp(source)]; } /** Given a a fixed array of options, return an autocompleter that completes them. */ function completeFromList(list) { let options = list.map(o => typeof o == "string" ? { label: o } : o); let [validFor, match] = options.every(o => /^\w+$/.test(o.label)) ? [/\w*$/, /\w+$/] : prefixMatch(options); return (context) => { let token = context.matchBefore(match); return token || context.explicit ? { from: token ? token.from : context.pos, options, validFor } : null; }; } /** Wrap the given completion source so that it will only fire when the cursor is in a syntax node with one of the given names. */ function ifIn(nodes, source) { return (context) => { for (let pos = syntaxTree(context.state).resolveInner(context.pos, -1); pos; pos = pos.parent) { if (nodes.indexOf(pos.name) > -1) return source(context); if (pos.type.isTop) break; } return null; }; } /** Wrap the given completion source so that it will not fire when the cursor is in a syntax node with one of the given names. */ function ifNotIn(nodes, source) { return (context) => { for (let pos = syntaxTree(context.state).resolveInner(context.pos, -1); pos; pos = pos.parent) { if (nodes.indexOf(pos.name) > -1) return null; if (pos.type.isTop) break; } return source(context); }; } class Option { constructor(completion, source, match, score) { this.completion = completion; this.source = source; this.match = match; this.score = score; } } function cur(state) { return state.selection.main.from; } // Make sure the given regexp has a $ at its end and, if `start` is // true, a ^ at its start. function ensureAnchor(expr, start) { var _a; let { source } = expr; let addStart = start && source[0] != "^", addEnd = source[source.length - 1] != "$"; if (!addStart && !addEnd) return expr; return new RegExp(`${addStart ? "^" : ""}(?:${source})${addEnd ? "$" : ""}`, (_a = expr.flags) !== null && _a !== void 0 ? _a : (expr.ignoreCase ? "i" : "")); } /** This annotation is added to transactions that are produced by picking a completion. */ const pickedCompletion = /*@__PURE__*/state_.Annotation.define(); /** Helper function that returns a transaction spec which inserts a completion's text in the main selection range, and any other selection range that has the same text in front of it. */ function insertCompletionText(state, text, from, to) { let { main } = state.selection, fromOff = from - main.from, toOff = to - main.from; return Object.assign(Object.assign({}, state.changeByRange(range => { if (range != main && from != to && state.sliceDoc(range.from + fromOff, range.from + toOff) != state.sliceDoc(from, to)) return { range }; return { changes: { from: range.from + fromOff, to: to == main.from ? range.to : range.from + toOff, insert: text }, range: state_.EditorSelection.cursor(range.from + fromOff + text.length) }; })), { scrollIntoView: true, userEvent: "input.complete" }); } const SourceCache = /*@__PURE__*/new WeakMap(); function asSource(source) { if (!Array.isArray(source)) return source; let known = SourceCache.get(source); if (!known) SourceCache.set(source, known = completeFromList(source)); return known; } const startCompletionEffect = /*@__PURE__*/state_.StateEffect.define(); const closeCompletionEffect = /*@__PURE__*/state_.StateEffect.define(); // A pattern matcher for fuzzy completion matching. Create an instance // once for a pattern, and then use that to match any number of // completions. class FuzzyMatcher { constructor(pattern) { this.pattern = pattern; this.chars = []; this.folded = []; // Buffers reused by calls to `match` to track matched character // positions. this.any = []; this.precise = []; this.byWord = []; this.score = 0; this.matched = []; for (let p = 0; p < pattern.length;) { let char = (0,state_.codePointAt)(pattern, p), size = (0,state_.codePointSize)(char); this.chars.push(char); let part = pattern.slice(p, p + size), upper = part.toUpperCase(); this.folded.push((0,state_.codePointAt)(upper == part ? part.toLowerCase() : upper, 0)); p += size; } this.astral = pattern.length != this.chars.length; } ret(score, matched) { this.score = score; this.matched = matched; return this; } // Matches a given word (completion) against the pattern (input). // Will return a boolean indicating whether there was a match and, // on success, set `this.score` to the score, `this.matched` to an // array of `from, to` pairs indicating the matched parts of `word`. // // The score is a number that is more negative the worse the match // is. See `Penalty` above. match(word) { if (this.pattern.length == 0) return this.ret(-100 /* Penalty.NotFull */, []); if (word.length < this.pattern.length) return null; let { chars, folded, any, precise, byWord } = this; // For single-character queries, only match when they occur right // at the start if (chars.length == 1) { let first = (0,state_.codePointAt)(word, 0), firstSize = (0,state_.codePointSize)(first); let score = firstSize == word.length ? 0 : -100 /* Penalty.NotFull */; if (first == chars[0]) ; else if (first == folded[0]) score += -200 /* Penalty.CaseFold */; else return null; return this.ret(score, [0, firstSize]); } let direct = word.indexOf(this.pattern); if (direct == 0) return this.ret(word.length == this.pattern.length ? 0 : -100 /* Penalty.NotFull */, [0, this.pattern.length]); let len = chars.length, anyTo = 0; if (direct < 0) { for (let i = 0, e = Math.min(word.length, 200); i < e && anyTo < len;) { let next = (0,state_.codePointAt)(word, i); if (next == chars[anyTo] || next == folded[anyTo]) any[anyTo++] = i; i += (0,state_.codePointSize)(next); } // No match, exit immediately if (anyTo < len) return null; } // This tracks the extent of the precise (non-folded, not // necessarily adjacent) match let preciseTo = 0; // Tracks whether there is a match that hits only characters that // appear to be starting words. `byWordFolded` is set to true when // a case folded character is encountered in such a match let byWordTo = 0, byWordFolded = false; // If we've found a partial adjacent match, these track its state let adjacentTo = 0, adjacentStart = -1, adjacentEnd = -1; let hasLower = /[a-z]/.test(word), wordAdjacent = true; // Go over the option's text, scanning for the various kinds of matches for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /* Tp.NonWord */; i < e && byWordTo < len;) { let next = (0,state_.codePointAt)(word, i); if (direct < 0) { if (preciseTo < len && next == chars[preciseTo]) precise[preciseTo++] = i; if (adjacentTo < len) { if (next == chars[adjacentTo] || next == folded[adjacentTo]) { if (adjacentTo == 0) adjacentStart = i; adjacentEnd = i + 1; adjacentTo++; } else { adjacentTo = 0; } } } let ch, type = next < 0xff ? (next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 /* Tp.Lower */ : next >= 65 && next <= 90 ? 1 /* Tp.Upper */ : 0 /* Tp.NonWord */) : ((ch = (0,state_.fromCodePoint)(next)) != ch.toLowerCase() ? 1 /* Tp.Upper */ : ch != ch.toUpperCase() ? 2 /* Tp.Lower */ : 0 /* Tp.NonWord */); if (!i || type == 1 /* Tp.Upper */ && hasLower || prevType == 0 /* Tp.NonWord */ && type != 0 /* Tp.NonWord */) { if (chars[byWordTo] == next || (folded[byWordTo] == next && (byWordFolded = true))) byWord[byWordTo++] = i; else if (byWord.length) wordAdjacent = false; } prevType = type; i += (0,state_.codePointSize)(next); } if (byWordTo == len && byWord[0] == 0 && wordAdjacent) return this.result(-100 /* Penalty.ByWord */ + (byWordFolded ? -200 /* Penalty.CaseFold */ : 0), byWord, word); if (adjacentTo == len && adjacentStart == 0) return this.ret(-200 /* Penalty.CaseFold */ - word.length + (adjacentEnd == word.length ? 0 : -100 /* Penalty.NotFull */), [0, adjacentEnd]); if (direct > -1) return this.ret(-700 /* Penalty.NotStart */ - word.length, [direct, direct + this.pattern.length]); if (adjacentTo == len) return this.ret(-200 /* Penalty.CaseFold */ + -700 /* Penalty.NotStart */ - word.length, [adjacentStart, adjacentEnd]); if (byWordTo == len) return this.result(-100 /* Penalty.ByWord */ + (byWordFolded ? -200 /* Penalty.CaseFold */ : 0) + -700 /* Penalty.NotStart */ + (wordAdjacent ? 0 : -1100 /* Penalty.Gap */), byWord, word); return chars.length == 2 ? null : this.result((any[0] ? -700 /* Penalty.NotStart */ : 0) + -200 /* Penalty.CaseFold */ + -1100 /* Penalty.Gap */, any, word); } result(score, positions, word) { let result = [], i = 0; for (let pos of positions) { let to = pos + (this.astral ? (0,state_.codePointSize)((0,state_.codePointAt)(word, pos)) : 1); if (i && result[i - 1] == pos) result[i - 1] = to; else { result[i++] = pos; result[i++] = to; } } return this.ret(score - word.length, result); } } class StrictMatcher { constructor(pattern) { this.pattern = pattern; this.matched = []; this.score = 0; this.folded = pattern.toLowerCase(); } match(word) { if (word.length < this.pattern.length) return null; let start = word.slice(0, this.pattern.length); let match = start == this.pattern ? 0 : start.toLowerCase() == this.folded ? -200 /* Penalty.CaseFold */ : null; if (match == null) return null; this.matched = [0, start.length]; this.score = match + (word.length == this.pattern.length ? 0 : -100 /* Penalty.NotFull */); return this; } } const completionConfig = /*@__PURE__*/state_.Facet.define({ combine(configs) { return (0,state_.combineConfig)(configs, { activateOnTyping: true, activateOnCompletion: () => false, activateOnTypingDelay: 100, selectOnOpen: true, override: null, closeOnBlur: true, maxRenderedOptions: 100, defaultKeymap: true, tooltipClass: () => "", optionClass: () => "", aboveCursor: false, icons: true, addToOptions: [], positionInfo: defaultPositionInfo, filterStrict: false, compareCompletions: (a, b) => a.label.localeCompare(b.label), interactionDelay: 75, updateSyncTime: 100 }, { defaultKeymap: (a, b) => a && b, closeOnBlur: (a, b) => a && b, icons: (a, b) => a && b, tooltipClass: (a, b) => c => joinClass(a(c), b(c)), optionClass: (a, b) => c => joinClass(a(c), b(c)), addToOptions: (a, b) => a.concat(b), filterStrict: (a, b) => a || b, }); } }); function joinClass(a, b) { return a ? b ? a + " " + b : a : b; } function defaultPositionInfo(view, list, option, info, space, tooltip) { let rtl = view.textDirection == view_.Direction.RTL, left = rtl, narrow = false; let side = "top", offset, maxWidth; let spaceLeft = list.left - space.left, spaceRight = space.right - list.right; let infoWidth = info.right - info.left, infoHeight = info.bottom - info.top; if (left && spaceLeft < Math.min(infoWidth, spaceRight)) left = false; else if (!left && spaceRight < Math.min(infoWidth, spaceLeft)) left = true; if (infoWidth <= (left ? spaceLeft : spaceRight)) { offset = Math.max(space.top, Math.min(option.top, space.bottom - infoHeight)) - list.top; maxWidth = Math.min(400 /* Info.Width */, left ? spaceLeft : spaceRight); } else { narrow = true; maxWidth = Math.min(400 /* Info.Width */, (rtl ? list.right : space.right - list.left) - 30 /* Info.Margin */); let spaceBelow = space.bottom - list.bottom; if (spaceBelow >= infoHeight || spaceBelow > list.top) { // Below the completion offset = option.bottom - list.top; } else { // Above it side = "bottom"; offset = list.bottom - option.top; } } let scaleY = (list.bottom - list.top) / tooltip.offsetHeight; let scaleX = (list.right - list.left) / tooltip.offsetWidth; return { style: `${side}: ${offset / scaleY}px; max-width: ${maxWidth / scaleX}px`, class: "cm-completionInfo-" + (narrow ? (rtl ? "left-narrow" : "right-narrow") : left ? "left" : "right") }; } function optionContent(config) { let content = config.addToOptions.slice(); if (config.icons) content.push({ render(completion) { let icon = document.createElement("div"); icon.classList.add("cm-completionIcon"); if (completion.type) icon.classList.add(...completion.type.split(/\s+/g).map(cls => "cm-completionIcon-" + cls)); icon.setAttribute("aria-hidden", "true"); return icon; }, position: 20 }); content.push({ render(completion, _s, _v, match) { let labelElt = document.createElement("span"); labelElt.className = "cm-completionLabel"; let label = completion.displayLabel || completion.label, off = 0; for (let j = 0; j < match.length;) { let from = match[j++], to = match[j++]; if (from > off) labelElt.appendChild(document.createTextNode(label.slice(off, from))); let span = labelElt.appendChild(document.createElement("span")); span.appendChild(document.createTextNode(label.slice(from, to))); span.className = "cm-completionMatchedText"; off = to; } if (off < label.length) labelElt.appendChild(document.createTextNode(label.slice(off))); return labelElt; }, position: 50 }, { render(completion) { if (!completion.detail) return null; let detailElt = document.createElement("span"); detailElt.className = "cm-completionDetail"; detailElt.textContent = completion.detail; return detailElt; }, position: 80 }); return content.sort((a, b) => a.position - b.position).map(a => a.render); } function rangeAroundSelected(total, selected, max) { if (total <= max) return { from: 0, to: total }; if (selected < 0) selected = 0; if (selected <= (total >> 1)) { let off = Math.floor(selected / max); return { from: off * max, to: (off + 1) * max }; } let off = Math.floor((total - selected) / max); return { from: total - (off + 1) * max, to: total - off * max }; } class CompletionTooltip { constructor(view, stateField, applyCompletion) { this.view = view; this.stateField = stateField; this.applyCompletion = applyCompletion; this.info = null; this.infoDestroy = null; this.placeInfoReq = { read: () => this.measureInfo(), write: (pos) => this.placeInfo(pos), key: this }; this.space = null; this.currentClass = ""; let cState = view.state.field(stateField); let { options, selected } = cState.open; let config = view.state.facet(completionConfig); this.optionContent = optionContent(config); this.optionClass = config.optionClass; this.tooltipClass = config.tooltipClass; this.range = rangeAroundSelected(options.length, selected, config.maxRenderedOptions); this.dom = document.createElement("div"); this.dom.className = "cm-tooltip-autocomplete"; this.updateTooltipClass(view.state); this.dom.addEventListener("mousedown", (e) => { let { options } = view.state.field(stateField).open; for (let dom = e.target, match; dom && dom != this.dom; dom = dom.parentNode) { if (dom.nodeName == "LI" && (match = /-(\d+)$/.exec(dom.id)) && +match[1] < options.length) { this.applyCompletion(view, options[+match[1]]); e.preventDefault(); return; } } }); this.dom.addEventListener("focusout", (e) => { let state = view.state.field(this.stateField, false); if (state && state.tooltip && view.state.facet(completionConfig).closeOnBlur && e.relatedTarget != view.contentDOM) view.dispatch({ effects: closeCompletionEffect.of(null) }); }); this.showOptions(options, cState.id); } mount() { this.updateSel(); } showOptions(options, id) { if (this.list) this.list.remove(); this.list = this.dom.appendChild(this.createListBox(options, id, this.range)); this.list.addEventListener("scroll", () => { if (this.info) this.view.requestMeasure(this.placeInfoReq); }); } update(update) { var _a; let cState = update.state.field(this.stateField); let prevState = update.startState.field(this.stateField); this.updateTooltipClass(update.state); if (cState != prevState) { let { options, selected, disabled } = cState.open; if (!prevState.open || prevState.open.options != options) { this.range = rangeAroundSelected(options.length, selected, update.state.facet(completionConfig).maxRenderedOptions); this.showOptions(options, cState.id); } this.updateSel(); if (disabled != ((_a = prevState.open) === null || _a === void 0 ? void 0 : _a.disabled)) this.dom.classList.toggle("cm-tooltip-autocomplete-disabled", !!disabled); } } updateTooltipClass(state) { let cls = this.tooltipClass(state); if (cls != this.currentClass) { for (let c of this.currentClass.split(" ")) if (c) this.dom.classList.remove(c); for (let c of cls.split(" ")) if (c) this.dom.classList.add(c); this.currentClass = cls; } } positioned(space) { this.space = space; if (this.info) this.view.requestMeasure(this.placeInfoReq); } updateSel() { let cState = this.view.state.field(this.stateField), open = cState.open; if (open.selected > -1 && open.selected < this.range.from || open.selected >= this.range.to) { this.range = rangeAroundSelected(open.options.length, open.selected, this.view.state.facet(completionConfig).maxRenderedOptions); this.showOptions(open.options, cState.id); } if (this.updateSelectedOption(open.selected)) { this.destroyInfo(); let { completion } = open.options[open.selected]; let { info } = completion; if (!info) return; let infoResult = typeof info === "string" ? document.createTextNode(info) : info(completion); if (!infoResult) return; if ("then" in infoResult) { infoResult.then(obj => { if (obj && this.view.state.field(this.stateField, false) == cState) this.addInfoPane(obj, completion); }).catch(e => (0,view_.logException)(this.view.state, e, "completion info")); } else { this.addInfoPane(infoResult, completion); } } } addInfoPane(content, completion) { this.destroyInfo(); let wrap = this.info = document.createElement("div"); wrap.className = "cm-tooltip cm-completionInfo"; if (content.nodeType != null) { wrap.appendChild(content); this.infoDestroy = null; } else { let { dom, destroy } = content; wrap.appendChild(dom); this.infoDestroy = destroy || null; } this.dom.appendChild(wrap); this.view.requestMeasure(this.placeInfoReq); } updateSelectedOption(selected) { let set = null; for (let opt = this.list.firstChild, i = this.range.from; opt; opt = opt.nextSibling, i++) { if (opt.nodeName != "LI" || !opt.id) { i--; // A section header } else if (i == selected) { if (!opt.hasAttribute("aria-selected")) { opt.setAttribute("aria-selected", "true"); set = opt; } } else { if (opt.hasAttribute("aria-selected")) opt.removeAttribute("aria-selected"); } } if (set) scrollIntoView(this.list, set); return set; } measureInfo() { let sel = this.dom.querySelector("[aria-selected]"); if (!sel || !this.info) return null; let listRect = this.dom.getBoundingClientRect(); let infoRect = this.info.getBoundingClientRect(); let selRect = sel.getBoundingClientRect(); let space = this.space; if (!space) { let win = this.dom.ownerDocument.defaultView || window; space = { left: 0, top: 0, right: win.innerWidth, bottom: win.innerHeight }; } if (selRect.top > Math.min(space.bottom, listRect.bottom) - 10 || selRect.bottom < Math.max(space.top, listRect.top) + 10) return null; return this.view.state.facet(completionConfig).positionInfo(this.view, listRect, selRect, infoRect, space, this.dom); } placeInfo(pos) { if (this.info) { if (pos) { if (pos.style) this.info.style.cssText = pos.style; this.info.className = "cm-tooltip cm-completionInfo " + (pos.class || ""); } else { this.info.style.cssText = "top: -1e6px"; } } } createListBox(options, id, range) { const ul = document.createElement("ul"); ul.id = id; ul.setAttribute("role", "listbox"); ul.setAttribute("aria-expanded", "true"); ul.setAttribute("aria-label", this.view.state.phrase("Completions")); let curSection = null; for (let i = range.from; i < range.to; i++) { let { completion, match } = options[i], { section } = completion; if (section) { let name = typeof section == "string" ? section : section.name; if (name != curSection && (i > range.from || range.from == 0)) { curSection = name; if (typeof section != "string" && section.header) { ul.appendChild(section.header(section)); } else { let header = ul.appendChild(document.createElement("completion-section")); header.textContent = name; } } } const li = ul.appendChild(document.createElement("li")); li.id = id + "-" + i; li.setAttribute("role", "option"); let cls = this.optionClass(completion); if (cls) li.className = cls; for (let source of this.optionContent) { let node = source(completion, this.view.state, this.view, match); if (node) li.appendChild(node); } } if (range.from) ul.classList.add("cm-completionListIncompleteTop"); if (range.to < options.length) ul.classList.add("cm-completionListIncompleteBottom"); return ul; } destroyInfo() { if (this.info) { if (this.infoDestroy) this.infoDestroy(); this.info.remove(); this.info = null; } } destroy() { this.destroyInfo(); } } function completionTooltip(stateField, applyCompletion) { return (view) => new CompletionTooltip(view, stateField, applyCompletion); } function scrollIntoView(container, element) { let parent = container.getBoundingClientRect(); let self = element.getBoundingClientRect(); let scaleY = parent.height / container.offsetHeight; if (self.top < parent.top) container.scrollTop -= (parent.top - self.top) / scaleY; else if (self.bottom > parent.bottom) container.scrollTop += (self.bottom - parent.bottom) / scaleY; } // Used to pick a preferred option when two options with the same // label occur in the result. function score(option) { return (option.boost || 0) * 100 + (option.apply ? 10 : 0) + (option.info ? 5 : 0) + (option.type ? 1 : 0); } function sortOptions(active, state) { let options = []; let sections = null; let addOption = (option) => { options.push(option); let { section } = option.completion; if (section) { if (!sections) sections = []; let name = typeof section == "string" ? section : section.name; if (!sections.some(s => s.name == name)) sections.push(typeof section == "string" ? { name } : section); } }; let conf = state.facet(completionConfig); for (let a of active) if (a.hasResult()) { let getMatch = a.result.getMatch; if (a.result.filter === false) { for (let option of a.result.options) { addOption(new Option(option, a.source, getMatch ? getMatch(option) : [], 1e9 - options.length)); } } else { let pattern = state.sliceDoc(a.from, a.to), match; let matcher = conf.filterStrict ? new StrictMatcher(pattern) : new FuzzyMatcher(pattern); for (let option of a.result.options) if (match = matcher.match(option.label)) { let matched = !option.displayLabel ? match.matched : getMatch ? getMatch(option, match.matched) : []; addOption(new Option(option, a.source, matched, match.score + (option.boost || 0))); } } } if (sections) { let sectionOrder = Object.create(null), pos = 0; let cmp = (a, b) => { var _a, _b; return ((_a = a.rank) !== null && _a !== void 0 ? _a : 1e9) - ((_b = b.rank) !== null && _b !== void 0 ? _b : 1e9) || (a.name < b.name ? -1 : 1); }; for (let s of sections.sort(cmp)) { pos -= 1e5; sectionOrder[s.name] = pos; } for (let option of options) { let { section } = option.completion; if (section) option.score += sectionOrder[typeof section == "string" ? section : section.name]; } } let result = [], prev = null; let compare = conf.compareCompletions; for (let opt of options.sort((a, b) => (b.score - a.score) || compare(a.completion, b.completion))) { let cur = opt.completion; if (!prev || prev.label != cur.label || prev.detail != cur.detail || (prev.type != null && cur.type != null && prev.type != cur.type) || prev.apply != cur.apply || prev.boost != cur.boost) result.push(opt); else if (score(opt.completion) > score(prev)) result[result.length - 1] = opt; prev = opt.completion; } return result; } class CompletionDialog { constructor(options, attrs, tooltip, timestamp, selected, disabled) { this.options = options; this.attrs = attrs; this.tooltip = tooltip; this.timestamp = timestamp; this.selected = selected; this.disabled = disabled; } setSelected(selected, id) { return selected == this.selected || selected >= this.options.length ? this : new CompletionDialog(this.options, makeAttrs(id, selected), this.tooltip, this.timestamp, selected, this.disabled); } static build(active, state, id, prev, conf) { let options = sortOptions(active, state); if (!options.length) { return prev && active.some(a => a.state == 1 /* State.Pending */) ? new CompletionDialog(prev.options, prev.attrs, prev.tooltip, prev.timestamp, prev.selected, true) : null; } let selected = state.facet(completionConfig).selectOnOpen ? 0 : -1; if (prev && prev.selected != selected && prev.selected != -1) { let selectedValue = prev.options[prev.selected].completion; for (let i = 0; i < options.length; i++) if (options[i].completion == selectedValue) { selected = i; break; } } return new CompletionDialog(options, makeAttrs(id, selected), { pos: active.reduce((a, b) => b.hasResult() ? Math.min(a, b.from) : a, 1e8), create: createTooltip, above: conf.aboveCursor, }, prev ? prev.timestamp : Date.now(), selected, false); } map(changes) { return new CompletionDialog(this.options, this.attrs, Object.assign(Object.assign({}, this.tooltip), { pos: changes.mapPos(this.tooltip.pos) }), this.timestamp, this.selected, this.disabled); } } class CompletionState { constructor(active, id, open) { this.active = active; this.id = id; this.open = open; } static start() { return new CompletionState(none, "cm-ac-" + Math.floor(Math.random() * 2e6).toString(36), null); } update(tr) { let { state } = tr, conf = state.facet(completionConfig); let sources = conf.override || state.languageDataAt("autocomplete", cur(state)).map(asSource); let active = sources.map(source => { let value = this.active.find(s => s.source == source) || new ActiveSource(source, this.active.some(a => a.state != 0 /* State.Inactive */) ? 1 /* State.Pending */ : 0 /* State.Inactive */); return value.update(tr, conf); }); if (active.length == this.active.length && active.every((a, i) => a == this.active[i])) active = this.active; let open = this.open; if (open && tr.docChanged) open = open.map(tr.changes); if (tr.selection || active.some(a => a.hasResult() && tr.changes.touchesRange(a.from, a.to)) || !sameResults(active, this.active)) open = CompletionDialog.build(active, state, this.id, open, conf); else if (open && open.disabled && !active.some(a => a.state == 1 /* State.Pending */)) open = null; if (!open && active.every(a => a.state != 1 /* State.Pending */) && active.some(a => a.hasResult())) active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /* State.Inactive */) : a); for (let effect of tr.effects) if (effect.is(setSelectedEffect)) open = open && open.setSelected(effect.value, this.id); return active == this.active && open == this.open ? this : new CompletionState(active, this.id, open); } get tooltip() { return this.open ? this.open.tooltip : null; } get attrs() { return this.open ? this.open.attrs : baseAttrs; } } function sameResults(a, b) { if (a == b) return true; for (let iA = 0, iB = 0;;) { while (iA < a.length && !a[iA].hasResult) iA++; while (iB < b.length && !b[iB].hasResult) iB++; let endA = iA == a.length, endB = iB == b.length; if (endA || endB) return endA == endB; if (a[iA++].result != b[iB++].result) return false; } } const baseAttrs = { "aria-autocomplete": "list" }; function makeAttrs(id, selected) { let result = { "aria-autocomplete": "list", "aria-haspopup": "listbox", "aria-controls": id }; if (selected > -1) result["aria-activedescendant"] = id + "-" + selected; return result; } const none = []; function getUserEvent(tr, conf) { if (tr.isUserEvent("input.complete")) { let completion = tr.annotation(pickedCompletion); if (completion && conf.activateOnCompletion(completion)) return "input"; } return tr.isUserEvent("input.type") ? "input" : tr.isUserEvent("delete.backward") ? "delete" : null; } class ActiveSource { constructor(source, state, explicitPos = -1) { this.source = source; this.state = state; this.explicitPos = explicitPos; } hasResult() { return false; } update(tr, conf) { let event = getUserEvent(tr, conf), value = this; if (event) value = value.handleUserEvent(tr, event, conf); else if (tr.docChanged) value = value.handleChange(tr); else if (tr.selection && value.state != 0 /* State.Inactive */) value = new ActiveSource(value.source, 0 /* State.Inactive */); for (let effect of tr.effects) { if (effect.is(startCompletionEffect)) value = new ActiveSource(value.source, 1 /* State.Pending */, effect.value ? cur(tr.state) : -1); else if (effect.is(closeCompletionEffect)) value = new ActiveSource(value.source, 0 /* State.Inactive */); else if (effect.is(setActiveEffect)) for (let active of effect.value) if (active.source == value.source) value = active; } return value; } handleUserEvent(tr, type, conf) { return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* State.Pending */); } handleChange(tr) { return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes); } map(changes) { return changes.empty || this.explicitPos < 0 ? this : new ActiveSource(this.source, this.state, changes.mapPos(this.explicitPos)); } } class ActiveResult extends ActiveSource { constructor(source, explicitPos, result, from, to) { super(source, 2 /* State.Result */, explicitPos); this.result = result; this.from = from; this.to = to; } hasResult() { return true; } handleUserEvent(tr, type, conf) { var _a; let result = this.result; if (result.map && !tr.changes.empty) result = result.map(result, tr.changes); let from = tr.changes.mapPos(this.from), to = tr.changes.mapPos(this.to, 1); let pos = cur(tr.state); if ((this.explicitPos < 0 ? pos <= from : pos < this.from) || pos > to || !result || type == "delete" && cur(tr.startState) == this.from) return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* State.Pending */ : 0 /* State.Inactive */); let explicitPos = this.explicitPos < 0 ? -1 : tr.changes.mapPos(this.explicitPos); if (checkValid(result.validFor, tr.state, from, to)) return new ActiveResult(this.source, explicitPos, result, from, to); if (result.update && (result = result.update(result, from, to, new CompletionContext(tr.state, pos, explicitPos >= 0)))) return new ActiveResult(this.source, explicitPos, result, result.from, (_a = result.to) !== null && _a !== void 0 ? _a : cur(tr.state)); return new ActiveSource(this.source, 1 /* State.Pending */, explicitPos); } handleChange(tr) { return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes); } map(mapping) { if (mapping.empty) return this; let result = this.result.map ? this.result.map(this.result, mapping) : this.result; if (!result) return new ActiveSource(this.source, 0 /* State.Inactive */); return new ActiveResult(this.source, this.explicitPos < 0 ? -1 : mapping.mapPos(this.explicitPos), this.result, mapping.mapPos(this.from), mapping.mapPos(this.to, 1)); } } function checkValid(validFor, state, from, to) { if (!validFor) return false; let text = state.sliceDoc(from, to); return typeof validFor == "function" ? validFor(text, from, to, state) : ensureAnchor(validFor, true).test(text); } const setActiveEffect = /*@__PURE__*/state_.StateEffect.define({ map(sources, mapping) { return sources.map(s => s.map(mapping)); } }); const setSelectedEffect = /*@__PURE__*/state_.StateEffect.define(); const completionState = /*@__PURE__*/state_.StateField.define({ create() { return CompletionState.start(); }, update(value, tr) { return value.update(tr); }, provide: f => [ view_.showTooltip.from(f, val => val.tooltip), view_.EditorView.contentAttributes.from(f, state => state.attrs) ] }); function applyCompletion(view, option) { const apply = option.completion.apply || option.completion.label; let result = view.state.field(completionState).active.find(a => a.source == option.source); if (!(result instanceof ActiveResult)) return false; if (typeof apply == "string") view.dispatch(Object.assign(Object.assign({}, insertCompletionText(view.state, apply, result.from, result.to)), { annotations: pickedCompletion.of(option.completion) })); else apply(view, option.completion, result.from, result.to); return true; } const createTooltip = /*@__PURE__*/completionTooltip(completionState, applyCompletion); /** Returns a command that moves the completion selection forward or backward by the given amount. */ function moveCompletionSelection(forward, by = "option") { return (view) => { let cState = view.state.field(completionState, false); if (!cState || !cState.open || cState.open.disabled || Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay) return false; let step = 1, tooltip; if (by == "page" && (tooltip = (0,view_.getTooltip)(view, cState.open.tooltip))) step = Math.max(2, Math.floor(tooltip.dom.offsetHeight / tooltip.dom.querySelector("li").offsetHeight) - 1); let { length } = cState.open.options; let selected = cState.open.selected > -1 ? cState.open.selected + step * (forward ? 1 : -1) : forward ? 0 : length - 1; if (selected < 0) selected = by == "page" ? 0 : length - 1; else if (selected >= length) selected = by == "page" ? length - 1 : 0; view.dispatch({ effects: setSelectedEffect.of(selected) }); return true; }; } /** Accept the current completion. */ const acceptCompletion = (view) => { let cState = view.state.field(completionState, false); if (view.state.readOnly || !cState || !cState.open || cState.open.selected < 0 || cState.open.disabled || Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay) return false; return applyCompletion(view, cState.open.options[cState.open.selected]); }; /** Explicitly start autocompletion. */ const startCompletion = (view) => { let cState = view.state.field(completionState, false); if (!cState) return false; view.dispatch({ effects: startCompletionEffect.of(true) }); return true; }; /** Close the currently active completion. */ const closeCompletion = (view) => { let cState = view.state.field(completionState, false); if (!cState || !cState.active.some(a => a.state != 0 /* State.Inactive */)) return false; view.dispatch({ effects: closeCompletionEffect.of(null) }); return true; }; class RunningQuery { constructor(active, context) { this.active = active; this.context = context; this.time = Date.now(); this.updates = []; // Note that 'undefined' means 'not done yet', whereas 'null' means // 'query returned null'. this.done = undefined; } } const MaxUpdateCount = 50, MinAbortTime = 1000; const completionPlugin = /*@__PURE__*/view_.ViewPlugin.fromClass(class { constructor(view) { this.view = view; this.debounceUpdate = -1; this.running = []; this.debounceAccept = -1; this.pendingStart = false; this.composing = 0 /* CompositionState.None */; for (let active of view.state.field(completionState).active) if (active.state == 1 /* State.Pending */) this.startQuery(active); } update(update) { let cState = update.state.field(completionState); let conf = update.state.facet(completionConfig); if (!update.selectionSet && !update.docChanged && update.startState.field(completionState) == cState) return; let doesReset = update.transactions.some(tr => { return (tr.selection || tr.docChanged) && !getUserEvent(tr, conf); }); for (let i = 0; i < this.running.length; i++) { let query = this.running[i]; if (doesReset || query.updates.length + update.transactions.length > MaxUpdateCount && Date.now() - query.time > MinAbortTime) { for (let handler of query.context.abortListeners) { try { handler(); } catch (e) { (0,view_.logException)(this.view.state, e); } } query.context.abortListeners = null; this.running.splice(i--, 1); } else { query.updates.push(...update.transactions); } } if (this.debounceUpdate > -1) clearTimeout(this.debounceUpdate); if (update.transactions.some(tr => tr.effects.some(e => e.is(startCompletionEffect)))) this.pendingStart = true; let delay = this.pendingStart ? 50 : conf.activateOnTypingDelay; this.debounceUpdate = cState.active.some(a => a.state == 1 /* State.Pending */ && !this.running.some(q => q.active.source == a.source)) ? setTimeout(() => this.startUpdate(), delay) : -1; if (this.composing != 0 /* CompositionState.None */) for (let tr of update.transactions) { if (getUserEvent(tr, conf) == "input") this.composing = 2 /* CompositionState.Changed */; else if (this.composing == 2 /* CompositionState.Changed */ && tr.selection) this.composing = 3 /* CompositionState.ChangedAndMoved */; } } startUpdate() { this.debounceUpdate = -1; this.pendingStart = false; let { state } = this.view, cState = state.field(completionState); for (let active of cState.active) { if (active.state == 1 /* State.Pending */ && !this.running.some(r => r.active.source == active.source)) this.startQuery(active); } } startQuery(active) { let { state } = this.view, pos = cur(state); let context = new CompletionContext(state, pos, active.explicitPos == pos); let pending = new RunningQuery(active, context); this.running.push(pending); Promise.resolve(active.source(context)).then(result => { if (!pending.context.aborted) { pending.done = result || null; this.scheduleAccept(); } }, err => { this.view.dispatch({ effects: closeCompletionEffect.of(null) }); (0,view_.logException)(this.view.state, err); }); } scheduleAccept() { if (this.running.every(q => q.done !== undefined)) this.accept(); else if (this.debounceAccept < 0) this.debounceAccept = setTimeout(() => this.accept(), this.view.state.facet(completionConfig).updateSyncTime); } // For each finished query in this.running, try to create a result // or, if appropriate, restart the query. accept() { var _a; if (this.debounceAccept > -1) clearTimeout(this.debounceAccept); this.debounceAccept = -1; let updated = []; let conf = this.view.state.facet(completionConfig); for (let i = 0; i < this.running.length; i++) { let query = this.running[i]; if (query.done === undefined) continue; this.running.splice(i--, 1); if (query.done) { let active = new ActiveResult(query.active.source, query.active.explicitPos, query.done, query.done.from, (_a = query.done.to) !== null && _a !== void 0 ? _a : cur(query.updates.length ? query.updates[0].startState : this.view.state)); // Replay the transactions that happened since the start of // the request and see if that preserves the result for (let tr of query.updates) active = active.update(tr, conf); if (active.hasResult()) { updated.push(active); continue; } } let current = this.view.state.field(completionState).active.find(a => a.source == query.active.source); if (current && current.state == 1 /* State.Pending */) { if (query.done == null) { // Explicitly failed. Should clear the pending status if it // hasn't been re-set in the meantime. let active = new ActiveSource(query.active.source, 0 /* State.Inactive */); for (let tr of query.updates) active = active.update(tr, conf); if (active.state != 1 /* State.Pending */) updated.push(active); } else { // Cleared by subsequent transactions. Restart. this.startQuery(current); } } } if (updated.length) this.view.dispatch({ effects: setActiveEffect.of(updated) }); } }, { eventHandlers: { blur(event) { let state = this.view.state.field(completionState, false); if (state && state.tooltip && this.view.state.facet(completionConfig).closeOnBlur) { let dialog = state.open && (0,view_.getTooltip)(this.view, state.open.tooltip); if (!dialog || !dialog.dom.contains(event.relatedTarget)) setTimeout(() => this.view.dispatch({ effects: closeCompletionEffect.of(null) }), 10); } }, compositionstart() { this.composing = 1 /* CompositionState.Started */; }, compositionend() { if (this.composing == 3 /* CompositionState.ChangedAndMoved */) { // Safari fires compositionend events synchronously, possibly // from inside an update, so dispatch asynchronously to avoid reentrancy setTimeout(() => this.view.dispatch({ effects: startCompletionEffect.of(false) }), 20); } this.composing = 0 /* CompositionState.None */; } } }); const windows = typeof navigator == "object" && /*@__PURE__*//Win/.test(navigator.platform); const commitCharacters = /*@__PURE__*/state_.Prec.highest(/*@__PURE__*/view_.EditorView.domEventHandlers({ keydown(event, view) { let field = view.state.field(completionState, false); if (!field || !field.open || field.open.disabled || field.open.selected < 0 || event.key.length > 1 || event.ctrlKey && !(windows && event.altKey) || event.metaKey) return false; let option = field.open.options[field.open.selected]; let result = field.active.find(a => a.source == option.source); let commitChars = option.completion.commitCharacters || result.result.commitCharacters; if (commitChars && commitChars.indexOf(event.key) > -1) applyCompletion(view, option); return false; } })); const dist_baseTheme = /*@__PURE__*/view_.EditorView.baseTheme({ ".cm-tooltip.cm-tooltip-autocomplete": { "& > ul": { fontFamily: "monospace", whiteSpace: "nowrap", overflow: "hidden auto", maxWidth_fallback: "700px", maxWidth: "min(700px, 95vw)", minWidth: "250px", maxHeight: "10em", height: "100%", listStyle: "none", margin: 0, padding: 0, "& > li, & > completion-section": { padding: "1px 3px", lineHeight: 1.2 }, "& > li": { overflowX: "hidden", textOverflow: "ellipsis", cursor: "pointer" }, "& > completion-section": { display: "list-item", borderBottom: "1px solid silver", paddingLeft: "0.5em", opacity: 0.7 } } }, "&light .cm-tooltip-autocomplete ul li[aria-selected]": { background: "#17c", color: "white", }, "&light .cm-tooltip-autocomplete-disabled ul li[aria-selected]": { background: "#777", }, "&dark .cm-tooltip-autocomplete ul li[aria-selected]": { background: "#347", color: "white", }, "&dark .cm-tooltip-autocomplete-disabled ul li[aria-selected]": { background: "#444", }, ".cm-completionListIncompleteTop:before, .cm-completionListIncompleteBottom:after": { content: '"···"', opacity: 0.5, display: "block", textAlign: "center" }, ".cm-tooltip.cm-completionInfo": { position: "absolute", padding: "3px 9px", width: "max-content", maxWidth: `${400 /* Info.Width */}px`, boxSizing: "border-box" }, ".cm-completionInfo.cm-completionInfo-left": { right: "100%" }, ".cm-completionInfo.cm-completionInfo-right": { left: "100%" }, ".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30 /* Info.Margin */}px` }, ".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30 /* Info.Margin */}px` }, "&light .cm-snippetField": { backgroundColor: "#00000022" }, "&dark .cm-snippetField": { backgroundColor: "#ffffff22" }, ".cm-snippetFieldPosition": { verticalAlign: "text-top", width: 0, height: "1.15em", display: "inline-block", margin: "0 -0.7px -.7em", borderLeft: "1.4px dotted #888" }, ".cm-completionMatchedText": { textDecoration: "underline" }, ".cm-completionDetail": { marginLeft: "0.5em", fontStyle: "italic" }, ".cm-completionIcon": { fontSize: "90%", width: ".8em", display: "inline-block", textAlign: "center", paddingRight: ".6em", opacity: "0.6", boxSizing: "content-box" }, ".cm-completionIcon-function, .cm-completionIcon-method": { "&:after": { content: "'ƒ'" } }, ".cm-completionIcon-class": { "&:after": { content: "'○'" } }, ".cm-completionIcon-interface": { "&:after": { content: "'◌'" } }, ".cm-completionIcon-variable": { "&:after": { content: "'𝑥'" } }, ".cm-completionIcon-constant": { "&:after": { content: "'𝐶'" } }, ".cm-completionIcon-type": { "&:after": { content: "'𝑡'" } }, ".cm-completionIcon-enum": { "&:after": { content: "'∪'" } }, ".cm-completionIcon-property": { "&:after": { content: "'□'" } }, ".cm-completionIcon-keyword": { "&:after": { content: "'🔑\uFE0E'" } // Disable emoji rendering }, ".cm-completionIcon-namespace": { "&:after": { content: "'▢'" } }, ".cm-completionIcon-text": { "&:after": { content: "'abc'", fontSize: "50%", verticalAlign: "middle" } } }); class FieldPos { constructor(field, line, from, to) { this.field = field; this.line = line; this.from = from; this.to = to; } } class FieldRange { constructor(field, from, to) { this.field = field; this.from = from; this.to = to; } map(changes) { let from = changes.mapPos(this.from, -1, MapMode.TrackDel); let to = changes.mapPos(this.to, 1, MapMode.TrackDel); return from == null || to == null ? null : new FieldRange(this.field, from, to); } } class Snippet { constructor(lines, fieldPositions) { this.lines = lines; this.fieldPositions = fieldPositions; } instantiate(state, pos) { let text = [], lineStart = [pos]; let lineObj = state.doc.lineAt(pos), baseIndent = /^\s*/.exec(lineObj.text)[0]; for (let line of this.lines) { if (text.length) { let indent = baseIndent, tabs = /^\t*/.exec(line)[0].length; for (let i = 0; i < tabs; i++) indent += state.facet(indentUnit); lineStart.push(pos + indent.length - tabs); line = indent + line.slice(tabs); } text.push(line); pos += line.length + 1; } let ranges = this.fieldPositions.map(pos => new FieldRange(pos.field, lineStart[pos.line] + pos.from, lineStart[pos.line] + pos.to)); return { text, ranges }; } static parse(template) { let fields = []; let lines = [], positions = [], m; for (let line of template.split(/\r\n?|\n/)) { while (m = /[#$]\{(?:(\d+)(?::([^}]*))?|((?:\\[{}]|[^}])*))\}/.exec(line)) { let seq = m[1] ? +m[1] : null, rawName = m[2] || m[3] || "", found = -1; let name = rawName.replace(/\\[{}]/g, m => m[1]); for (let i = 0; i < fields.length; i++) { if (seq != null ? fields[i].seq == seq : name ? fields[i].name == name : false) found = i; } if (found < 0) { let i = 0; while (i < fields.length && (seq == null || (fields[i].seq != null && fields[i].seq < seq))) i++; fields.splice(i, 0, { seq, name }); found = i; for (let pos of positions) if (pos.field >= found) pos.field++; } positions.push(new FieldPos(found, lines.length, m.index, m.index + name.length)); line = line.slice(0, m.index) + rawName + line.slice(m.index + m[0].length); } line = line.replace(/\\([{}])/g, (_, brace, index) => { for (let pos of positions) if (pos.line == lines.length && pos.from > index) { pos.from--; pos.to--; } return brace; }); lines.push(line); } return new Snippet(lines, positions); } } let fieldMarker = /*@__PURE__*/view_.Decoration.widget({ widget: /*@__PURE__*/new class extends view_.WidgetType { toDOM() { let span = document.createElement("span"); span.className = "cm-snippetFieldPosition"; return span; } ignoreEvent() { return false; } } }); let fieldRange = /*@__PURE__*/view_.Decoration.mark({ class: "cm-snippetField" }); class ActiveSnippet { constructor(ranges, active) { this.ranges = ranges; this.active = active; this.deco = view_.Decoration.set(ranges.map(r => (r.from == r.to ? fieldMarker : fieldRange).range(r.from, r.to))); } map(changes) { let ranges = []; for (let r of this.ranges) { let mapped = r.map(changes); if (!mapped) return null; ranges.push(mapped); } return new ActiveSnippet(ranges, this.active); } selectionInsideField(sel) { return sel.ranges.every(range => this.ranges.some(r => r.field == this.active && r.from <= range.from && r.to >= range.to)); } } const setActive = /*@__PURE__*/state_.StateEffect.define({ map(value, changes) { return value && value.map(changes); } }); const moveToField = /*@__PURE__*/state_.StateEffect.define(); const snippetState = /*@__PURE__*/state_.StateField.define({ create() { return null; }, update(value, tr) { for (let effect of tr.effects) { if (effect.is(setActive)) return effect.value; if (effect.is(moveToField) && value) return new ActiveSnippet(value.ranges, effect.value); } if (value && tr.docChanged) value = value.map(tr.changes); if (value && tr.selection && !value.selectionInsideField(tr.selection)) value = null; return value; }, provide: f => view_.EditorView.decorations.from(f, val => val ? val.deco : view_.Decoration.none) }); function fieldSelection(ranges, field) { return state_.EditorSelection.create(ranges.filter(r => r.field == field).map(r => state_.EditorSelection.range(r.from, r.to))); } /** Convert a snippet template to a function that can [apply](https://codemirror.net/6/docs/ref/#autocomplete.Completion.apply) it. Snippets are written using syntax like this: "for (let ${index} = 0; ${index} < ${end}; ${index}++) {\n\t${}\n}" Each `${}` placeholder (you may also use `#{}`) indicates a field that the user can fill in. Its name, if any, will be the default content for the field. When the snippet is activated by calling the returned function, the code is inserted at the given position. Newlines in the template are indented by the indentation of the start line, plus one [indent unit](https://codemirror.net/6/docs/ref/#language.indentUnit) per tab character after the newline. On activation, (all instances of) the first field are selected. The user can move between fields with Tab and Shift-Tab as long as the fields are active. Moving to the last field or moving the cursor out of the current field deactivates the fields. The order of fields defaults to textual order, but you can add numbers to placeholders (`${1}` or `${1:defaultText}`) to provide a custom order. To include a literal `{` or `}` in your template, put a backslash in front of it. This will be removed and the brace will not be interpreted as indicating a placeholder. */ function snippet(template) { let snippet = Snippet.parse(template); return (editor, completion, from, to) => { let { text, ranges } = snippet.instantiate(editor.state, from); let spec = { changes: { from, to, insert: Text.of(text) }, scrollIntoView: true, annotations: completion ? [pickedCompletion.of(completion), Transaction.userEvent.of("input.complete")] : undefined }; if (ranges.length) spec.selection = fieldSelection(ranges, 0); if (ranges.some(r => r.field > 0)) { let active = new ActiveSnippet(ranges, 0); let effects = spec.effects = [setActive.of(active)]; if (editor.state.field(snippetState, false) === undefined) effects.push(StateEffect.appendConfig.of([snippetState, addSnippetKeymap, snippetPointerHandler, dist_baseTheme])); } editor.dispatch(editor.state.update(spec)); }; } function moveField(dir) { return ({ state, dispatch }) => { let active = state.field(snippetState, false); if (!active || dir < 0 && active.active == 0) return false; let next = active.active + dir, last = dir > 0 && !active.ranges.some(r => r.field == next + dir); dispatch(state.update({ selection: fieldSelection(active.ranges, next), effects: setActive.of(last ? null : new ActiveSnippet(active.ranges, next)), scrollIntoView: true })); return true; }; } /** A command that clears the active snippet, if any. */ const clearSnippet = ({ state, dispatch }) => { let active = state.field(snippetState, false); if (!active) return false; dispatch(state.update({ effects: setActive.of(null) })); return true; }; /** Move to the next snippet field, if available. */ const nextSnippetField = /*@__PURE__*/moveField(1); /** Move to the previous snippet field, if available. */ const prevSnippetField = /*@__PURE__*/moveField(-1); /** Check if there is an active snippet with a next field for `nextSnippetField` to move to. */ function hasNextSnippetField(state) { let active = state.field(snippetState, false); return !!(active && active.ranges.some(r => r.field == active.active + 1)); } /** Returns true if there is an active snippet and a previous field for `prevSnippetField` to move to. */ function hasPrevSnippetField(state) { let active = state.field(snippetState, false); return !!(active && active.active > 0); } const defaultSnippetKeymap = [ { key: "Tab", run: nextSnippetField, shift: prevSnippetField }, { key: "Escape", run: clearSnippet } ]; /** A facet that can be used to configure the key bindings used by snippets. The default binds Tab to [`nextSnippetField`](https://codemirror.net/6/docs/ref/#autocomplete.nextSnippetField), Shift-Tab to [`prevSnippetField`](https://codemirror.net/6/docs/ref/#autocomplete.prevSnippetField), and Escape to [`clearSnippet`](https://codemirror.net/6/docs/ref/#autocomplete.clearSnippet). */ const snippetKeymap = /*@__PURE__*/state_.Facet.define({ combine(maps) { return maps.length ? maps[0] : defaultSnippetKeymap; } }); const addSnippetKeymap = /*@__PURE__*/state_.Prec.highest(/*@__PURE__*/view_.keymap.compute([snippetKeymap], state => state.facet(snippetKeymap))); /** Create a completion from a snippet. Returns an object with the properties from `completion`, plus an `apply` function that applies the snippet. */ function snippetCompletion(template, completion) { return Object.assign(Object.assign({}, completion), { apply: snippet(template) }); } const snippetPointerHandler = /*@__PURE__*/view_.EditorView.domEventHandlers({ mousedown(event, view) { let active = view.state.field(snippetState, false), pos; if (!active || (pos = view.posAtCoords({ x: event.clientX, y: event.clientY })) == null) return false; let match = active.ranges.find(r => r.from <= pos && r.to >= pos); if (!match || match.field == active.active) return false; view.dispatch({ selection: fieldSelection(active.ranges, match.field), effects: setActive.of(active.ranges.some(r => r.field > match.field) ? new ActiveSnippet(active.ranges, match.field) : null), scrollIntoView: true }); return true; } }); function wordRE(wordChars) { let escaped = wordChars.replace(/[\]\-\\]/g, "\\$&"); try { return new RegExp(`[\\p{Alphabetic}\\p{Number}_${escaped}]+`, "ug"); } catch (_a) { return new RegExp(`[\w${escaped}]`, "g"); } } function mapRE(re, f) { return new RegExp(f(re.source), re.unicode ? "u" : ""); } const wordCaches = /*@__PURE__*/(/* unused pure expression or super */ null && (Object.create(null))); function wordCache(wordChars) { return wordCaches[wordChars] || (wordCaches[wordChars] = new WeakMap); } function storeWords(doc, wordRE, result, seen, ignoreAt) { for (let lines = doc.iterLines(), pos = 0; !lines.next().done;) { let { value } = lines, m; wordRE.lastIndex = 0; while (m = wordRE.exec(value)) { if (!seen[m[0]] && pos + m.index != ignoreAt) { result.push({ type: "text", label: m[0] }); seen[m[0]] = true; if (result.length >= 2000 /* C.MaxList */) return; } } pos += value.length + 1; } } function collectWords(doc, cache, wordRE, to, ignoreAt) { let big = doc.length >= 1000 /* C.MinCacheLen */; let cached = big && cache.get(doc); if (cached) return cached; let result = [], seen = Object.create(null); if (doc.children) { let pos = 0; for (let ch of doc.children) { if (ch.length >= 1000 /* C.MinCacheLen */) { for (let c of collectWords(ch, cache, wordRE, to - pos, ignoreAt - pos)) { if (!seen[c.label]) { seen[c.label] = true; result.push(c); } } } else { storeWords(ch, wordRE, result, seen, ignoreAt - pos); } pos += ch.length + 1; } } else { storeWords(doc, wordRE, result, seen, ignoreAt); } if (big && result.length < 2000 /* C.MaxList */) cache.set(doc, result); return result; } /** A completion source that will scan the document for words (using a [character categorizer](https://codemirror.net/6/docs/ref/#state.EditorState.charCategorizer)), and return those as completions. */ const completeAnyWord = context => { let wordChars = context.state.languageDataAt("wordChars", context.pos).join(""); let re = wordRE(wordChars); let token = context.matchBefore(mapRE(re, s => s + "$")); if (!token && !context.explicit) return null; let from = token ? token.from : context.pos; let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /* C.Range */, from); return { from, options, validFor: mapRE(re, s => "^" + s) }; }; const defaults = { brackets: ["(", "[", "{", "'", '"'], before: ")]}:;>", stringPrefixes: [] }; const closeBracketEffect = /*@__PURE__*/state_.StateEffect.define({ map(value, mapping) { let mapped = mapping.mapPos(value, -1, state_.MapMode.TrackAfter); return mapped == null ? undefined : mapped; } }); const closedBracket = /*@__PURE__*/new class extends state_.RangeValue { }; closedBracket.startSide = 1; closedBracket.endSide = -1; const bracketState = /*@__PURE__*/state_.StateField.define({ create() { return state_.RangeSet.empty; }, update(value, tr) { value = value.map(tr.changes); if (tr.selection) { let line = tr.state.doc.lineAt(tr.selection.main.head); value = value.update({ filter: from => from >= line.from && from <= line.to }); } for (let effect of tr.effects) if (effect.is(closeBracketEffect)) value = value.update({ add: [closedBracket.range(effect.value, effect.value + 1)] }); return value; } }); /** Extension to enable bracket-closing behavior. When a closeable bracket is typed, its closing bracket is immediately inserted after the cursor. When closing a bracket directly in front of a closing bracket inserted by the extension, the cursor moves over that bracket. */ function closeBrackets() { return [inputHandler, bracketState]; } const definedClosing = "()[]{}<>"; function closing(ch) { for (let i = 0; i < definedClosing.length; i += 2) if (definedClosing.charCodeAt(i) == ch) return definedClosing.charAt(i + 1); return (0,state_.fromCodePoint)(ch < 128 ? ch : ch + 1); } function config(state, pos) { return state.languageDataAt("closeBrackets", pos)[0] || defaults; } const android = typeof navigator == "object" && /*@__PURE__*//Android\b/.test(navigator.userAgent); const inputHandler = /*@__PURE__*/view_.EditorView.inputHandler.of((view, from, to, insert) => { if ((android ? view.composing : view.compositionStarted) || view.state.readOnly) return false; let sel = view.state.selection.main; if (insert.length > 2 || insert.length == 2 && (0,state_.codePointSize)((0,state_.codePointAt)(insert, 0)) == 1 || from != sel.from || to != sel.to) return false; let tr = insertBracket(view.state, insert); if (!tr) return false; view.dispatch(tr); return true; }); /** Command that implements deleting a pair of matching brackets when the cursor is between them. */ const deleteBracketPair = ({ state, dispatch }) => { if (state.readOnly) return false; let conf = config(state, state.selection.main.head); let tokens = conf.brackets || defaults.brackets; let dont = null, changes = state.changeByRange(range => { if (range.empty) { let before = prevChar(state.doc, range.head); for (let token of tokens) { if (token == before && nextChar(state.doc, range.head) == closing((0,state_.codePointAt)(token, 0))) return { changes: { from: range.head - token.length, to: range.head + token.length }, range: state_.EditorSelection.cursor(range.head - token.length) }; } } return { range: dont = range }; }); if (!dont) dispatch(state.update(changes, { scrollIntoView: true, userEvent: "delete.backward" })); return !dont; }; /** Close-brackets related key bindings. Binds Backspace to [`deleteBracketPair`](https://codemirror.net/6/docs/ref/#autocomplete.deleteBracketPair). */ const closeBracketsKeymap = [ { key: "Backspace", run: deleteBracketPair } ]; /** Implements the extension's behavior on text insertion. If the given string counts as a bracket in the language around the selection, and replacing the selection with it requires custom behavior (inserting a closing version or skipping past a previously-closed bracket), this function returns a transaction representing that custom behavior. (You only need this if you want to programmatically insert brackets—the [`closeBrackets`](https://codemirror.net/6/docs/ref/#autocomplete.closeBrackets) extension will take care of running this for user input.) */ function insertBracket(state, bracket) { let conf = config(state, state.selection.main.head); let tokens = conf.brackets || defaults.brackets; for (let tok of tokens) { let closed = closing((0,state_.codePointAt)(tok, 0)); if (bracket == tok) return closed == tok ? handleSame(state, tok, tokens.indexOf(tok + tok + tok) > -1, conf) : handleOpen(state, tok, closed, conf.before || defaults.before); if (bracket == closed && closedBracketAt(state, state.selection.main.from)) return handleClose(state, tok, closed); } return null; } function closedBracketAt(state, pos) { let found = false; state.field(bracketState).between(0, state.doc.length, from => { if (from == pos) found = true; }); return found; } function nextChar(doc, pos) { let next = doc.sliceString(pos, pos + 2); return next.slice(0, (0,state_.codePointSize)((0,state_.codePointAt)(next, 0))); } function prevChar(doc, pos) { let prev = doc.sliceString(pos - 2, pos); return (0,state_.codePointSize)((0,state_.codePointAt)(prev, 0)) == prev.length ? prev : prev.slice(1); } function handleOpen(state, open, close, closeBefore) { let dont = null, changes = state.changeByRange(range => { if (!range.empty) return { changes: [{ insert: open, from: range.from }, { insert: close, from: range.to }], effects: closeBracketEffect.of(range.to + open.length), range: state_.EditorSelection.range(range.anchor + open.length, range.head + open.length) }; let next = nextChar(state.doc, range.head); if (!next || /\s/.test(next) || closeBefore.indexOf(next) > -1) return { changes: { insert: open + close, from: range.head }, effects: closeBracketEffect.of(range.head + open.length), range: state_.EditorSelection.cursor(range.head + open.length) }; return { range: dont = range }; }); return dont ? null : state.update(changes, { scrollIntoView: true, userEvent: "input.type" }); } function handleClose(state, _open, close) { let dont = null, changes = state.changeByRange(range => { if (range.empty && nextChar(state.doc, range.head) == close) return { changes: { from: range.head, to: range.head + close.length, insert: close }, range: state_.EditorSelection.cursor(range.head + close.length) }; return dont = { range }; }); return dont ? null : state.update(changes, { scrollIntoView: true, userEvent: "input.type" }); } // Handles cases where the open and close token are the same, and // possibly triple quotes (as in `"""abc"""`-style quoting). function handleSame(state, token, allowTriple, config) { let stringPrefixes = config.stringPrefixes || defaults.stringPrefixes; let dont = null, changes = state.changeByRange(range => { if (!range.empty) return { changes: [{ insert: token, from: range.from }, { insert: token, from: range.to }], effects: closeBracketEffect.of(range.to + token.length), range: state_.EditorSelection.range(range.anchor + token.length, range.head + token.length) }; let pos = range.head, next = nextChar(state.doc, pos), start; if (next == token) { if (nodeStart(state, pos)) { return { changes: { insert: token + token, from: pos }, effects: closeBracketEffect.of(pos + token.length), range: state_.EditorSelection.cursor(pos + token.length) }; } else if (closedBracketAt(state, pos)) { let isTriple = allowTriple && state.sliceDoc(pos, pos + token.length * 3) == token + token + token; let content = isTriple ? token + token + token : token; return { changes: { from: pos, to: pos + content.length, insert: content }, range: state_.EditorSelection.cursor(pos + content.length) }; } } else if (allowTriple && state.sliceDoc(pos - 2 * token.length, pos) == token + token && (start = canStartStringAt(state, pos - 2 * token.length, stringPrefixes)) > -1 && nodeStart(state, start)) { return { changes: { insert: token + token + token + token, from: pos }, effects: closeBracketEffect.of(pos + token.length), range: state_.EditorSelection.cursor(pos + token.length) }; } else if (state.charCategorizer(pos)(next) != state_.CharCategory.Word) { if (canStartStringAt(state, pos, stringPrefixes) > -1 && !probablyInString(state, pos, token, stringPrefixes)) return { changes: { insert: token + token, from: pos }, effects: closeBracketEffect.of(pos + token.length), range: state_.EditorSelection.cursor(pos + token.length) }; } return { range: dont = range }; }); return dont ? null : state.update(changes, { scrollIntoView: true, userEvent: "input.type" }); } function nodeStart(state, pos) { let tree = (0,language_dist/* syntaxTree */.mv)(state).resolveInner(pos + 1); return tree.parent && tree.from == pos; } function probablyInString(state, pos, quoteToken, prefixes) { let node = (0,language_dist/* syntaxTree */.mv)(state).resolveInner(pos, -1); let maxPrefix = prefixes.reduce((m, p) => Math.max(m, p.length), 0); for (let i = 0; i < 5; i++) { let start = state.sliceDoc(node.from, Math.min(node.to, node.from + quoteToken.length + maxPrefix)); let quotePos = start.indexOf(quoteToken); if (!quotePos || quotePos > -1 && prefixes.indexOf(start.slice(0, quotePos)) > -1) { let first = node.firstChild; while (first && first.from == node.from && first.to - first.from > quoteToken.length + quotePos) { if (state.sliceDoc(first.to - quoteToken.length, first.to) == quoteToken) return false; first = first.firstChild; } return true; } let parent = node.to == pos && node.parent; if (!parent) break; node = parent; } return false; } function canStartStringAt(state, pos, prefixes) { let charCat = state.charCategorizer(pos); if (charCat(state.sliceDoc(pos - 1, pos)) != state_.CharCategory.Word) return pos; for (let prefix of prefixes) { let start = pos - prefix.length; if (state.sliceDoc(start, pos) == prefix && charCat(state.sliceDoc(start - 1, start)) != state_.CharCategory.Word) return start; } return -1; } /** Returns an extension that enables autocompletion. */ function autocompletion(config = {}) { return [ commitCharacters, completionState, completionConfig.of(config), completionPlugin, completionKeymapExt, dist_baseTheme ]; } /** Basic keybindings for autocompletion. - Ctrl-Space: [`startCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.startCompletion) - Escape: [`closeCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.closeCompletion) - ArrowDown: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(true)` - ArrowUp: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(false)` - PageDown: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(true, "page")` - PageDown: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(true, "page")` - Enter: [`acceptCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.acceptCompletion) */ const completionKeymap = [ { key: "Ctrl-Space", run: startCompletion }, { key: "Escape", run: closeCompletion }, { key: "ArrowDown", run: /*@__PURE__*/moveCompletionSelection(true) }, { key: "ArrowUp", run: /*@__PURE__*/moveCompletionSelection(false) }, { key: "PageDown", run: /*@__PURE__*/moveCompletionSelection(true, "page") }, { key: "PageUp", run: /*@__PURE__*/moveCompletionSelection(false, "page") }, { key: "Enter", run: acceptCompletion } ]; const completionKeymapExt = /*@__PURE__*/state_.Prec.highest(/*@__PURE__*/view_.keymap.computeN([completionConfig], state => state.facet(completionConfig).defaultKeymap ? [completionKeymap] : [])); /** Get the current completion status. When completions are available, this will return `"active"`. When completions are pending (in the process of being queried), this returns `"pending"`. Otherwise, it returns `null`. */ function completionStatus(state) { let cState = state.field(completionState, false); return cState && cState.active.some(a => a.state == 1 /* State.Pending */) ? "pending" : cState && cState.active.some(a => a.state != 0 /* State.Inactive */) ? "active" : null; } const completionArrayCache = /*@__PURE__*/new WeakMap; /** Returns the available completions as an array. */ function currentCompletions(state) { var _a; let open = (_a = state.field(completionState, false)) === null || _a === void 0 ? void 0 : _a.open; if (!open || open.disabled) return []; let completions = completionArrayCache.get(open.options); if (!completions) completionArrayCache.set(open.options, completions = open.options.map(o => o.completion)); return completions; } /** Return the currently selected completion, if any. */ function selectedCompletion(state) { var _a; let open = (_a = state.field(completionState, false)) === null || _a === void 0 ? void 0 : _a.open; return open && !open.disabled && open.selected >= 0 ? open.options[open.selected].completion : null; } /** Returns the currently selected position in the active completion list, or null if no completions are active. */ function selectedCompletionIndex(state) { var _a; let open = (_a = state.field(completionState, false)) === null || _a === void 0 ? void 0 : _a.open; return open && !open.disabled && open.selected >= 0 ? open.selected : null; } /** Create an effect that can be attached to a transaction to change the currently selected completion. */ function setSelectedCompletion(index) { return setSelectedEffect.of(index); } ;// CONCATENATED MODULE: ../node_modules/@codemirror/lint/dist/index.js class SelectedDiagnostic { constructor(from, to, diagnostic) { this.from = from; this.to = to; this.diagnostic = diagnostic; } } class LintState { constructor(diagnostics, panel, selected) { this.diagnostics = diagnostics; this.panel = panel; this.selected = selected; } static init(diagnostics, panel, state) { // Filter the list of diagnostics for which to create markers let markedDiagnostics = diagnostics; let diagnosticFilter = state.facet(lintConfig).markerFilter; if (diagnosticFilter) markedDiagnostics = diagnosticFilter(markedDiagnostics, state); let ranges = view_.Decoration.set(markedDiagnostics.map((d) => { // For zero-length ranges or ranges covering only a line break, create a widget return d.from == d.to || (d.from == d.to - 1 && state.doc.lineAt(d.from).to == d.from) ? view_.Decoration.widget({ widget: new DiagnosticWidget(d), diagnostic: d }).range(d.from) : view_.Decoration.mark({ attributes: { class: "cm-lintRange cm-lintRange-" + d.severity + (d.markClass ? " " + d.markClass : "") }, diagnostic: d, inclusive: true }).range(d.from, d.to); }), true); return new LintState(ranges, panel, findDiagnostic(ranges)); } } function findDiagnostic(diagnostics, diagnostic = null, after = 0) { let found = null; diagnostics.between(after, 1e9, (from, to, { spec }) => { if (diagnostic && spec.diagnostic != diagnostic) return; found = new SelectedDiagnostic(from, to, spec.diagnostic); return false; }); return found; } function hideTooltip(tr, tooltip) { let from = tooltip.pos, to = tooltip.end || from; let result = tr.state.facet(lintConfig).hideOn(tr, from, to); if (result != null) return result; let line = tr.startState.doc.lineAt(tooltip.pos); return !!(tr.effects.some(e => e.is(setDiagnosticsEffect)) || tr.changes.touchesRange(line.from, Math.max(line.to, to))); } function maybeEnableLint(state, effects) { return state.field(lintState, false) ? effects : effects.concat(state_.StateEffect.appendConfig.of(lintExtensions)); } /** Returns a transaction spec which updates the current set of diagnostics, and enables the lint extension if if wasn't already active. */ function setDiagnostics(state, diagnostics) { return { effects: maybeEnableLint(state, [setDiagnosticsEffect.of(diagnostics)]) }; } /** The state effect that updates the set of active diagnostics. Can be useful when writing an extension that needs to track these. */ const setDiagnosticsEffect = /*@__PURE__*/state_.StateEffect.define(); const dist_togglePanel = /*@__PURE__*/state_.StateEffect.define(); const movePanelSelection = /*@__PURE__*/state_.StateEffect.define(); const lintState = /*@__PURE__*/state_.StateField.define({ create() { return new LintState(view_.Decoration.none, null, null); }, update(value, tr) { if (tr.docChanged && value.diagnostics.size) { let mapped = value.diagnostics.map(tr.changes), selected = null, panel = value.panel; if (value.selected) { let selPos = tr.changes.mapPos(value.selected.from, 1); selected = findDiagnostic(mapped, value.selected.diagnostic, selPos) || findDiagnostic(mapped, null, selPos); } if (!mapped.size && panel && tr.state.facet(lintConfig).autoPanel) panel = null; value = new LintState(mapped, panel, selected); } for (let effect of tr.effects) { if (effect.is(setDiagnosticsEffect)) { let panel = !tr.state.facet(lintConfig).autoPanel ? value.panel : effect.value.length ? LintPanel.open : null; value = LintState.init(effect.value, panel, tr.state); } else if (effect.is(dist_togglePanel)) { value = new LintState(value.diagnostics, effect.value ? LintPanel.open : null, value.selected); } else if (effect.is(movePanelSelection)) { value = new LintState(value.diagnostics, value.panel, effect.value); } } return value; }, provide: f => [view_.showPanel.from(f, val => val.panel), view_.EditorView.decorations.from(f, s => s.diagnostics)] }); /** Returns the number of active lint diagnostics in the given state. */ function diagnosticCount(state) { let lint = state.field(lintState, false); return lint ? lint.diagnostics.size : 0; } const activeMark = /*@__PURE__*/view_.Decoration.mark({ class: "cm-lintRange cm-lintRange-active", inclusive: true }); function lintTooltip(view, pos, side) { let { diagnostics } = view.state.field(lintState); let found = [], stackStart = 2e8, stackEnd = 0; diagnostics.between(pos - (side < 0 ? 1 : 0), pos + (side > 0 ? 1 : 0), (from, to, { spec }) => { if (pos >= from && pos <= to && (from == to || ((pos > from || side > 0) && (pos < to || side < 0)))) { found.push(spec.diagnostic); stackStart = Math.min(from, stackStart); stackEnd = Math.max(to, stackEnd); } }); let diagnosticFilter = view.state.facet(lintConfig).tooltipFilter; if (diagnosticFilter) found = diagnosticFilter(found, view.state); if (!found.length) return null; return { pos: stackStart, end: stackEnd, above: view.state.doc.lineAt(stackStart).to < stackEnd, create() { return { dom: diagnosticsTooltip(view, found) }; } }; } function diagnosticsTooltip(view, diagnostics) { return crelt("ul", { class: "cm-tooltip-lint" }, diagnostics.map(d => renderDiagnostic(view, d, false))); } /** Command to open and focus the lint panel. */ const openLintPanel = (view) => { let field = view.state.field(lintState, false); if (!field || !field.panel) view.dispatch({ effects: maybeEnableLint(view.state, [dist_togglePanel.of(true)]) }); let panel = (0,view_.getPanel)(view, LintPanel.open); if (panel) panel.dom.querySelector(".cm-panel-lint ul").focus(); return true; }; /** Command to close the lint panel, when open. */ const closeLintPanel = (view) => { let field = view.state.field(lintState, false); if (!field || !field.panel) return false; view.dispatch({ effects: dist_togglePanel.of(false) }); return true; }; /** Move the selection to the next diagnostic. */ const nextDiagnostic = (view) => { let field = view.state.field(lintState, false); if (!field) return false; let sel = view.state.selection.main, next = field.diagnostics.iter(sel.to + 1); if (!next.value) { next = field.diagnostics.iter(0); if (!next.value || next.from == sel.from && next.to == sel.to) return false; } view.dispatch({ selection: { anchor: next.from, head: next.to }, scrollIntoView: true }); return true; }; /** Move the selection to the previous diagnostic. */ const previousDiagnostic = (view) => { let { state } = view, field = state.field(lintState, false); if (!field) return false; let sel = state.selection.main; let prevFrom, prevTo, lastFrom, lastTo; field.diagnostics.between(0, state.doc.length, (from, to) => { if (to < sel.to && (prevFrom == null || prevFrom < from)) { prevFrom = from; prevTo = to; } if (lastFrom == null || from > lastFrom) { lastFrom = from; lastTo = to; } }); if (lastFrom == null || prevFrom == null && lastFrom == sel.from) return false; view.dispatch({ selection: { anchor: prevFrom !== null && prevFrom !== void 0 ? prevFrom : lastFrom, head: prevTo !== null && prevTo !== void 0 ? prevTo : lastTo }, scrollIntoView: true }); return true; }; /** A set of default key bindings for the lint functionality. - Ctrl-Shift-m (Cmd-Shift-m on macOS): [`openLintPanel`](https://codemirror.net/6/docs/ref/#lint.openLintPanel) - F8: [`nextDiagnostic`](https://codemirror.net/6/docs/ref/#lint.nextDiagnostic) */ const lintKeymap = [ { key: "Mod-Shift-m", run: openLintPanel, preventDefault: true }, { key: "F8", run: nextDiagnostic } ]; const lintPlugin = /*@__PURE__*/(/* unused pure expression or super */ null && (ViewPlugin.fromClass(class { constructor(view) { this.view = view; this.timeout = -1; this.set = true; let { delay } = view.state.facet(lintConfig); this.lintTime = Date.now() + delay; this.run = this.run.bind(this); this.timeout = setTimeout(this.run, delay); } run() { clearTimeout(this.timeout); let now = Date.now(); if (now < this.lintTime - 10) { this.timeout = setTimeout(this.run, this.lintTime - now); } else { this.set = false; let { state } = this.view, { sources } = state.facet(lintConfig); if (sources.length) Promise.all(sources.map(source => Promise.resolve(source(this.view)))).then(annotations => { let all = annotations.reduce((a, b) => a.concat(b)); if (this.view.state.doc == state.doc) this.view.dispatch(setDiagnostics(this.view.state, all)); }, error => { logException(this.view.state, error); }); } } update(update) { let config = update.state.facet(lintConfig); if (update.docChanged || config != update.startState.facet(lintConfig) || config.needsRefresh && config.needsRefresh(update)) { this.lintTime = Date.now() + config.delay; if (!this.set) { this.set = true; this.timeout = setTimeout(this.run, config.delay); } } } force() { if (this.set) { this.lintTime = Date.now(); this.run(); } } destroy() { clearTimeout(this.timeout); } }))); const lintConfig = /*@__PURE__*/state_.Facet.define({ combine(input) { return Object.assign({ sources: input.map(i => i.source).filter(x => x != null) }, (0,state_.combineConfig)(input.map(i => i.config), { delay: 750, markerFilter: null, tooltipFilter: null, needsRefresh: null, hideOn: () => null, }, { needsRefresh: (a, b) => !a ? b : !b ? a : u => a(u) || b(u) })); } }); /** Given a diagnostic source, this function returns an extension that enables linting with that source. It will be called whenever the editor is idle (after its content changed). If `null` is given as source, this only configures the lint extension. */ function linter(source, config = {}) { return [ lintConfig.of({ source, config }), lintPlugin, lintExtensions ]; } /** Forces any linters [configured](https://codemirror.net/6/docs/ref/#lint.linter) to run when the editor is idle to run right away. */ function forceLinting(view) { let plugin = view.plugin(lintPlugin); if (plugin) plugin.force(); } function assignKeys(actions) { let assigned = []; if (actions) actions: for (let { name } of actions) { for (let i = 0; i < name.length; i++) { let ch = name[i]; if (/[a-zA-Z]/.test(ch) && !assigned.some(c => c.toLowerCase() == ch.toLowerCase())) { assigned.push(ch); continue actions; } } assigned.push(""); } return assigned; } function renderDiagnostic(view, diagnostic, inPanel) { var _a; let keys = inPanel ? assignKeys(diagnostic.actions) : []; return crelt("li", { class: "cm-diagnostic cm-diagnostic-" + diagnostic.severity }, crelt("span", { class: "cm-diagnosticText" }, diagnostic.renderMessage ? diagnostic.renderMessage(view) : diagnostic.message), (_a = diagnostic.actions) === null || _a === void 0 ? void 0 : _a.map((action, i) => { let fired = false, click = (e) => { e.preventDefault(); if (fired) return; fired = true; let found = findDiagnostic(view.state.field(lintState).diagnostics, diagnostic); if (found) action.apply(view, found.from, found.to); }; let { name } = action, keyIndex = keys[i] ? name.indexOf(keys[i]) : -1; let nameElt = keyIndex < 0 ? name : [name.slice(0, keyIndex), crelt("u", name.slice(keyIndex, keyIndex + 1)), name.slice(keyIndex + 1)]; return crelt("button", { type: "button", class: "cm-diagnosticAction", onclick: click, onmousedown: click, "aria-label": ` Action: ${name}${keyIndex < 0 ? "" : ` (access key "${keys[i]})"`}.` }, nameElt); }), diagnostic.source && crelt("div", { class: "cm-diagnosticSource" }, diagnostic.source)); } class DiagnosticWidget extends view_.WidgetType { constructor(diagnostic) { super(); this.diagnostic = diagnostic; } eq(other) { return other.diagnostic == this.diagnostic; } toDOM() { return crelt("span", { class: "cm-lintPoint cm-lintPoint-" + this.diagnostic.severity }); } } class PanelItem { constructor(view, diagnostic) { this.diagnostic = diagnostic; this.id = "item_" + Math.floor(Math.random() * 0xffffffff).toString(16); this.dom = renderDiagnostic(view, diagnostic, true); this.dom.id = this.id; this.dom.setAttribute("role", "option"); } } class LintPanel { constructor(view) { this.view = view; this.items = []; let onkeydown = (event) => { if (event.keyCode == 27) { // Escape closeLintPanel(this.view); this.view.focus(); } else if (event.keyCode == 38 || event.keyCode == 33) { // ArrowUp, PageUp this.moveSelection((this.selectedIndex - 1 + this.items.length) % this.items.length); } else if (event.keyCode == 40 || event.keyCode == 34) { // ArrowDown, PageDown this.moveSelection((this.selectedIndex + 1) % this.items.length); } else if (event.keyCode == 36) { // Home this.moveSelection(0); } else if (event.keyCode == 35) { // End this.moveSelection(this.items.length - 1); } else if (event.keyCode == 13) { // Enter this.view.focus(); } else if (event.keyCode >= 65 && event.keyCode <= 90 && this.selectedIndex >= 0) { // A-Z let { diagnostic } = this.items[this.selectedIndex], keys = assignKeys(diagnostic.actions); for (let i = 0; i < keys.length; i++) if (keys[i].toUpperCase().charCodeAt(0) == event.keyCode) { let found = findDiagnostic(this.view.state.field(lintState).diagnostics, diagnostic); if (found) diagnostic.actions[i].apply(view, found.from, found.to); } } else { return; } event.preventDefault(); }; let onclick = (event) => { for (let i = 0; i < this.items.length; i++) { if (this.items[i].dom.contains(event.target)) this.moveSelection(i); } }; this.list = crelt("ul", { tabIndex: 0, role: "listbox", "aria-label": this.view.state.phrase("Diagnostics"), onkeydown, onclick }); this.dom = crelt("div", { class: "cm-panel-lint" }, this.list, crelt("button", { type: "button", name: "close", "aria-label": this.view.state.phrase("close"), onclick: () => closeLintPanel(this.view) }, "×")); this.update(); } get selectedIndex() { let selected = this.view.state.field(lintState).selected; if (!selected) return -1; for (let i = 0; i < this.items.length; i++) if (this.items[i].diagnostic == selected.diagnostic) return i; return -1; } update() { let { diagnostics, selected } = this.view.state.field(lintState); let i = 0, needsSync = false, newSelectedItem = null; diagnostics.between(0, this.view.state.doc.length, (_start, _end, { spec }) => { let found = -1, item; for (let j = i; j < this.items.length; j++) if (this.items[j].diagnostic == spec.diagnostic) { found = j; break; } if (found < 0) { item = new PanelItem(this.view, spec.diagnostic); this.items.splice(i, 0, item); needsSync = true; } else { item = this.items[found]; if (found > i) { this.items.splice(i, found - i); needsSync = true; } } if (selected && item.diagnostic == selected.diagnostic) { if (!item.dom.hasAttribute("aria-selected")) { item.dom.setAttribute("aria-selected", "true"); newSelectedItem = item; } } else if (item.dom.hasAttribute("aria-selected")) { item.dom.removeAttribute("aria-selected"); } i++; }); while (i < this.items.length && !(this.items.length == 1 && this.items[0].diagnostic.from < 0)) { needsSync = true; this.items.pop(); } if (this.items.length == 0) { this.items.push(new PanelItem(this.view, { from: -1, to: -1, severity: "info", message: this.view.state.phrase("No diagnostics") })); needsSync = true; } if (newSelectedItem) { this.list.setAttribute("aria-activedescendant", newSelectedItem.id); this.view.requestMeasure({ key: this, read: () => ({ sel: newSelectedItem.dom.getBoundingClientRect(), panel: this.list.getBoundingClientRect() }), write: ({ sel, panel }) => { let scaleY = panel.height / this.list.offsetHeight; if (sel.top < panel.top) this.list.scrollTop -= (panel.top - sel.top) / scaleY; else if (sel.bottom > panel.bottom) this.list.scrollTop += (sel.bottom - panel.bottom) / scaleY; } }); } else if (this.selectedIndex < 0) { this.list.removeAttribute("aria-activedescendant"); } if (needsSync) this.sync(); } sync() { let domPos = this.list.firstChild; function rm() { let prev = domPos; domPos = prev.nextSibling; prev.remove(); } for (let item of this.items) { if (item.dom.parentNode == this.list) { while (domPos != item.dom) rm(); domPos = item.dom.nextSibling; } else { this.list.insertBefore(item.dom, domPos); } } while (domPos) rm(); } moveSelection(selectedIndex) { if (this.selectedIndex < 0) return; let field = this.view.state.field(lintState); let selection = findDiagnostic(field.diagnostics, this.items[selectedIndex].diagnostic); if (!selection) return; this.view.dispatch({ selection: { anchor: selection.from, head: selection.to }, scrollIntoView: true, effects: movePanelSelection.of(selection) }); } static open(view) { return new LintPanel(view); } } function svg(content, attrs = `viewBox="0 0 40 40"`) { return `url('data:image/svg+xml,${encodeURIComponent(content)}')`; } function underline(color) { return svg(``, `width="6" height="3"`); } const lint_dist_baseTheme = /*@__PURE__*/view_.EditorView.baseTheme({ ".cm-diagnostic": { padding: "3px 6px 3px 8px", marginLeft: "-1px", display: "block", whiteSpace: "pre-wrap" }, ".cm-diagnostic-error": { borderLeft: "5px solid #d11" }, ".cm-diagnostic-warning": { borderLeft: "5px solid orange" }, ".cm-diagnostic-info": { borderLeft: "5px solid #999" }, ".cm-diagnostic-hint": { borderLeft: "5px solid #66d" }, ".cm-diagnosticAction": { font: "inherit", border: "none", padding: "2px 4px", backgroundColor: "#444", color: "white", borderRadius: "3px", marginLeft: "8px", cursor: "pointer" }, ".cm-diagnosticSource": { fontSize: "70%", opacity: .7 }, ".cm-lintRange": { backgroundPosition: "left bottom", backgroundRepeat: "repeat-x", paddingBottom: "0.7px", }, ".cm-lintRange-error": { backgroundImage: /*@__PURE__*/underline("#d11") }, ".cm-lintRange-warning": { backgroundImage: /*@__PURE__*/underline("orange") }, ".cm-lintRange-info": { backgroundImage: /*@__PURE__*/underline("#999") }, ".cm-lintRange-hint": { backgroundImage: /*@__PURE__*/underline("#66d") }, ".cm-lintRange-active": { backgroundColor: "#ffdd9980" }, ".cm-tooltip-lint": { padding: 0, margin: 0 }, ".cm-lintPoint": { position: "relative", "&:after": { content: '""', position: "absolute", bottom: 0, left: "-2px", borderLeft: "3px solid transparent", borderRight: "3px solid transparent", borderBottom: "4px solid #d11" } }, ".cm-lintPoint-warning": { "&:after": { borderBottomColor: "orange" } }, ".cm-lintPoint-info": { "&:after": { borderBottomColor: "#999" } }, ".cm-lintPoint-hint": { "&:after": { borderBottomColor: "#66d" } }, ".cm-panel.cm-panel-lint": { position: "relative", "& ul": { maxHeight: "100px", overflowY: "auto", "& [aria-selected]": { backgroundColor: "#ddd", "& u": { textDecoration: "underline" } }, "&:focus [aria-selected]": { background_fallback: "#bdf", backgroundColor: "Highlight", color_fallback: "white", color: "HighlightText" }, "& u": { textDecoration: "none" }, padding: 0, margin: 0 }, "& [name=close]": { position: "absolute", top: "0", right: "2px", background: "inherit", border: "none", font: "inherit", padding: 0, margin: 0 } } }); function severityWeight(sev) { return sev == "error" ? 4 : sev == "warning" ? 3 : sev == "info" ? 2 : 1; } class LintGutterMarker extends view_.GutterMarker { constructor(diagnostics) { super(); this.diagnostics = diagnostics; this.severity = diagnostics.reduce((max, d) => severityWeight(max) < severityWeight(d.severity) ? d.severity : max, "hint"); } toDOM(view) { let elt = document.createElement("div"); elt.className = "cm-lint-marker cm-lint-marker-" + this.severity; let diagnostics = this.diagnostics; let diagnosticsFilter = view.state.facet(lintGutterConfig).tooltipFilter; if (diagnosticsFilter) diagnostics = diagnosticsFilter(diagnostics, view.state); if (diagnostics.length) elt.onmouseover = () => gutterMarkerMouseOver(view, elt, diagnostics); return elt; } } function trackHoverOn(view, marker) { let mousemove = (event) => { let rect = marker.getBoundingClientRect(); if (event.clientX > rect.left - 10 /* Hover.Margin */ && event.clientX < rect.right + 10 /* Hover.Margin */ && event.clientY > rect.top - 10 /* Hover.Margin */ && event.clientY < rect.bottom + 10 /* Hover.Margin */) return; for (let target = event.target; target; target = target.parentNode) { if (target.nodeType == 1 && target.classList.contains("cm-tooltip-lint")) return; } window.removeEventListener("mousemove", mousemove); if (view.state.field(lintGutterTooltip)) view.dispatch({ effects: setLintGutterTooltip.of(null) }); }; window.addEventListener("mousemove", mousemove); } function gutterMarkerMouseOver(view, marker, diagnostics) { function hovered() { let line = view.elementAtHeight(marker.getBoundingClientRect().top + 5 - view.documentTop); const linePos = view.coordsAtPos(line.from); if (linePos) { view.dispatch({ effects: setLintGutterTooltip.of({ pos: line.from, above: false, create() { return { dom: diagnosticsTooltip(view, diagnostics), getCoords: () => marker.getBoundingClientRect() }; } }) }); } marker.onmouseout = marker.onmousemove = null; trackHoverOn(view, marker); } let { hoverTime } = view.state.facet(lintGutterConfig); let hoverTimeout = setTimeout(hovered, hoverTime); marker.onmouseout = () => { clearTimeout(hoverTimeout); marker.onmouseout = marker.onmousemove = null; }; marker.onmousemove = () => { clearTimeout(hoverTimeout); hoverTimeout = setTimeout(hovered, hoverTime); }; } function markersForDiagnostics(doc, diagnostics) { let byLine = Object.create(null); for (let diagnostic of diagnostics) { let line = doc.lineAt(diagnostic.from); (byLine[line.from] || (byLine[line.from] = [])).push(diagnostic); } let markers = []; for (let line in byLine) { markers.push(new LintGutterMarker(byLine[line]).range(+line)); } return state_.RangeSet.of(markers, true); } const lintGutterExtension = /*@__PURE__*/(0,view_.gutter)({ class: "cm-gutter-lint", markers: view => view.state.field(lintGutterMarkers), }); const lintGutterMarkers = /*@__PURE__*/state_.StateField.define({ create() { return state_.RangeSet.empty; }, update(markers, tr) { markers = markers.map(tr.changes); let diagnosticFilter = tr.state.facet(lintGutterConfig).markerFilter; for (let effect of tr.effects) { if (effect.is(setDiagnosticsEffect)) { let diagnostics = effect.value; if (diagnosticFilter) diagnostics = diagnosticFilter(diagnostics || [], tr.state); markers = markersForDiagnostics(tr.state.doc, diagnostics.slice(0)); } } return markers; } }); const setLintGutterTooltip = /*@__PURE__*/state_.StateEffect.define(); const lintGutterTooltip = /*@__PURE__*/state_.StateField.define({ create() { return null; }, update(tooltip, tr) { if (tooltip && tr.docChanged) tooltip = hideTooltip(tr, tooltip) ? null : Object.assign(Object.assign({}, tooltip), { pos: tr.changes.mapPos(tooltip.pos) }); return tr.effects.reduce((t, e) => e.is(setLintGutterTooltip) ? e.value : t, tooltip); }, provide: field => view_.showTooltip.from(field) }); const lintGutterTheme = /*@__PURE__*/view_.EditorView.baseTheme({ ".cm-gutter-lint": { width: "1.4em", "& .cm-gutterElement": { padding: ".2em" } }, ".cm-lint-marker": { width: "1em", height: "1em" }, ".cm-lint-marker-info": { content: /*@__PURE__*/svg(``) }, ".cm-lint-marker-warning": { content: /*@__PURE__*/svg(``), }, ".cm-lint-marker-error": { content: /*@__PURE__*/svg(``) }, }); const lintExtensions = [ lintState, /*@__PURE__*/view_.EditorView.decorations.compute([lintState], state => { let { selected, panel } = state.field(lintState); return !selected || !panel || selected.from == selected.to ? view_.Decoration.none : view_.Decoration.set([ activeMark.range(selected.from, selected.to) ]); }), /*@__PURE__*/(0,view_.hoverTooltip)(lintTooltip, { hideOn: hideTooltip }), lint_dist_baseTheme ]; const lintGutterConfig = /*@__PURE__*/state_.Facet.define({ combine(configs) { return (0,state_.combineConfig)(configs, { hoverTime: 300 /* Hover.Time */, markerFilter: null, tooltipFilter: null }); } }); /** Returns an extension that installs a gutter showing markers for each line that has diagnostics, which can be hovered over to see the diagnostics. */ function lintGutter(config = {}) { return [lintGutterConfig.of(config), lintGutterMarkers, lintGutterExtension, lintGutterTheme, lintGutterTooltip]; } /** Iterate over the marked diagnostics for the given editor state, calling `f` for each of them. Note that, if the document changed since the diagnostics were created, the `Diagnostic` object will hold the original outdated position, whereas the `to` and `from` arguments hold the diagnostic's current position. */ function forEachDiagnostic(state, f) { let lState = state.field(lintState, false); if (lState && lState.diagnostics.size) for (let iter = RangeSet.iter([lState.diagnostics]); iter.value; iter.next()) f(iter.value.spec.diagnostic, iter.from, iter.to); } ;// CONCATENATED MODULE: ../extensions/basic-setup/esm/index.js /** This is an extension value that just pulls together a number of extensions that you might want in a basic editor. It is meant as a convenient helper to quickly set up CodeMirror without installing and importing a lot of separate packages. Specifically, it includes... - [the default command bindings](https://codemirror.net/6/docs/ref/#commands.defaultKeymap) - [line numbers](https://codemirror.net/6/docs/ref/#view.lineNumbers) - [special character highlighting](https://codemirror.net/6/docs/ref/#view.highlightSpecialChars) - [the undo history](https://codemirror.net/6/docs/ref/#commands.history) - [a fold gutter](https://codemirror.net/6/docs/ref/#language.foldGutter) - [custom selection drawing](https://codemirror.net/6/docs/ref/#view.drawSelection) - [drop cursor](https://codemirror.net/6/docs/ref/#view.dropCursor) - [multiple selections](https://codemirror.net/6/docs/ref/#state.EditorState^allowMultipleSelections) - [reindentation on input](https://codemirror.net/6/docs/ref/#language.indentOnInput) - [the default highlight style](https://codemirror.net/6/docs/ref/#language.defaultHighlightStyle) (as fallback) - [bracket matching](https://codemirror.net/6/docs/ref/#language.bracketMatching) - [bracket closing](https://codemirror.net/6/docs/ref/#autocomplete.closeBrackets) - [autocompletion](https://codemirror.net/6/docs/ref/#autocomplete.autocompletion) - [rectangular selection](https://codemirror.net/6/docs/ref/#view.rectangularSelection) and [crosshair cursor](https://codemirror.net/6/docs/ref/#view.crosshairCursor) - [active line highlighting](https://codemirror.net/6/docs/ref/#view.highlightActiveLine) - [active line gutter highlighting](https://codemirror.net/6/docs/ref/#view.highlightActiveLineGutter) - [selection match highlighting](https://codemirror.net/6/docs/ref/#search.highlightSelectionMatches) - [search](https://codemirror.net/6/docs/ref/#search.searchKeymap) - [linting](https://codemirror.net/6/docs/ref/#lint.lintKeymap) (You'll probably want to add some language package to your setup too.) This extension does not allow customization. The idea is that, once you decide you want to configure your editor more precisely, you take this package's source (which is just a bunch of imports and an array literal), copy it into your own code, and adjust it as desired. */ var basicSetup = function basicSetup(options) { if (options === void 0) { options = {}; } var { crosshairCursor: initCrosshairCursor = false } = options; var keymaps = []; if (options.closeBracketsKeymap !== false) { keymaps = keymaps.concat(closeBracketsKeymap); } if (options.defaultKeymap !== false) { keymaps = keymaps.concat(dist/* defaultKeymap */.pw); } if (options.searchKeymap !== false) { keymaps = keymaps.concat(searchKeymap); } if (options.historyKeymap !== false) { keymaps = keymaps.concat(dist/* historyKeymap */.cL); } if (options.foldKeymap !== false) { keymaps = keymaps.concat(language_dist/* foldKeymap */.f7); } if (options.completionKeymap !== false) { keymaps = keymaps.concat(completionKeymap); } if (options.lintKeymap !== false) { keymaps = keymaps.concat(lintKeymap); } var extensions = []; if (options.lineNumbers !== false) extensions.push((0,view_.lineNumbers)()); if (options.highlightActiveLineGutter !== false) extensions.push((0,view_.highlightActiveLineGutter)()); if (options.highlightSpecialChars !== false) extensions.push((0,view_.highlightSpecialChars)()); if (options.history !== false) extensions.push((0,dist/* history */.b6)()); if (options.foldGutter !== false) extensions.push((0,language_dist/* foldGutter */.Lv)()); if (options.drawSelection !== false) extensions.push((0,view_.drawSelection)()); if (options.dropCursor !== false) extensions.push((0,view_.dropCursor)()); if (options.allowMultipleSelections !== false) extensions.push(state_.EditorState.allowMultipleSelections.of(true)); if (options.indentOnInput !== false) extensions.push((0,language_dist/* indentOnInput */.WD)()); if (options.syntaxHighlighting !== false) extensions.push((0,language_dist/* syntaxHighlighting */.y9)(language_dist/* defaultHighlightStyle */.Zt, { fallback: true })); if (options.bracketMatching !== false) extensions.push((0,language_dist/* bracketMatching */.SG)()); if (options.closeBrackets !== false) extensions.push(closeBrackets()); if (options.autocompletion !== false) extensions.push(autocompletion()); if (options.rectangularSelection !== false) extensions.push((0,view_.rectangularSelection)()); if (initCrosshairCursor !== false) extensions.push((0,view_.crosshairCursor)()); if (options.highlightActiveLine !== false) extensions.push((0,view_.highlightActiveLine)()); if (options.highlightSelectionMatches !== false) extensions.push(highlightSelectionMatches()); if (options.tabSize && typeof options.tabSize === 'number') extensions.push(language_dist/* indentUnit */.Xt.of(' '.repeat(options.tabSize))); return extensions.concat([view_.keymap.of(keymaps.flat())]).filter(Boolean); }; /** A minimal set of extensions to create a functional editor. Only includes [the default keymap](https://codemirror.net/6/docs/ref/#commands.defaultKeymap), [undo history](https://codemirror.net/6/docs/ref/#commands.history), [special character highlighting](https://codemirror.net/6/docs/ref/#view.highlightSpecialChars), [custom selection drawing](https://codemirror.net/6/docs/ref/#view.drawSelection), and [default highlight style](https://codemirror.net/6/docs/ref/#language.defaultHighlightStyle). */ var minimalSetup = function minimalSetup(options) { if (options === void 0) { options = {}; } var keymaps = []; if (options.defaultKeymap !== false) { keymaps = keymaps.concat(dist/* defaultKeymap */.pw); } if (options.historyKeymap !== false) { keymaps = keymaps.concat(dist/* historyKeymap */.cL); } var extensions = []; if (options.highlightSpecialChars !== false) extensions.push((0,view_.highlightSpecialChars)()); if (options.history !== false) extensions.push((0,dist/* history */.b6)()); if (options.drawSelection !== false) extensions.push((0,view_.drawSelection)()); if (options.syntaxHighlighting !== false) extensions.push((0,language_dist/* syntaxHighlighting */.y9)(language_dist/* defaultHighlightStyle */.Zt, { fallback: true })); return extensions.concat([view_.keymap.of(keymaps.flat())]).filter(Boolean); }; /***/ }), /***/ 89: /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ defaultLightThemeOption: () => (/* reexport safe */ _theme_light__WEBPACK_IMPORTED_MODULE_4__.c), /* harmony export */ getDefaultExtensions: () => (/* binding */ getDefaultExtensions) /* harmony export */ }); /* harmony import */ var _codemirror_commands__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(720); /* harmony import */ var _uiw_codemirror_extensions_basic_setup__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(368); /* harmony import */ var _codemirror_view__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(730); /* harmony import */ var _codemirror_view__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_codemirror_view__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _codemirror_theme_one_dark__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(708); /* harmony import */ var _codemirror_theme_one_dark__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_codemirror_theme_one_dark__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _codemirror_state__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(60); /* harmony import */ var _codemirror_state__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_codemirror_state__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _theme_light__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(806); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _codemirror_theme_one_dark__WEBPACK_IMPORTED_MODULE_2__) if(["default","getDefaultExtensions"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _codemirror_theme_one_dark__WEBPACK_IMPORTED_MODULE_2__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); var getDefaultExtensions=function getDefaultExtensions(){var optios=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};var _optios$indentWithTab=optios.indentWithTab,defaultIndentWithTab=_optios$indentWithTab===void 0?true:_optios$indentWithTab,_optios$editable=optios.editable,editable=_optios$editable===void 0?true:_optios$editable,_optios$readOnly=optios.readOnly,readOnly=_optios$readOnly===void 0?false:_optios$readOnly,_optios$theme=optios.theme,theme=_optios$theme===void 0?'light':_optios$theme,_optios$placeholder=optios.placeholder,placeholderStr=_optios$placeholder===void 0?'':_optios$placeholder,_optios$basicSetup=optios.basicSetup,defaultBasicSetup=_optios$basicSetup===void 0?true:_optios$basicSetup;var getExtensions=[];if(defaultIndentWithTab){getExtensions.unshift(_codemirror_view__WEBPACK_IMPORTED_MODULE_1__.keymap.of([_codemirror_commands__WEBPACK_IMPORTED_MODULE_5__/* .indentWithTab */ .Yc]));}if(defaultBasicSetup){if(typeof defaultBasicSetup==='boolean'){getExtensions.unshift((0,_uiw_codemirror_extensions_basic_setup__WEBPACK_IMPORTED_MODULE_0__/* .basicSetup */ .o)());}else{getExtensions.unshift((0,_uiw_codemirror_extensions_basic_setup__WEBPACK_IMPORTED_MODULE_0__/* .basicSetup */ .o)(defaultBasicSetup));}}if(placeholderStr){getExtensions.unshift((0,_codemirror_view__WEBPACK_IMPORTED_MODULE_1__.placeholder)(placeholderStr));}switch(theme){case'light':getExtensions.push(_theme_light__WEBPACK_IMPORTED_MODULE_4__/* .defaultLightThemeOption */ .c);break;case'dark':getExtensions.push(_codemirror_theme_one_dark__WEBPACK_IMPORTED_MODULE_2__.oneDark);break;case'none':break;default:getExtensions.push(theme);break;}if(editable===false){getExtensions.push(_codemirror_view__WEBPACK_IMPORTED_MODULE_1__.EditorView.editable.of(false));}if(readOnly){getExtensions.push(_codemirror_state__WEBPACK_IMPORTED_MODULE_3__.EditorState.readOnly.of(true));}return[].concat(getExtensions);}; /***/ }), /***/ 806: /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ c: () => (/* binding */ defaultLightThemeOption) /* harmony export */ }); /* harmony import */ var _codemirror_view__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(730); /* harmony import */ var _codemirror_view__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_codemirror_view__WEBPACK_IMPORTED_MODULE_0__); var defaultLightThemeOption=_codemirror_view__WEBPACK_IMPORTED_MODULE_0__.EditorView.theme({'&':{backgroundColor:'#fff'}},{dark:false}); /***/ }), /***/ 695: /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { // EXPORTS __webpack_require__.d(__webpack_exports__, { q: () => (/* binding */ useCodeMirror) }); ;// CONCATENATED MODULE: ../node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } ;// CONCATENATED MODULE: ../node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } ;// CONCATENATED MODULE: ../node_modules/@babel/runtime/helpers/esm/iterableToArray.js function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } ;// CONCATENATED MODULE: ../node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } ;// CONCATENATED MODULE: ../node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } ;// CONCATENATED MODULE: ../node_modules/@babel/runtime/helpers/esm/toConsumableArray.js function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } ;// CONCATENATED MODULE: ../node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } ;// CONCATENATED MODULE: ../node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } ;// CONCATENATED MODULE: ../node_modules/@babel/runtime/helpers/esm/nonIterableRest.js function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } ;// CONCATENATED MODULE: ../node_modules/@babel/runtime/helpers/esm/slicedToArray.js function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } // EXTERNAL MODULE: external {"root":"React","commonjs2":"react","commonjs":"react","amd":"react"} var external_root_React_commonjs2_react_commonjs_react_amd_react_ = __webpack_require__(442); // EXTERNAL MODULE: external {"root":["CM","@codemirror/state"],"commonjs":"@codemirror/state","commonjs2":"@codemirror/state"} var state_ = __webpack_require__(60); // EXTERNAL MODULE: external {"root":["CM","@codemirror/view"],"commonjs":"@codemirror/view","commonjs2":"@codemirror/view"} var view_ = __webpack_require__(730); // EXTERNAL MODULE: ./src/getDefaultExtensions.ts var getDefaultExtensions = __webpack_require__(89); // EXTERNAL MODULE: ./src/utils.ts var utils = __webpack_require__(369); ;// CONCATENATED MODULE: ./src/useCodeMirror.ts var External=state_.Annotation.define();var emptyExtensions=[];function useCodeMirror(props){var value=props.value,selection=props.selection,onChange=props.onChange,onStatistics=props.onStatistics,onCreateEditor=props.onCreateEditor,onUpdate=props.onUpdate,_props$extensions=props.extensions,extensions=_props$extensions===void 0?emptyExtensions:_props$extensions,autoFocus=props.autoFocus,_props$theme=props.theme,theme=_props$theme===void 0?'light':_props$theme,_props$height=props.height,height=_props$height===void 0?null:_props$height,_props$minHeight=props.minHeight,minHeight=_props$minHeight===void 0?null:_props$minHeight,_props$maxHeight=props.maxHeight,maxHeight=_props$maxHeight===void 0?null:_props$maxHeight,_props$width=props.width,width=_props$width===void 0?null:_props$width,_props$minWidth=props.minWidth,minWidth=_props$minWidth===void 0?null:_props$minWidth,_props$maxWidth=props.maxWidth,maxWidth=_props$maxWidth===void 0?null:_props$maxWidth,_props$placeholder=props.placeholder,placeholderStr=_props$placeholder===void 0?'':_props$placeholder,_props$editable=props.editable,editable=_props$editable===void 0?true:_props$editable,_props$readOnly=props.readOnly,readOnly=_props$readOnly===void 0?false:_props$readOnly,_props$indentWithTab=props.indentWithTab,defaultIndentWithTab=_props$indentWithTab===void 0?true:_props$indentWithTab,_props$basicSetup=props.basicSetup,defaultBasicSetup=_props$basicSetup===void 0?true:_props$basicSetup,root=props.root,initialState=props.initialState;var _useState=(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useState)(),_useState2=_slicedToArray(_useState,2),container=_useState2[0],setContainer=_useState2[1];var _useState3=(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useState)(),_useState4=_slicedToArray(_useState3,2),view=_useState4[0],setView=_useState4[1];var _useState5=(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useState)(),_useState6=_slicedToArray(_useState5,2),state=_useState6[0],setState=_useState6[1];var defaultThemeOption=view_.EditorView.theme({'&':{height:height,minHeight:minHeight,maxHeight:maxHeight,width:width,minWidth:minWidth,maxWidth:maxWidth},'& .cm-scroller':{height:'100% !important'}});var updateListener=view_.EditorView.updateListener.of(function(vu){if(vu.docChanged&&typeof onChange==='function'&&// Fix echoing of the remote changes: // If transaction is market as remote we don't have to call `onChange` handler again !vu.transactions.some(function(tr){return tr.annotation(External);})){var doc=vu.state.doc;var _value=doc.toString();onChange(_value,vu);}onStatistics&&onStatistics((0,utils/* getStatistics */.m)(vu));});var defaultExtensions=(0,getDefaultExtensions.getDefaultExtensions)({theme:theme,editable:editable,readOnly:readOnly,placeholder:placeholderStr,indentWithTab:defaultIndentWithTab,basicSetup:defaultBasicSetup});var getExtensions=[updateListener,defaultThemeOption].concat(_toConsumableArray(defaultExtensions));if(onUpdate&&typeof onUpdate==='function'){getExtensions.push(view_.EditorView.updateListener.of(onUpdate));}getExtensions=getExtensions.concat(extensions);(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useEffect)(function(){if(container&&!state){var config={doc:value,selection:selection,extensions:getExtensions};var stateCurrent=initialState?state_.EditorState.fromJSON(initialState.json,config,initialState.fields):state_.EditorState.create(config);setState(stateCurrent);if(!view){var viewCurrent=new view_.EditorView({state:stateCurrent,parent:container,root:root});setView(viewCurrent);onCreateEditor&&onCreateEditor(viewCurrent,stateCurrent);}}return function(){if(view){setState(undefined);setView(undefined);}};},[container,state]);(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useEffect)(function(){return setContainer(props.container);},[props.container]);(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useEffect)(function(){return function(){if(view){view.destroy();setView(undefined);}};},[view]);(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useEffect)(function(){if(autoFocus&&view){view.focus();}},[autoFocus,view]);(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useEffect)(function(){if(view){view.dispatch({effects:state_.StateEffect.reconfigure.of(getExtensions)});}// eslint-disable-next-line react-hooks/exhaustive-deps },[theme,extensions,height,minHeight,maxHeight,width,minWidth,maxWidth,placeholderStr,editable,readOnly,defaultIndentWithTab,defaultBasicSetup,onChange,onUpdate]);(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useEffect)(function(){if(value===undefined){return;}var currentValue=view?view.state.doc.toString():'';if(view&&value!==currentValue){view.dispatch({changes:{from:0,to:currentValue.length,insert:value||''},annotations:[External.of(true)]});}},[value,view]);return{state:state,setState:setState,view:view,setView:setView,container:container,setContainer:setContainer};} /***/ }), /***/ 369: /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ m: () => (/* binding */ getStatistics) /* harmony export */ }); var getStatistics=function getStatistics(view){return{line:view.state.doc.lineAt(view.state.selection.main.from),lineCount:view.state.doc.lines,lineBreak:view.state.lineBreak,length:view.state.doc.length,readOnly:view.state.readOnly,tabSize:view.state.tabSize,selection:view.state.selection,selectionAsSingle:view.state.selection.asSingle().main,ranges:view.state.selection.ranges,selectionCode:view.state.sliceDoc(view.state.selection.main.from,view.state.selection.main.to),selections:view.state.selection.ranges.map(function(r){return view.state.sliceDoc(r.from,r.to);}),selectedText:view.state.selection.ranges.some(function(r){return!r.empty;})};}; /***/ }), /***/ 442: /***/ ((module) => { module.exports = __WEBPACK_EXTERNAL_MODULE__442__; /***/ }), /***/ 742: /***/ ((module) => { module.exports = __WEBPACK_EXTERNAL_MODULE__742__; /***/ }), /***/ 60: /***/ ((module) => { module.exports = __WEBPACK_EXTERNAL_MODULE__60__; /***/ }), /***/ 708: /***/ ((module) => { module.exports = __WEBPACK_EXTERNAL_MODULE__708__; /***/ }), /***/ 730: /***/ ((module) => { module.exports = __WEBPACK_EXTERNAL_MODULE__730__; /***/ }), /***/ 957: /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { // EXPORTS __webpack_require__.d(__webpack_exports__, { A: () => (/* binding */ _objectSpread2) }); ;// CONCATENATED MODULE: ../node_modules/@babel/runtime/helpers/esm/typeof.js function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } ;// CONCATENATED MODULE: ../node_modules/@babel/runtime/helpers/esm/toPrimitive.js function toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } ;// CONCATENATED MODULE: ../node_modules/@babel/runtime/helpers/esm/toPropertyKey.js function toPropertyKey(t) { var i = toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } ;// CONCATENATED MODULE: ../node_modules/@babel/runtime/helpers/esm/defineProperty.js function _defineProperty(e, r, t) { return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } ;// CONCATENATED MODULE: ../node_modules/@babel/runtime/helpers/esm/objectSpread2.js function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /***/ }), /***/ 644: /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { // EXPORTS __webpack_require__.d(__webpack_exports__, { A: () => (/* binding */ _objectWithoutProperties) }); ;// CONCATENATED MODULE: ../node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.indexOf(n) >= 0) continue; t[n] = r[n]; } return t; } ;// CONCATENATED MODULE: ../node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], t.indexOf(o) >= 0 || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; } /***/ }), /***/ 720: /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ Yc: () => (/* binding */ indentWithTab), /* harmony export */ b6: () => (/* binding */ history), /* harmony export */ cL: () => (/* binding */ historyKeymap), /* harmony export */ pw: () => (/* binding */ defaultKeymap) /* harmony export */ }); /* unused harmony exports blockComment, blockUncomment, copyLineDown, copyLineUp, cursorCharBackward, cursorCharForward, cursorCharLeft, cursorCharRight, cursorDocEnd, cursorDocStart, cursorGroupBackward, cursorGroupForward, cursorGroupLeft, cursorGroupRight, cursorLineBoundaryBackward, cursorLineBoundaryForward, cursorLineBoundaryLeft, cursorLineBoundaryRight, cursorLineDown, cursorLineEnd, cursorLineStart, cursorLineUp, cursorMatchingBracket, cursorPageDown, cursorPageUp, cursorSubwordBackward, cursorSubwordForward, cursorSyntaxLeft, cursorSyntaxRight, deleteCharBackward, deleteCharBackwardStrict, deleteCharForward, deleteGroupBackward, deleteGroupForward, deleteLine, deleteLineBoundaryBackward, deleteLineBoundaryForward, deleteToLineEnd, deleteToLineStart, deleteTrailingWhitespace, emacsStyleKeymap, historyField, indentLess, indentMore, indentSelection, insertBlankLine, insertNewline, insertNewlineAndIndent, insertNewlineKeepIndent, insertTab, invertedEffects, isolateHistory, lineComment, lineUncomment, moveLineDown, moveLineUp, redo, redoDepth, redoSelection, selectAll, selectCharBackward, selectCharForward, selectCharLeft, selectCharRight, selectDocEnd, selectDocStart, selectGroupBackward, selectGroupForward, selectGroupLeft, selectGroupRight, selectLine, selectLineBoundaryBackward, selectLineBoundaryForward, selectLineBoundaryLeft, selectLineBoundaryRight, selectLineDown, selectLineEnd, selectLineStart, selectLineUp, selectMatchingBracket, selectPageDown, selectPageUp, selectParentSyntax, selectSubwordBackward, selectSubwordForward, selectSyntaxLeft, selectSyntaxRight, simplifySelection, splitLine, standardKeymap, temporarilySetTabFocusMode, toggleBlockComment, toggleBlockCommentByLine, toggleComment, toggleLineComment, toggleTabFocusMode, transposeChars, undo, undoDepth, undoSelection */ /* harmony import */ var _codemirror_state__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(60); /* harmony import */ var _codemirror_view__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(730); /* harmony import */ var _codemirror_language__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(194); /* harmony import */ var _lezer_common__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(203); /** Comment or uncomment the current selection. Will use line comments if available, otherwise falling back to block comments. */ const toggleComment = target => { let { state } = target, line = state.doc.lineAt(state.selection.main.from), config = getConfig(target.state, line.from); return config.line ? toggleLineComment(target) : config.block ? toggleBlockCommentByLine(target) : false; }; function command(f, option) { return ({ state, dispatch }) => { if (state.readOnly) return false; let tr = f(option, state); if (!tr) return false; dispatch(state.update(tr)); return true; }; } /** Comment or uncomment the current selection using line comments. The line comment syntax is taken from the [`commentTokens`](https://codemirror.net/6/docs/ref/#commands.CommentTokens) [language data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt). */ const toggleLineComment = /*@__PURE__*/command(changeLineComment, 0 /* CommentOption.Toggle */); /** Comment the current selection using line comments. */ const lineComment = /*@__PURE__*/(/* unused pure expression or super */ null && (command(changeLineComment, 1 /* CommentOption.Comment */))); /** Uncomment the current selection using line comments. */ const lineUncomment = /*@__PURE__*/(/* unused pure expression or super */ null && (command(changeLineComment, 2 /* CommentOption.Uncomment */))); /** Comment or uncomment the current selection using block comments. The block comment syntax is taken from the [`commentTokens`](https://codemirror.net/6/docs/ref/#commands.CommentTokens) [language data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt). */ const toggleBlockComment = /*@__PURE__*/command(changeBlockComment, 0 /* CommentOption.Toggle */); /** Comment the current selection using block comments. */ const blockComment = /*@__PURE__*/(/* unused pure expression or super */ null && (command(changeBlockComment, 1 /* CommentOption.Comment */))); /** Uncomment the current selection using block comments. */ const blockUncomment = /*@__PURE__*/(/* unused pure expression or super */ null && (command(changeBlockComment, 2 /* CommentOption.Uncomment */))); /** Comment or uncomment the lines around the current selection using block comments. */ const toggleBlockCommentByLine = /*@__PURE__*/command((o, s) => changeBlockComment(o, s, selectedLineRanges(s)), 0 /* CommentOption.Toggle */); function getConfig(state, pos) { let data = state.languageDataAt("commentTokens", pos); return data.length ? data[0] : {}; } const SearchMargin = 50; /** Determines if the given range is block-commented in the given state. */ function findBlockComment(state, { open, close }, from, to) { let textBefore = state.sliceDoc(from - SearchMargin, from); let textAfter = state.sliceDoc(to, to + SearchMargin); let spaceBefore = /\s*$/.exec(textBefore)[0].length, spaceAfter = /^\s*/.exec(textAfter)[0].length; let beforeOff = textBefore.length - spaceBefore; if (textBefore.slice(beforeOff - open.length, beforeOff) == open && textAfter.slice(spaceAfter, spaceAfter + close.length) == close) { return { open: { pos: from - spaceBefore, margin: spaceBefore && 1 }, close: { pos: to + spaceAfter, margin: spaceAfter && 1 } }; } let startText, endText; if (to - from <= 2 * SearchMargin) { startText = endText = state.sliceDoc(from, to); } else { startText = state.sliceDoc(from, from + SearchMargin); endText = state.sliceDoc(to - SearchMargin, to); } let startSpace = /^\s*/.exec(startText)[0].length, endSpace = /\s*$/.exec(endText)[0].length; let endOff = endText.length - endSpace - close.length; if (startText.slice(startSpace, startSpace + open.length) == open && endText.slice(endOff, endOff + close.length) == close) { return { open: { pos: from + startSpace + open.length, margin: /\s/.test(startText.charAt(startSpace + open.length)) ? 1 : 0 }, close: { pos: to - endSpace - close.length, margin: /\s/.test(endText.charAt(endOff - 1)) ? 1 : 0 } }; } return null; } function selectedLineRanges(state) { let ranges = []; for (let r of state.selection.ranges) { let fromLine = state.doc.lineAt(r.from); let toLine = r.to <= fromLine.to ? fromLine : state.doc.lineAt(r.to); let last = ranges.length - 1; if (last >= 0 && ranges[last].to > fromLine.from) ranges[last].to = toLine.to; else ranges.push({ from: fromLine.from + /^\s*/.exec(fromLine.text)[0].length, to: toLine.to }); } return ranges; } // Performs toggle, comment and uncomment of block comments in // languages that support them. function changeBlockComment(option, state, ranges = state.selection.ranges) { let tokens = ranges.map(r => getConfig(state, r.from).block); if (!tokens.every(c => c)) return null; let comments = ranges.map((r, i) => findBlockComment(state, tokens[i], r.from, r.to)); if (option != 2 /* CommentOption.Uncomment */ && !comments.every(c => c)) { return { changes: state.changes(ranges.map((range, i) => { if (comments[i]) return []; return [{ from: range.from, insert: tokens[i].open + " " }, { from: range.to, insert: " " + tokens[i].close }]; })) }; } else if (option != 1 /* CommentOption.Comment */ && comments.some(c => c)) { let changes = []; for (let i = 0, comment; i < comments.length; i++) if (comment = comments[i]) { let token = tokens[i], { open, close } = comment; changes.push({ from: open.pos - token.open.length, to: open.pos + open.margin }, { from: close.pos - close.margin, to: close.pos + token.close.length }); } return { changes }; } return null; } // Performs toggle, comment and uncomment of line comments. function changeLineComment(option, state, ranges = state.selection.ranges) { let lines = []; let prevLine = -1; for (let { from, to } of ranges) { let startI = lines.length, minIndent = 1e9; let token = getConfig(state, from).line; if (!token) continue; for (let pos = from; pos <= to;) { let line = state.doc.lineAt(pos); if (line.from > prevLine && (from == to || to > line.from)) { prevLine = line.from; let indent = /^\s*/.exec(line.text)[0].length; let empty = indent == line.length; let comment = line.text.slice(indent, indent + token.length) == token ? indent : -1; if (indent < line.text.length && indent < minIndent) minIndent = indent; lines.push({ line, comment, token, indent, empty, single: false }); } pos = line.to + 1; } if (minIndent < 1e9) for (let i = startI; i < lines.length; i++) if (lines[i].indent < lines[i].line.text.length) lines[i].indent = minIndent; if (lines.length == startI + 1) lines[startI].single = true; } if (option != 2 /* CommentOption.Uncomment */ && lines.some(l => l.comment < 0 && (!l.empty || l.single))) { let changes = []; for (let { line, token, indent, empty, single } of lines) if (single || !empty) changes.push({ from: line.from + indent, insert: token + " " }); let changeSet = state.changes(changes); return { changes: changeSet, selection: state.selection.map(changeSet, 1) }; } else if (option != 1 /* CommentOption.Comment */ && lines.some(l => l.comment >= 0)) { let changes = []; for (let { line, comment, token } of lines) if (comment >= 0) { let from = line.from + comment, to = from + token.length; if (line.text[to - line.from] == " ") to++; changes.push({ from, to }); } return { changes }; } return null; } const fromHistory = /*@__PURE__*/_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.Annotation.define(); /** Transaction annotation that will prevent that transaction from being combined with other transactions in the undo history. Given `"before"`, it'll prevent merging with previous transactions. With `"after"`, subsequent transactions won't be combined with this one. With `"full"`, the transaction is isolated on both sides. */ const isolateHistory = /*@__PURE__*/_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.Annotation.define(); /** This facet provides a way to register functions that, given a transaction, provide a set of effects that the history should store when inverting the transaction. This can be used to integrate some kinds of effects in the history, so that they can be undone (and redone again). */ const invertedEffects = /*@__PURE__*/_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.Facet.define(); const historyConfig = /*@__PURE__*/_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.Facet.define({ combine(configs) { return (0,_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.combineConfig)(configs, { minDepth: 100, newGroupDelay: 500, joinToEvent: (_t, isAdjacent) => isAdjacent, }, { minDepth: Math.max, newGroupDelay: Math.min, joinToEvent: (a, b) => (tr, adj) => a(tr, adj) || b(tr, adj) }); } }); const historyField_ = /*@__PURE__*/_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.StateField.define({ create() { return HistoryState.empty; }, update(state, tr) { let config = tr.state.facet(historyConfig); let fromHist = tr.annotation(fromHistory); if (fromHist) { let item = HistEvent.fromTransaction(tr, fromHist.selection), from = fromHist.side; let other = from == 0 /* BranchName.Done */ ? state.undone : state.done; if (item) other = updateBranch(other, other.length, config.minDepth, item); else other = addSelection(other, tr.startState.selection); return new HistoryState(from == 0 /* BranchName.Done */ ? fromHist.rest : other, from == 0 /* BranchName.Done */ ? other : fromHist.rest); } let isolate = tr.annotation(isolateHistory); if (isolate == "full" || isolate == "before") state = state.isolate(); if (tr.annotation(_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.Transaction.addToHistory) === false) return !tr.changes.empty ? state.addMapping(tr.changes.desc) : state; let event = HistEvent.fromTransaction(tr); let time = tr.annotation(_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.Transaction.time), userEvent = tr.annotation(_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.Transaction.userEvent); if (event) state = state.addChanges(event, time, userEvent, config, tr); else if (tr.selection) state = state.addSelection(tr.startState.selection, time, userEvent, config.newGroupDelay); if (isolate == "full" || isolate == "after") state = state.isolate(); return state; }, toJSON(value) { return { done: value.done.map(e => e.toJSON()), undone: value.undone.map(e => e.toJSON()) }; }, fromJSON(json) { return new HistoryState(json.done.map(HistEvent.fromJSON), json.undone.map(HistEvent.fromJSON)); } }); /** Create a history extension with the given configuration. */ function history(config = {}) { return [ historyField_, historyConfig.of(config), _codemirror_view__WEBPACK_IMPORTED_MODULE_1__.EditorView.domEventHandlers({ beforeinput(e, view) { let command = e.inputType == "historyUndo" ? undo : e.inputType == "historyRedo" ? redo : null; if (!command) return false; e.preventDefault(); return command(view); } }) ]; } /** The state field used to store the history data. Should probably only be used when you want to [serialize](https://codemirror.net/6/docs/ref/#state.EditorState.toJSON) or [deserialize](https://codemirror.net/6/docs/ref/#state.EditorState^fromJSON) state objects in a way that preserves history. */ const historyField = (/* unused pure expression or super */ null && (historyField_)); function cmd(side, selection) { return function ({ state, dispatch }) { if (!selection && state.readOnly) return false; let historyState = state.field(historyField_, false); if (!historyState) return false; let tr = historyState.pop(side, state, selection); if (!tr) return false; dispatch(tr); return true; }; } /** Undo a single group of history events. Returns false if no group was available. */ const undo = /*@__PURE__*/cmd(0 /* BranchName.Done */, false); /** Redo a group of history events. Returns false if no group was available. */ const redo = /*@__PURE__*/cmd(1 /* BranchName.Undone */, false); /** Undo a change or selection change. */ const undoSelection = /*@__PURE__*/cmd(0 /* BranchName.Done */, true); /** Redo a change or selection change. */ const redoSelection = /*@__PURE__*/cmd(1 /* BranchName.Undone */, true); function depth(side) { return function (state) { let histState = state.field(historyField_, false); if (!histState) return 0; let branch = side == 0 /* BranchName.Done */ ? histState.done : histState.undone; return branch.length - (branch.length && !branch[0].changes ? 1 : 0); }; } /** The amount of undoable change events available in a given state. */ const undoDepth = /*@__PURE__*/(/* unused pure expression or super */ null && (depth(0 /* BranchName.Done */))); /** The amount of redoable change events available in a given state. */ const redoDepth = /*@__PURE__*/(/* unused pure expression or super */ null && (depth(1 /* BranchName.Undone */))); // History events store groups of changes or effects that need to be // undone/redone together. class HistEvent { constructor( // The changes in this event. Normal events hold at least one // change or effect. But it may be necessary to store selection // events before the first change, in which case a special type of // instance is created which doesn't hold any changes, with // changes == startSelection == undefined changes, // The effects associated with this event effects, // Accumulated mapping (from addToHistory==false) that should be // applied to events below this one. mapped, // The selection before this event startSelection, // Stores selection changes after this event, to be used for // selection undo/redo. selectionsAfter) { this.changes = changes; this.effects = effects; this.mapped = mapped; this.startSelection = startSelection; this.selectionsAfter = selectionsAfter; } setSelAfter(after) { return new HistEvent(this.changes, this.effects, this.mapped, this.startSelection, after); } toJSON() { var _a, _b, _c; return { changes: (_a = this.changes) === null || _a === void 0 ? void 0 : _a.toJSON(), mapped: (_b = this.mapped) === null || _b === void 0 ? void 0 : _b.toJSON(), startSelection: (_c = this.startSelection) === null || _c === void 0 ? void 0 : _c.toJSON(), selectionsAfter: this.selectionsAfter.map(s => s.toJSON()) }; } static fromJSON(json) { return new HistEvent(json.changes && _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.ChangeSet.fromJSON(json.changes), [], json.mapped && _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.ChangeDesc.fromJSON(json.mapped), json.startSelection && _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.fromJSON(json.startSelection), json.selectionsAfter.map(_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.fromJSON)); } // This does not check `addToHistory` and such, it assumes the // transaction needs to be converted to an item. Returns null when // there are no changes or effects in the transaction. static fromTransaction(tr, selection) { let effects = none; for (let invert of tr.startState.facet(invertedEffects)) { let result = invert(tr); if (result.length) effects = effects.concat(result); } if (!effects.length && tr.changes.empty) return null; return new HistEvent(tr.changes.invert(tr.startState.doc), effects, undefined, selection || tr.startState.selection, none); } static selection(selections) { return new HistEvent(undefined, none, undefined, undefined, selections); } } function updateBranch(branch, to, maxLen, newEvent) { let start = to + 1 > maxLen + 20 ? to - maxLen - 1 : 0; let newBranch = branch.slice(start, to); newBranch.push(newEvent); return newBranch; } function isAdjacent(a, b) { let ranges = [], isAdjacent = false; a.iterChangedRanges((f, t) => ranges.push(f, t)); b.iterChangedRanges((_f, _t, f, t) => { for (let i = 0; i < ranges.length;) { let from = ranges[i++], to = ranges[i++]; if (t >= from && f <= to) isAdjacent = true; } }); return isAdjacent; } function eqSelectionShape(a, b) { return a.ranges.length == b.ranges.length && a.ranges.filter((r, i) => r.empty != b.ranges[i].empty).length === 0; } function conc(a, b) { return !a.length ? b : !b.length ? a : a.concat(b); } const none = []; const MaxSelectionsPerEvent = 200; function addSelection(branch, selection) { if (!branch.length) { return [HistEvent.selection([selection])]; } else { let lastEvent = branch[branch.length - 1]; let sels = lastEvent.selectionsAfter.slice(Math.max(0, lastEvent.selectionsAfter.length - MaxSelectionsPerEvent)); if (sels.length && sels[sels.length - 1].eq(selection)) return branch; sels.push(selection); return updateBranch(branch, branch.length - 1, 1e9, lastEvent.setSelAfter(sels)); } } // Assumes the top item has one or more selectionAfter values function popSelection(branch) { let last = branch[branch.length - 1]; let newBranch = branch.slice(); newBranch[branch.length - 1] = last.setSelAfter(last.selectionsAfter.slice(0, last.selectionsAfter.length - 1)); return newBranch; } // Add a mapping to the top event in the given branch. If this maps // away all the changes and effects in that item, drop it and // propagate the mapping to the next item. function addMappingToBranch(branch, mapping) { if (!branch.length) return branch; let length = branch.length, selections = none; while (length) { let event = mapEvent(branch[length - 1], mapping, selections); if (event.changes && !event.changes.empty || event.effects.length) { // Event survived mapping let result = branch.slice(0, length); result[length - 1] = event; return result; } else { // Drop this event, since there's no changes or effects left mapping = event.mapped; length--; selections = event.selectionsAfter; } } return selections.length ? [HistEvent.selection(selections)] : none; } function mapEvent(event, mapping, extraSelections) { let selections = conc(event.selectionsAfter.length ? event.selectionsAfter.map(s => s.map(mapping)) : none, extraSelections); // Change-less events don't store mappings (they are always the last event in a branch) if (!event.changes) return HistEvent.selection(selections); let mappedChanges = event.changes.map(mapping), before = mapping.mapDesc(event.changes, true); let fullMapping = event.mapped ? event.mapped.composeDesc(before) : before; return new HistEvent(mappedChanges, _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.StateEffect.mapEffects(event.effects, mapping), fullMapping, event.startSelection.map(before), selections); } const joinableUserEvent = /^(input\.type|delete)($|\.)/; class HistoryState { constructor(done, undone, prevTime = 0, prevUserEvent = undefined) { this.done = done; this.undone = undone; this.prevTime = prevTime; this.prevUserEvent = prevUserEvent; } isolate() { return this.prevTime ? new HistoryState(this.done, this.undone) : this; } addChanges(event, time, userEvent, config, tr) { let done = this.done, lastEvent = done[done.length - 1]; if (lastEvent && lastEvent.changes && !lastEvent.changes.empty && event.changes && (!userEvent || joinableUserEvent.test(userEvent)) && ((!lastEvent.selectionsAfter.length && time - this.prevTime < config.newGroupDelay && config.joinToEvent(tr, isAdjacent(lastEvent.changes, event.changes))) || // For compose (but not compose.start) events, always join with previous event userEvent == "input.type.compose")) { done = updateBranch(done, done.length - 1, config.minDepth, new HistEvent(event.changes.compose(lastEvent.changes), conc(event.effects, lastEvent.effects), lastEvent.mapped, lastEvent.startSelection, none)); } else { done = updateBranch(done, done.length, config.minDepth, event); } return new HistoryState(done, none, time, userEvent); } addSelection(selection, time, userEvent, newGroupDelay) { let last = this.done.length ? this.done[this.done.length - 1].selectionsAfter : none; if (last.length > 0 && time - this.prevTime < newGroupDelay && userEvent == this.prevUserEvent && userEvent && /^select($|\.)/.test(userEvent) && eqSelectionShape(last[last.length - 1], selection)) return this; return new HistoryState(addSelection(this.done, selection), this.undone, time, userEvent); } addMapping(mapping) { return new HistoryState(addMappingToBranch(this.done, mapping), addMappingToBranch(this.undone, mapping), this.prevTime, this.prevUserEvent); } pop(side, state, onlySelection) { let branch = side == 0 /* BranchName.Done */ ? this.done : this.undone; if (branch.length == 0) return null; let event = branch[branch.length - 1], selection = event.selectionsAfter[0] || state.selection; if (onlySelection && event.selectionsAfter.length) { return state.update({ selection: event.selectionsAfter[event.selectionsAfter.length - 1], annotations: fromHistory.of({ side, rest: popSelection(branch), selection }), userEvent: side == 0 /* BranchName.Done */ ? "select.undo" : "select.redo", scrollIntoView: true }); } else if (!event.changes) { return null; } else { let rest = branch.length == 1 ? none : branch.slice(0, branch.length - 1); if (event.mapped) rest = addMappingToBranch(rest, event.mapped); return state.update({ changes: event.changes, selection: event.startSelection, effects: event.effects, annotations: fromHistory.of({ side, rest, selection }), filter: false, userEvent: side == 0 /* BranchName.Done */ ? "undo" : "redo", scrollIntoView: true }); } } } HistoryState.empty = /*@__PURE__*/new HistoryState(none, none); /** Default key bindings for the undo history. - Mod-z: [`undo`](https://codemirror.net/6/docs/ref/#commands.undo). - Mod-y (Mod-Shift-z on macOS) + Ctrl-Shift-z on Linux: [`redo`](https://codemirror.net/6/docs/ref/#commands.redo). - Mod-u: [`undoSelection`](https://codemirror.net/6/docs/ref/#commands.undoSelection). - Alt-u (Mod-Shift-u on macOS): [`redoSelection`](https://codemirror.net/6/docs/ref/#commands.redoSelection). */ const historyKeymap = [ { key: "Mod-z", run: undo, preventDefault: true }, { key: "Mod-y", mac: "Mod-Shift-z", run: redo, preventDefault: true }, { linux: "Ctrl-Shift-z", run: redo, preventDefault: true }, { key: "Mod-u", run: undoSelection, preventDefault: true }, { key: "Alt-u", mac: "Mod-Shift-u", run: redoSelection, preventDefault: true } ]; function updateSel(sel, by) { return _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.create(sel.ranges.map(by), sel.mainIndex); } function setSel(state, selection) { return state.update({ selection, scrollIntoView: true, userEvent: "select" }); } function moveSel({ state, dispatch }, how) { let selection = updateSel(state.selection, how); if (selection.eq(state.selection, true)) return false; dispatch(setSel(state, selection)); return true; } function rangeEnd(range, forward) { return _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.cursor(forward ? range.to : range.from); } function cursorByChar(view, forward) { return moveSel(view, range => range.empty ? view.moveByChar(range, forward) : rangeEnd(range, forward)); } function ltrAtCursor(view) { return view.textDirectionAt(view.state.selection.main.head) == _codemirror_view__WEBPACK_IMPORTED_MODULE_1__.Direction.LTR; } /** Move the selection one character to the left (which is backward in left-to-right text, forward in right-to-left text). */ const cursorCharLeft = view => cursorByChar(view, !ltrAtCursor(view)); /** Move the selection one character to the right. */ const cursorCharRight = view => cursorByChar(view, ltrAtCursor(view)); /** Move the selection one character forward. */ const cursorCharForward = view => cursorByChar(view, true); /** Move the selection one character backward. */ const cursorCharBackward = view => cursorByChar(view, false); function cursorByGroup(view, forward) { return moveSel(view, range => range.empty ? view.moveByGroup(range, forward) : rangeEnd(range, forward)); } /** Move the selection to the left across one group of word or non-word (but also non-space) characters. */ const cursorGroupLeft = view => cursorByGroup(view, !ltrAtCursor(view)); /** Move the selection one group to the right. */ const cursorGroupRight = view => cursorByGroup(view, ltrAtCursor(view)); /** Move the selection one group forward. */ const cursorGroupForward = view => cursorByGroup(view, true); /** Move the selection one group backward. */ const cursorGroupBackward = view => cursorByGroup(view, false); const segmenter = typeof Intl != "undefined" && Intl.Segmenter ? /*@__PURE__*/new (Intl.Segmenter)(undefined, { granularity: "word" }) : null; function moveBySubword(view, range, forward) { let categorize = view.state.charCategorizer(range.from); let cat = CharCategory.Space, pos = range.from, steps = 0; let done = false, sawUpper = false, sawLower = false; let step = (next) => { if (done) return false; pos += forward ? next.length : -next.length; let nextCat = categorize(next), ahead; if (nextCat == CharCategory.Word && next.charCodeAt(0) < 128 && /[\W_]/.test(next)) nextCat = -1; // Treat word punctuation specially if (cat == CharCategory.Space) cat = nextCat; if (cat != nextCat) return false; if (cat == CharCategory.Word) { if (next.toLowerCase() == next) { if (!forward && sawUpper) return false; sawLower = true; } else if (sawLower) { if (forward) return false; done = true; } else { if (sawUpper && forward && categorize(ahead = view.state.sliceDoc(pos, pos + 1)) == CharCategory.Word && ahead.toLowerCase() == ahead) return false; sawUpper = true; } } steps++; return true; }; let end = view.moveByChar(range, forward, start => { step(start); return step; }); if (segmenter && cat == CharCategory.Word && end.from == range.from + steps * (forward ? 1 : -1)) { let from = Math.min(range.head, end.head), to = Math.max(range.head, end.head); let skipped = view.state.sliceDoc(from, to); if (skipped.length > 1 && /[\u4E00-\uffff]/.test(skipped)) { let segments = Array.from(segmenter.segment(skipped)); if (segments.length > 1) { if (forward) return EditorSelection.cursor(range.head + segments[1].index, -1); return EditorSelection.cursor(end.head + segments[segments.length - 1].index, 1); } } } return end; } function cursorBySubword(view, forward) { return moveSel(view, range => range.empty ? moveBySubword(view, range, forward) : rangeEnd(range, forward)); } /** Move the selection one group or camel-case subword forward. */ const cursorSubwordForward = view => cursorBySubword(view, true); /** Move the selection one group or camel-case subword backward. */ const cursorSubwordBackward = view => cursorBySubword(view, false); function interestingNode(state, node, bracketProp) { if (node.type.prop(bracketProp)) return true; let len = node.to - node.from; return len && (len > 2 || /[^\s,.;:]/.test(state.sliceDoc(node.from, node.to))) || node.firstChild; } function moveBySyntax(state, start, forward) { let pos = (0,_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .syntaxTree */ .mv)(state).resolveInner(start.head); let bracketProp = forward ? _lezer_common__WEBPACK_IMPORTED_MODULE_2__/* .NodeProp */ .uY.closedBy : _lezer_common__WEBPACK_IMPORTED_MODULE_2__/* .NodeProp */ .uY.openedBy; // Scan forward through child nodes to see if there's an interesting // node ahead. for (let at = start.head;;) { let next = forward ? pos.childAfter(at) : pos.childBefore(at); if (!next) break; if (interestingNode(state, next, bracketProp)) pos = next; else at = forward ? next.to : next.from; } let bracket = pos.type.prop(bracketProp), match, newPos; if (bracket && (match = forward ? (0,_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .matchBrackets */ .jU)(state, pos.from, 1) : (0,_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .matchBrackets */ .jU)(state, pos.to, -1)) && match.matched) newPos = forward ? match.end.to : match.end.from; else newPos = forward ? pos.to : pos.from; return _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.cursor(newPos, forward ? -1 : 1); } /** Move the cursor over the next syntactic element to the left. */ const cursorSyntaxLeft = view => moveSel(view, range => moveBySyntax(view.state, range, !ltrAtCursor(view))); /** Move the cursor over the next syntactic element to the right. */ const cursorSyntaxRight = view => moveSel(view, range => moveBySyntax(view.state, range, ltrAtCursor(view))); function cursorByLine(view, forward) { return moveSel(view, range => { if (!range.empty) return rangeEnd(range, forward); let moved = view.moveVertically(range, forward); return moved.head != range.head ? moved : view.moveToLineBoundary(range, forward); }); } /** Move the selection one line up. */ const cursorLineUp = view => cursorByLine(view, false); /** Move the selection one line down. */ const cursorLineDown = view => cursorByLine(view, true); function pageInfo(view) { let selfScroll = view.scrollDOM.clientHeight < view.scrollDOM.scrollHeight - 2; let marginTop = 0, marginBottom = 0, height; if (selfScroll) { for (let source of view.state.facet(_codemirror_view__WEBPACK_IMPORTED_MODULE_1__.EditorView.scrollMargins)) { let margins = source(view); if (margins === null || margins === void 0 ? void 0 : margins.top) marginTop = Math.max(margins === null || margins === void 0 ? void 0 : margins.top, marginTop); if (margins === null || margins === void 0 ? void 0 : margins.bottom) marginBottom = Math.max(margins === null || margins === void 0 ? void 0 : margins.bottom, marginBottom); } height = view.scrollDOM.clientHeight - marginTop - marginBottom; } else { height = (view.dom.ownerDocument.defaultView || window).innerHeight; } return { marginTop, marginBottom, selfScroll, height: Math.max(view.defaultLineHeight, height - 5) }; } function cursorByPage(view, forward) { let page = pageInfo(view); let { state } = view, selection = updateSel(state.selection, range => { return range.empty ? view.moveVertically(range, forward, page.height) : rangeEnd(range, forward); }); if (selection.eq(state.selection)) return false; let effect; if (page.selfScroll) { let startPos = view.coordsAtPos(state.selection.main.head); let scrollRect = view.scrollDOM.getBoundingClientRect(); let scrollTop = scrollRect.top + page.marginTop, scrollBottom = scrollRect.bottom - page.marginBottom; if (startPos && startPos.top > scrollTop && startPos.bottom < scrollBottom) effect = _codemirror_view__WEBPACK_IMPORTED_MODULE_1__.EditorView.scrollIntoView(selection.main.head, { y: "start", yMargin: startPos.top - scrollTop }); } view.dispatch(setSel(state, selection), { effects: effect }); return true; } /** Move the selection one page up. */ const cursorPageUp = view => cursorByPage(view, false); /** Move the selection one page down. */ const cursorPageDown = view => cursorByPage(view, true); function moveByLineBoundary(view, start, forward) { let line = view.lineBlockAt(start.head), moved = view.moveToLineBoundary(start, forward); if (moved.head == start.head && moved.head != (forward ? line.to : line.from)) moved = view.moveToLineBoundary(start, forward, false); if (!forward && moved.head == line.from && line.length) { let space = /^\s*/.exec(view.state.sliceDoc(line.from, Math.min(line.from + 100, line.to)))[0].length; if (space && start.head != line.from + space) moved = _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.cursor(line.from + space); } return moved; } /** Move the selection to the next line wrap point, or to the end of the line if there isn't one left on this line. */ const cursorLineBoundaryForward = view => moveSel(view, range => moveByLineBoundary(view, range, true)); /** Move the selection to previous line wrap point, or failing that to the start of the line. If the line is indented, and the cursor isn't already at the end of the indentation, this will move to the end of the indentation instead of the start of the line. */ const cursorLineBoundaryBackward = view => moveSel(view, range => moveByLineBoundary(view, range, false)); /** Move the selection one line wrap point to the left. */ const cursorLineBoundaryLeft = view => moveSel(view, range => moveByLineBoundary(view, range, !ltrAtCursor(view))); /** Move the selection one line wrap point to the right. */ const cursorLineBoundaryRight = view => moveSel(view, range => moveByLineBoundary(view, range, ltrAtCursor(view))); /** Move the selection to the start of the line. */ const cursorLineStart = view => moveSel(view, range => _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.cursor(view.lineBlockAt(range.head).from, 1)); /** Move the selection to the end of the line. */ const cursorLineEnd = view => moveSel(view, range => _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.cursor(view.lineBlockAt(range.head).to, -1)); function toMatchingBracket(state, dispatch, extend) { let found = false, selection = updateSel(state.selection, range => { let matching = (0,_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .matchBrackets */ .jU)(state, range.head, -1) || (0,_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .matchBrackets */ .jU)(state, range.head, 1) || (range.head > 0 && (0,_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .matchBrackets */ .jU)(state, range.head - 1, 1)) || (range.head < state.doc.length && (0,_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .matchBrackets */ .jU)(state, range.head + 1, -1)); if (!matching || !matching.end) return range; found = true; let head = matching.start.from == range.head ? matching.end.to : matching.end.from; return extend ? _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.range(range.anchor, head) : _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.cursor(head); }); if (!found) return false; dispatch(setSel(state, selection)); return true; } /** Move the selection to the bracket matching the one it is currently on, if any. */ const cursorMatchingBracket = ({ state, dispatch }) => toMatchingBracket(state, dispatch, false); /** Extend the selection to the bracket matching the one the selection head is currently on, if any. */ const selectMatchingBracket = ({ state, dispatch }) => toMatchingBracket(state, dispatch, true); function extendSel(view, how) { let selection = updateSel(view.state.selection, range => { let head = how(range); return _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.range(range.anchor, head.head, head.goalColumn, head.bidiLevel || undefined); }); if (selection.eq(view.state.selection)) return false; view.dispatch(setSel(view.state, selection)); return true; } function selectByChar(view, forward) { return extendSel(view, range => view.moveByChar(range, forward)); } /** Move the selection head one character to the left, while leaving the anchor in place. */ const selectCharLeft = view => selectByChar(view, !ltrAtCursor(view)); /** Move the selection head one character to the right. */ const selectCharRight = view => selectByChar(view, ltrAtCursor(view)); /** Move the selection head one character forward. */ const selectCharForward = view => selectByChar(view, true); /** Move the selection head one character backward. */ const selectCharBackward = view => selectByChar(view, false); function selectByGroup(view, forward) { return extendSel(view, range => view.moveByGroup(range, forward)); } /** Move the selection head one [group](https://codemirror.net/6/docs/ref/#commands.cursorGroupLeft) to the left. */ const selectGroupLeft = view => selectByGroup(view, !ltrAtCursor(view)); /** Move the selection head one group to the right. */ const selectGroupRight = view => selectByGroup(view, ltrAtCursor(view)); /** Move the selection head one group forward. */ const selectGroupForward = view => selectByGroup(view, true); /** Move the selection head one group backward. */ const selectGroupBackward = view => selectByGroup(view, false); function selectBySubword(view, forward) { return extendSel(view, range => moveBySubword(view, range, forward)); } /** Move the selection head one group or camel-case subword forward. */ const selectSubwordForward = view => selectBySubword(view, true); /** Move the selection head one group or subword backward. */ const selectSubwordBackward = view => selectBySubword(view, false); /** Move the selection head over the next syntactic element to the left. */ const selectSyntaxLeft = view => extendSel(view, range => moveBySyntax(view.state, range, !ltrAtCursor(view))); /** Move the selection head over the next syntactic element to the right. */ const selectSyntaxRight = view => extendSel(view, range => moveBySyntax(view.state, range, ltrAtCursor(view))); function selectByLine(view, forward) { return extendSel(view, range => view.moveVertically(range, forward)); } /** Move the selection head one line up. */ const selectLineUp = view => selectByLine(view, false); /** Move the selection head one line down. */ const selectLineDown = view => selectByLine(view, true); function selectByPage(view, forward) { return extendSel(view, range => view.moveVertically(range, forward, pageInfo(view).height)); } /** Move the selection head one page up. */ const selectPageUp = view => selectByPage(view, false); /** Move the selection head one page down. */ const selectPageDown = view => selectByPage(view, true); /** Move the selection head to the next line boundary. */ const selectLineBoundaryForward = view => extendSel(view, range => moveByLineBoundary(view, range, true)); /** Move the selection head to the previous line boundary. */ const selectLineBoundaryBackward = view => extendSel(view, range => moveByLineBoundary(view, range, false)); /** Move the selection head one line boundary to the left. */ const selectLineBoundaryLeft = view => extendSel(view, range => moveByLineBoundary(view, range, !ltrAtCursor(view))); /** Move the selection head one line boundary to the right. */ const selectLineBoundaryRight = view => extendSel(view, range => moveByLineBoundary(view, range, ltrAtCursor(view))); /** Move the selection head to the start of the line. */ const selectLineStart = view => extendSel(view, range => _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.cursor(view.lineBlockAt(range.head).from)); /** Move the selection head to the end of the line. */ const selectLineEnd = view => extendSel(view, range => _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.cursor(view.lineBlockAt(range.head).to)); /** Move the selection to the start of the document. */ const cursorDocStart = ({ state, dispatch }) => { dispatch(setSel(state, { anchor: 0 })); return true; }; /** Move the selection to the end of the document. */ const cursorDocEnd = ({ state, dispatch }) => { dispatch(setSel(state, { anchor: state.doc.length })); return true; }; /** Move the selection head to the start of the document. */ const selectDocStart = ({ state, dispatch }) => { dispatch(setSel(state, { anchor: state.selection.main.anchor, head: 0 })); return true; }; /** Move the selection head to the end of the document. */ const selectDocEnd = ({ state, dispatch }) => { dispatch(setSel(state, { anchor: state.selection.main.anchor, head: state.doc.length })); return true; }; /** Select the entire document. */ const selectAll = ({ state, dispatch }) => { dispatch(state.update({ selection: { anchor: 0, head: state.doc.length }, userEvent: "select" })); return true; }; /** Expand the selection to cover entire lines. */ const selectLine = ({ state, dispatch }) => { let ranges = selectedLineBlocks(state).map(({ from, to }) => _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.range(from, Math.min(to + 1, state.doc.length))); dispatch(state.update({ selection: _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.create(ranges), userEvent: "select" })); return true; }; /** Select the next syntactic construct that is larger than the selection. Note that this will only work insofar as the language [provider](https://codemirror.net/6/docs/ref/#language.language) you use builds up a full syntax tree. */ const selectParentSyntax = ({ state, dispatch }) => { let selection = updateSel(state.selection, range => { var _a; let stack = (0,_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .syntaxTree */ .mv)(state).resolveStack(range.from, 1); for (let cur = stack; cur; cur = cur.next) { let { node } = cur; if (((node.from < range.from && node.to >= range.to) || (node.to > range.to && node.from <= range.from)) && ((_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent)) return _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.range(node.to, node.from); } return range; }); dispatch(setSel(state, selection)); return true; }; /** Simplify the current selection. When multiple ranges are selected, reduce it to its main range. Otherwise, if the selection is non-empty, convert it to a cursor selection. */ const simplifySelection = ({ state, dispatch }) => { let cur = state.selection, selection = null; if (cur.ranges.length > 1) selection = _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.create([cur.main]); else if (!cur.main.empty) selection = _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.create([_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.cursor(cur.main.head)]); if (!selection) return false; dispatch(setSel(state, selection)); return true; }; function deleteBy(target, by) { if (target.state.readOnly) return false; let event = "delete.selection", { state } = target; let changes = state.changeByRange(range => { let { from, to } = range; if (from == to) { let towards = by(range); if (towards < from) { event = "delete.backward"; towards = skipAtomic(target, towards, false); } else if (towards > from) { event = "delete.forward"; towards = skipAtomic(target, towards, true); } from = Math.min(from, towards); to = Math.max(to, towards); } else { from = skipAtomic(target, from, false); to = skipAtomic(target, to, true); } return from == to ? { range } : { changes: { from, to }, range: _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.cursor(from, from < range.head ? -1 : 1) }; }); if (changes.changes.empty) return false; target.dispatch(state.update(changes, { scrollIntoView: true, userEvent: event, effects: event == "delete.selection" ? _codemirror_view__WEBPACK_IMPORTED_MODULE_1__.EditorView.announce.of(state.phrase("Selection deleted")) : undefined })); return true; } function skipAtomic(target, pos, forward) { if (target instanceof _codemirror_view__WEBPACK_IMPORTED_MODULE_1__.EditorView) for (let ranges of target.state.facet(_codemirror_view__WEBPACK_IMPORTED_MODULE_1__.EditorView.atomicRanges).map(f => f(target))) ranges.between(pos, pos, (from, to) => { if (from < pos && to > pos) pos = forward ? to : from; }); return pos; } const deleteByChar = (target, forward, byIndentUnit) => deleteBy(target, range => { let pos = range.from, { state } = target, line = state.doc.lineAt(pos), before, targetPos; if (byIndentUnit && !forward && pos > line.from && pos < line.from + 200 && !/[^ \t]/.test(before = line.text.slice(0, pos - line.from))) { if (before[before.length - 1] == "\t") return pos - 1; let col = (0,_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.countColumn)(before, state.tabSize), drop = col % (0,_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .getIndentUnit */ .tp)(state) || (0,_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .getIndentUnit */ .tp)(state); for (let i = 0; i < drop && before[before.length - 1 - i] == " "; i++) pos--; targetPos = pos; } else { targetPos = (0,_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.findClusterBreak)(line.text, pos - line.from, forward, forward) + line.from; if (targetPos == pos && line.number != (forward ? state.doc.lines : 1)) targetPos += forward ? 1 : -1; else if (!forward && /[\ufe00-\ufe0f]/.test(line.text.slice(targetPos - line.from, pos - line.from))) targetPos = (0,_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.findClusterBreak)(line.text, targetPos - line.from, false, false) + line.from; } return targetPos; }); /** Delete the selection, or, for cursor selections, the character or indentation unit before the cursor. */ const deleteCharBackward = view => deleteByChar(view, false, true); /** Delete the selection or the character before the cursor. Does not implement any extended behavior like deleting whole indentation units in one go. */ const deleteCharBackwardStrict = view => deleteByChar(view, false, false); /** Delete the selection or the character after the cursor. */ const deleteCharForward = view => deleteByChar(view, true, false); const deleteByGroup = (target, forward) => deleteBy(target, range => { let pos = range.head, { state } = target, line = state.doc.lineAt(pos); let categorize = state.charCategorizer(pos); for (let cat = null;;) { if (pos == (forward ? line.to : line.from)) { if (pos == range.head && line.number != (forward ? state.doc.lines : 1)) pos += forward ? 1 : -1; break; } let next = (0,_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.findClusterBreak)(line.text, pos - line.from, forward) + line.from; let nextChar = line.text.slice(Math.min(pos, next) - line.from, Math.max(pos, next) - line.from); let nextCat = categorize(nextChar); if (cat != null && nextCat != cat) break; if (nextChar != " " || pos != range.head) cat = nextCat; pos = next; } return pos; }); /** Delete the selection or backward until the end of the next [group](https://codemirror.net/6/docs/ref/#view.EditorView.moveByGroup), only skipping groups of whitespace when they consist of a single space. */ const deleteGroupBackward = target => deleteByGroup(target, false); /** Delete the selection or forward until the end of the next group. */ const deleteGroupForward = target => deleteByGroup(target, true); /** Delete the selection, or, if it is a cursor selection, delete to the end of the line. If the cursor is directly at the end of the line, delete the line break after it. */ const deleteToLineEnd = view => deleteBy(view, range => { let lineEnd = view.lineBlockAt(range.head).to; return range.head < lineEnd ? lineEnd : Math.min(view.state.doc.length, range.head + 1); }); /** Delete the selection, or, if it is a cursor selection, delete to the start of the line. If the cursor is directly at the start of the line, delete the line break before it. */ const deleteToLineStart = view => deleteBy(view, range => { let lineStart = view.lineBlockAt(range.head).from; return range.head > lineStart ? lineStart : Math.max(0, range.head - 1); }); /** Delete the selection, or, if it is a cursor selection, delete to the start of the line or the next line wrap before the cursor. */ const deleteLineBoundaryBackward = view => deleteBy(view, range => { let lineStart = view.moveToLineBoundary(range, false).head; return range.head > lineStart ? lineStart : Math.max(0, range.head - 1); }); /** Delete the selection, or, if it is a cursor selection, delete to the end of the line or the next line wrap after the cursor. */ const deleteLineBoundaryForward = view => deleteBy(view, range => { let lineStart = view.moveToLineBoundary(range, true).head; return range.head < lineStart ? lineStart : Math.min(view.state.doc.length, range.head + 1); }); /** Delete all whitespace directly before a line end from the document. */ const deleteTrailingWhitespace = ({ state, dispatch }) => { if (state.readOnly) return false; let changes = []; for (let pos = 0, prev = "", iter = state.doc.iter();;) { iter.next(); if (iter.lineBreak || iter.done) { let trailing = prev.search(/\s+$/); if (trailing > -1) changes.push({ from: pos - (prev.length - trailing), to: pos }); if (iter.done) break; prev = ""; } else { prev = iter.value; } pos += iter.value.length; } if (!changes.length) return false; dispatch(state.update({ changes, userEvent: "delete" })); return true; }; /** Replace each selection range with a line break, leaving the cursor on the line before the break. */ const splitLine = ({ state, dispatch }) => { if (state.readOnly) return false; let changes = state.changeByRange(range => { return { changes: { from: range.from, to: range.to, insert: _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.Text.of(["", ""]) }, range: _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.cursor(range.from) }; }); dispatch(state.update(changes, { scrollIntoView: true, userEvent: "input" })); return true; }; /** Flip the characters before and after the cursor(s). */ const transposeChars = ({ state, dispatch }) => { if (state.readOnly) return false; let changes = state.changeByRange(range => { if (!range.empty || range.from == 0 || range.from == state.doc.length) return { range }; let pos = range.from, line = state.doc.lineAt(pos); let from = pos == line.from ? pos - 1 : (0,_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.findClusterBreak)(line.text, pos - line.from, false) + line.from; let to = pos == line.to ? pos + 1 : (0,_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.findClusterBreak)(line.text, pos - line.from, true) + line.from; return { changes: { from, to, insert: state.doc.slice(pos, to).append(state.doc.slice(from, pos)) }, range: _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.cursor(to) }; }); if (changes.changes.empty) return false; dispatch(state.update(changes, { scrollIntoView: true, userEvent: "move.character" })); return true; }; function selectedLineBlocks(state) { let blocks = [], upto = -1; for (let range of state.selection.ranges) { let startLine = state.doc.lineAt(range.from), endLine = state.doc.lineAt(range.to); if (!range.empty && range.to == endLine.from) endLine = state.doc.lineAt(range.to - 1); if (upto >= startLine.number) { let prev = blocks[blocks.length - 1]; prev.to = endLine.to; prev.ranges.push(range); } else { blocks.push({ from: startLine.from, to: endLine.to, ranges: [range] }); } upto = endLine.number + 1; } return blocks; } function moveLine(state, dispatch, forward) { if (state.readOnly) return false; let changes = [], ranges = []; for (let block of selectedLineBlocks(state)) { if (forward ? block.to == state.doc.length : block.from == 0) continue; let nextLine = state.doc.lineAt(forward ? block.to + 1 : block.from - 1); let size = nextLine.length + 1; if (forward) { changes.push({ from: block.to, to: nextLine.to }, { from: block.from, insert: nextLine.text + state.lineBreak }); for (let r of block.ranges) ranges.push(_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.range(Math.min(state.doc.length, r.anchor + size), Math.min(state.doc.length, r.head + size))); } else { changes.push({ from: nextLine.from, to: block.from }, { from: block.to, insert: state.lineBreak + nextLine.text }); for (let r of block.ranges) ranges.push(_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.range(r.anchor - size, r.head - size)); } } if (!changes.length) return false; dispatch(state.update({ changes, scrollIntoView: true, selection: _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.create(ranges, state.selection.mainIndex), userEvent: "move.line" })); return true; } /** Move the selected lines up one line. */ const moveLineUp = ({ state, dispatch }) => moveLine(state, dispatch, false); /** Move the selected lines down one line. */ const moveLineDown = ({ state, dispatch }) => moveLine(state, dispatch, true); function copyLine(state, dispatch, forward) { if (state.readOnly) return false; let changes = []; for (let block of selectedLineBlocks(state)) { if (forward) changes.push({ from: block.from, insert: state.doc.slice(block.from, block.to) + state.lineBreak }); else changes.push({ from: block.to, insert: state.lineBreak + state.doc.slice(block.from, block.to) }); } dispatch(state.update({ changes, scrollIntoView: true, userEvent: "input.copyline" })); return true; } /** Create a copy of the selected lines. Keep the selection in the top copy. */ const copyLineUp = ({ state, dispatch }) => copyLine(state, dispatch, false); /** Create a copy of the selected lines. Keep the selection in the bottom copy. */ const copyLineDown = ({ state, dispatch }) => copyLine(state, dispatch, true); /** Delete selected lines. */ const deleteLine = view => { if (view.state.readOnly) return false; let { state } = view, changes = state.changes(selectedLineBlocks(state).map(({ from, to }) => { if (from > 0) from--; else if (to < state.doc.length) to++; return { from, to }; })); let selection = updateSel(state.selection, range => { let dist = undefined; if (view.lineWrapping) { let block = view.lineBlockAt(range.head), pos = view.coordsAtPos(range.head, range.assoc || 1); if (pos) dist = (block.bottom + view.documentTop) - pos.bottom + view.defaultLineHeight / 2; } return view.moveVertically(range, true, dist); }).map(changes); view.dispatch({ changes, selection, scrollIntoView: true, userEvent: "delete.line" }); return true; }; /** Replace the selection with a newline. */ const insertNewline = ({ state, dispatch }) => { dispatch(state.update(state.replaceSelection(state.lineBreak), { scrollIntoView: true, userEvent: "input" })); return true; }; /** Replace the selection with a newline and the same amount of indentation as the line above. */ const insertNewlineKeepIndent = ({ state, dispatch }) => { dispatch(state.update(state.changeByRange(range => { let indent = /^\s*/.exec(state.doc.lineAt(range.from).text)[0]; return { changes: { from: range.from, to: range.to, insert: state.lineBreak + indent }, range: EditorSelection.cursor(range.from + indent.length + 1) }; }), { scrollIntoView: true, userEvent: "input" })); return true; }; function isBetweenBrackets(state, pos) { if (/\(\)|\[\]|\{\}/.test(state.sliceDoc(pos - 1, pos + 1))) return { from: pos, to: pos }; let context = (0,_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .syntaxTree */ .mv)(state).resolveInner(pos); let before = context.childBefore(pos), after = context.childAfter(pos), closedBy; if (before && after && before.to <= pos && after.from >= pos && (closedBy = before.type.prop(_lezer_common__WEBPACK_IMPORTED_MODULE_2__/* .NodeProp */ .uY.closedBy)) && closedBy.indexOf(after.name) > -1 && state.doc.lineAt(before.to).from == state.doc.lineAt(after.from).from && !/\S/.test(state.sliceDoc(before.to, after.from))) return { from: before.to, to: after.from }; return null; } /** Replace the selection with a newline and indent the newly created line(s). If the current line consists only of whitespace, this will also delete that whitespace. When the cursor is between matching brackets, an additional newline will be inserted after the cursor. */ const insertNewlineAndIndent = /*@__PURE__*/newlineAndIndent(false); /** Create a blank, indented line below the current line. */ const insertBlankLine = /*@__PURE__*/newlineAndIndent(true); function newlineAndIndent(atEof) { return ({ state, dispatch }) => { if (state.readOnly) return false; let changes = state.changeByRange(range => { let { from, to } = range, line = state.doc.lineAt(from); let explode = !atEof && from == to && isBetweenBrackets(state, from); if (atEof) from = to = (to <= line.to ? line : state.doc.lineAt(to)).to; let cx = new _codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .IndentContext */ .KB(state, { simulateBreak: from, simulateDoubleBreak: !!explode }); let indent = (0,_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .getIndentation */ ._v)(cx, from); if (indent == null) indent = (0,_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.countColumn)(/^\s*/.exec(state.doc.lineAt(from).text)[0], state.tabSize); while (to < line.to && /\s/.test(line.text[to - line.from])) to++; if (explode) ({ from, to } = explode); else if (from > line.from && from < line.from + 100 && !/\S/.test(line.text.slice(0, from))) from = line.from; let insert = ["", (0,_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .indentString */ .EI)(state, indent)]; if (explode) insert.push((0,_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .indentString */ .EI)(state, cx.lineIndent(line.from, -1))); return { changes: { from, to, insert: _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.Text.of(insert) }, range: _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.cursor(from + 1 + insert[1].length) }; }); dispatch(state.update(changes, { scrollIntoView: true, userEvent: "input" })); return true; }; } function changeBySelectedLine(state, f) { let atLine = -1; return state.changeByRange(range => { let changes = []; for (let pos = range.from; pos <= range.to;) { let line = state.doc.lineAt(pos); if (line.number > atLine && (range.empty || range.to > line.from)) { f(line, changes, range); atLine = line.number; } pos = line.to + 1; } let changeSet = state.changes(changes); return { changes, range: _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.EditorSelection.range(changeSet.mapPos(range.anchor, 1), changeSet.mapPos(range.head, 1)) }; }); } /** Auto-indent the selected lines. This uses the [indentation service facet](https://codemirror.net/6/docs/ref/#language.indentService) as source for auto-indent information. */ const indentSelection = ({ state, dispatch }) => { if (state.readOnly) return false; let updated = Object.create(null); let context = new _codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .IndentContext */ .KB(state, { overrideIndentation: start => { let found = updated[start]; return found == null ? -1 : found; } }); let changes = changeBySelectedLine(state, (line, changes, range) => { let indent = (0,_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .getIndentation */ ._v)(context, line.from); if (indent == null) return; if (!/\S/.test(line.text)) indent = 0; let cur = /^\s*/.exec(line.text)[0]; let norm = (0,_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .indentString */ .EI)(state, indent); if (cur != norm || range.from < line.from + cur.length) { updated[line.from] = indent; changes.push({ from: line.from, to: line.from + cur.length, insert: norm }); } }); if (!changes.changes.empty) dispatch(state.update(changes, { userEvent: "indent" })); return true; }; /** Add a [unit](https://codemirror.net/6/docs/ref/#language.indentUnit) of indentation to all selected lines. */ const indentMore = ({ state, dispatch }) => { if (state.readOnly) return false; dispatch(state.update(changeBySelectedLine(state, (line, changes) => { changes.push({ from: line.from, insert: state.facet(_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .indentUnit */ .Xt) }); }), { userEvent: "input.indent" })); return true; }; /** Remove a [unit](https://codemirror.net/6/docs/ref/#language.indentUnit) of indentation from all selected lines. */ const indentLess = ({ state, dispatch }) => { if (state.readOnly) return false; dispatch(state.update(changeBySelectedLine(state, (line, changes) => { let space = /^\s*/.exec(line.text)[0]; if (!space) return; let col = (0,_codemirror_state__WEBPACK_IMPORTED_MODULE_0__.countColumn)(space, state.tabSize), keep = 0; let insert = (0,_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .indentString */ .EI)(state, Math.max(0, col - (0,_codemirror_language__WEBPACK_IMPORTED_MODULE_3__/* .getIndentUnit */ .tp)(state))); while (keep < space.length && keep < insert.length && space.charCodeAt(keep) == insert.charCodeAt(keep)) keep++; changes.push({ from: line.from + keep, to: line.from + space.length, insert: insert.slice(keep) }); }), { userEvent: "delete.dedent" })); return true; }; /** Enables or disables [tab-focus mode](https://codemirror.net/6/docs/ref/#view.EditorView.setTabFocusMode). While on, this prevents the editor's key bindings from capturing Tab or Shift-Tab, making it possible for the user to move focus out of the editor with the keyboard. */ const toggleTabFocusMode = view => { view.setTabFocusMode(); return true; }; /** Temporarily enables [tab-focus mode](https://codemirror.net/6/docs/ref/#view.EditorView.setTabFocusMode) for two seconds or until another key is pressed. */ const temporarilySetTabFocusMode = view => { view.setTabFocusMode(2000); return true; }; /** Insert a tab character at the cursor or, if something is selected, use [`indentMore`](https://codemirror.net/6/docs/ref/#commands.indentMore) to indent the entire selection. */ const insertTab = ({ state, dispatch }) => { if (state.selection.ranges.some(r => !r.empty)) return indentMore({ state, dispatch }); dispatch(state.update(state.replaceSelection("\t"), { scrollIntoView: true, userEvent: "input" })); return true; }; /** Array of key bindings containing the Emacs-style bindings that are available on macOS by default. - Ctrl-b: [`cursorCharLeft`](https://codemirror.net/6/docs/ref/#commands.cursorCharLeft) ([`selectCharLeft`](https://codemirror.net/6/docs/ref/#commands.selectCharLeft) with Shift) - Ctrl-f: [`cursorCharRight`](https://codemirror.net/6/docs/ref/#commands.cursorCharRight) ([`selectCharRight`](https://codemirror.net/6/docs/ref/#commands.selectCharRight) with Shift) - Ctrl-p: [`cursorLineUp`](https://codemirror.net/6/docs/ref/#commands.cursorLineUp) ([`selectLineUp`](https://codemirror.net/6/docs/ref/#commands.selectLineUp) with Shift) - Ctrl-n: [`cursorLineDown`](https://codemirror.net/6/docs/ref/#commands.cursorLineDown) ([`selectLineDown`](https://codemirror.net/6/docs/ref/#commands.selectLineDown) with Shift) - Ctrl-a: [`cursorLineStart`](https://codemirror.net/6/docs/ref/#commands.cursorLineStart) ([`selectLineStart`](https://codemirror.net/6/docs/ref/#commands.selectLineStart) with Shift) - Ctrl-e: [`cursorLineEnd`](https://codemirror.net/6/docs/ref/#commands.cursorLineEnd) ([`selectLineEnd`](https://codemirror.net/6/docs/ref/#commands.selectLineEnd) with Shift) - Ctrl-d: [`deleteCharForward`](https://codemirror.net/6/docs/ref/#commands.deleteCharForward) - Ctrl-h: [`deleteCharBackward`](https://codemirror.net/6/docs/ref/#commands.deleteCharBackward) - Ctrl-k: [`deleteToLineEnd`](https://codemirror.net/6/docs/ref/#commands.deleteToLineEnd) - Ctrl-Alt-h: [`deleteGroupBackward`](https://codemirror.net/6/docs/ref/#commands.deleteGroupBackward) - Ctrl-o: [`splitLine`](https://codemirror.net/6/docs/ref/#commands.splitLine) - Ctrl-t: [`transposeChars`](https://codemirror.net/6/docs/ref/#commands.transposeChars) - Ctrl-v: [`cursorPageDown`](https://codemirror.net/6/docs/ref/#commands.cursorPageDown) - Alt-v: [`cursorPageUp`](https://codemirror.net/6/docs/ref/#commands.cursorPageUp) */ const emacsStyleKeymap = [ { key: "Ctrl-b", run: cursorCharLeft, shift: selectCharLeft, preventDefault: true }, { key: "Ctrl-f", run: cursorCharRight, shift: selectCharRight }, { key: "Ctrl-p", run: cursorLineUp, shift: selectLineUp }, { key: "Ctrl-n", run: cursorLineDown, shift: selectLineDown }, { key: "Ctrl-a", run: cursorLineStart, shift: selectLineStart }, { key: "Ctrl-e", run: cursorLineEnd, shift: selectLineEnd }, { key: "Ctrl-d", run: deleteCharForward }, { key: "Ctrl-h", run: deleteCharBackward }, { key: "Ctrl-k", run: deleteToLineEnd }, { key: "Ctrl-Alt-h", run: deleteGroupBackward }, { key: "Ctrl-o", run: splitLine }, { key: "Ctrl-t", run: transposeChars }, { key: "Ctrl-v", run: cursorPageDown }, ]; /** An array of key bindings closely sticking to platform-standard or widely used bindings. (This includes the bindings from [`emacsStyleKeymap`](https://codemirror.net/6/docs/ref/#commands.emacsStyleKeymap), with their `key` property changed to `mac`.) - ArrowLeft: [`cursorCharLeft`](https://codemirror.net/6/docs/ref/#commands.cursorCharLeft) ([`selectCharLeft`](https://codemirror.net/6/docs/ref/#commands.selectCharLeft) with Shift) - ArrowRight: [`cursorCharRight`](https://codemirror.net/6/docs/ref/#commands.cursorCharRight) ([`selectCharRight`](https://codemirror.net/6/docs/ref/#commands.selectCharRight) with Shift) - Ctrl-ArrowLeft (Alt-ArrowLeft on macOS): [`cursorGroupLeft`](https://codemirror.net/6/docs/ref/#commands.cursorGroupLeft) ([`selectGroupLeft`](https://codemirror.net/6/docs/ref/#commands.selectGroupLeft) with Shift) - Ctrl-ArrowRight (Alt-ArrowRight on macOS): [`cursorGroupRight`](https://codemirror.net/6/docs/ref/#commands.cursorGroupRight) ([`selectGroupRight`](https://codemirror.net/6/docs/ref/#commands.selectGroupRight) with Shift) - Cmd-ArrowLeft (on macOS): [`cursorLineStart`](https://codemirror.net/6/docs/ref/#commands.cursorLineStart) ([`selectLineStart`](https://codemirror.net/6/docs/ref/#commands.selectLineStart) with Shift) - Cmd-ArrowRight (on macOS): [`cursorLineEnd`](https://codemirror.net/6/docs/ref/#commands.cursorLineEnd) ([`selectLineEnd`](https://codemirror.net/6/docs/ref/#commands.selectLineEnd) with Shift) - ArrowUp: [`cursorLineUp`](https://codemirror.net/6/docs/ref/#commands.cursorLineUp) ([`selectLineUp`](https://codemirror.net/6/docs/ref/#commands.selectLineUp) with Shift) - ArrowDown: [`cursorLineDown`](https://codemirror.net/6/docs/ref/#commands.cursorLineDown) ([`selectLineDown`](https://codemirror.net/6/docs/ref/#commands.selectLineDown) with Shift) - Cmd-ArrowUp (on macOS): [`cursorDocStart`](https://codemirror.net/6/docs/ref/#commands.cursorDocStart) ([`selectDocStart`](https://codemirror.net/6/docs/ref/#commands.selectDocStart) with Shift) - Cmd-ArrowDown (on macOS): [`cursorDocEnd`](https://codemirror.net/6/docs/ref/#commands.cursorDocEnd) ([`selectDocEnd`](https://codemirror.net/6/docs/ref/#commands.selectDocEnd) with Shift) - Ctrl-ArrowUp (on macOS): [`cursorPageUp`](https://codemirror.net/6/docs/ref/#commands.cursorPageUp) ([`selectPageUp`](https://codemirror.net/6/docs/ref/#commands.selectPageUp) with Shift) - Ctrl-ArrowDown (on macOS): [`cursorPageDown`](https://codemirror.net/6/docs/ref/#commands.cursorPageDown) ([`selectPageDown`](https://codemirror.net/6/docs/ref/#commands.selectPageDown) with Shift) - PageUp: [`cursorPageUp`](https://codemirror.net/6/docs/ref/#commands.cursorPageUp) ([`selectPageUp`](https://codemirror.net/6/docs/ref/#commands.selectPageUp) with Shift) - PageDown: [`cursorPageDown`](https://codemirror.net/6/docs/ref/#commands.cursorPageDown) ([`selectPageDown`](https://codemirror.net/6/docs/ref/#commands.selectPageDown) with Shift) - Home: [`cursorLineBoundaryBackward`](https://codemirror.net/6/docs/ref/#commands.cursorLineBoundaryBackward) ([`selectLineBoundaryBackward`](https://codemirror.net/6/docs/ref/#commands.selectLineBoundaryBackward) with Shift) - End: [`cursorLineBoundaryForward`](https://codemirror.net/6/docs/ref/#commands.cursorLineBoundaryForward) ([`selectLineBoundaryForward`](https://codemirror.net/6/docs/ref/#commands.selectLineBoundaryForward) with Shift) - Ctrl-Home (Cmd-Home on macOS): [`cursorDocStart`](https://codemirror.net/6/docs/ref/#commands.cursorDocStart) ([`selectDocStart`](https://codemirror.net/6/docs/ref/#commands.selectDocStart) with Shift) - Ctrl-End (Cmd-Home on macOS): [`cursorDocEnd`](https://codemirror.net/6/docs/ref/#commands.cursorDocEnd) ([`selectDocEnd`](https://codemirror.net/6/docs/ref/#commands.selectDocEnd) with Shift) - Enter: [`insertNewlineAndIndent`](https://codemirror.net/6/docs/ref/#commands.insertNewlineAndIndent) - Ctrl-a (Cmd-a on macOS): [`selectAll`](https://codemirror.net/6/docs/ref/#commands.selectAll) - Backspace: [`deleteCharBackward`](https://codemirror.net/6/docs/ref/#commands.deleteCharBackward) - Delete: [`deleteCharForward`](https://codemirror.net/6/docs/ref/#commands.deleteCharForward) - Ctrl-Backspace (Alt-Backspace on macOS): [`deleteGroupBackward`](https://codemirror.net/6/docs/ref/#commands.deleteGroupBackward) - Ctrl-Delete (Alt-Delete on macOS): [`deleteGroupForward`](https://codemirror.net/6/docs/ref/#commands.deleteGroupForward) - Cmd-Backspace (macOS): [`deleteLineBoundaryBackward`](https://codemirror.net/6/docs/ref/#commands.deleteLineBoundaryBackward). - Cmd-Delete (macOS): [`deleteLineBoundaryForward`](https://codemirror.net/6/docs/ref/#commands.deleteLineBoundaryForward). */ const standardKeymap = /*@__PURE__*/[ { key: "ArrowLeft", run: cursorCharLeft, shift: selectCharLeft, preventDefault: true }, { key: "Mod-ArrowLeft", mac: "Alt-ArrowLeft", run: cursorGroupLeft, shift: selectGroupLeft, preventDefault: true }, { mac: "Cmd-ArrowLeft", run: cursorLineBoundaryLeft, shift: selectLineBoundaryLeft, preventDefault: true }, { key: "ArrowRight", run: cursorCharRight, shift: selectCharRight, preventDefault: true }, { key: "Mod-ArrowRight", mac: "Alt-ArrowRight", run: cursorGroupRight, shift: selectGroupRight, preventDefault: true }, { mac: "Cmd-ArrowRight", run: cursorLineBoundaryRight, shift: selectLineBoundaryRight, preventDefault: true }, { key: "ArrowUp", run: cursorLineUp, shift: selectLineUp, preventDefault: true }, { mac: "Cmd-ArrowUp", run: cursorDocStart, shift: selectDocStart }, { mac: "Ctrl-ArrowUp", run: cursorPageUp, shift: selectPageUp }, { key: "ArrowDown", run: cursorLineDown, shift: selectLineDown, preventDefault: true }, { mac: "Cmd-ArrowDown", run: cursorDocEnd, shift: selectDocEnd }, { mac: "Ctrl-ArrowDown", run: cursorPageDown, shift: selectPageDown }, { key: "PageUp", run: cursorPageUp, shift: selectPageUp }, { key: "PageDown", run: cursorPageDown, shift: selectPageDown }, { key: "Home", run: cursorLineBoundaryBackward, shift: selectLineBoundaryBackward, preventDefault: true }, { key: "Mod-Home", run: cursorDocStart, shift: selectDocStart }, { key: "End", run: cursorLineBoundaryForward, shift: selectLineBoundaryForward, preventDefault: true }, { key: "Mod-End", run: cursorDocEnd, shift: selectDocEnd }, { key: "Enter", run: insertNewlineAndIndent }, { key: "Mod-a", run: selectAll }, { key: "Backspace", run: deleteCharBackward, shift: deleteCharBackward }, { key: "Delete", run: deleteCharForward }, { key: "Mod-Backspace", mac: "Alt-Backspace", run: deleteGroupBackward }, { key: "Mod-Delete", mac: "Alt-Delete", run: deleteGroupForward }, { mac: "Mod-Backspace", run: deleteLineBoundaryBackward }, { mac: "Mod-Delete", run: deleteLineBoundaryForward } ].concat(/*@__PURE__*/emacsStyleKeymap.map(b => ({ mac: b.key, run: b.run, shift: b.shift }))); /** The default keymap. Includes all bindings from [`standardKeymap`](https://codemirror.net/6/docs/ref/#commands.standardKeymap) plus the following: - Alt-ArrowLeft (Ctrl-ArrowLeft on macOS): [`cursorSyntaxLeft`](https://codemirror.net/6/docs/ref/#commands.cursorSyntaxLeft) ([`selectSyntaxLeft`](https://codemirror.net/6/docs/ref/#commands.selectSyntaxLeft) with Shift) - Alt-ArrowRight (Ctrl-ArrowRight on macOS): [`cursorSyntaxRight`](https://codemirror.net/6/docs/ref/#commands.cursorSyntaxRight) ([`selectSyntaxRight`](https://codemirror.net/6/docs/ref/#commands.selectSyntaxRight) with Shift) - Alt-ArrowUp: [`moveLineUp`](https://codemirror.net/6/docs/ref/#commands.moveLineUp) - Alt-ArrowDown: [`moveLineDown`](https://codemirror.net/6/docs/ref/#commands.moveLineDown) - Shift-Alt-ArrowUp: [`copyLineUp`](https://codemirror.net/6/docs/ref/#commands.copyLineUp) - Shift-Alt-ArrowDown: [`copyLineDown`](https://codemirror.net/6/docs/ref/#commands.copyLineDown) - Escape: [`simplifySelection`](https://codemirror.net/6/docs/ref/#commands.simplifySelection) - Ctrl-Enter (Cmd-Enter on macOS): [`insertBlankLine`](https://codemirror.net/6/docs/ref/#commands.insertBlankLine) - Alt-l (Ctrl-l on macOS): [`selectLine`](https://codemirror.net/6/docs/ref/#commands.selectLine) - Ctrl-i (Cmd-i on macOS): [`selectParentSyntax`](https://codemirror.net/6/docs/ref/#commands.selectParentSyntax) - Ctrl-[ (Cmd-[ on macOS): [`indentLess`](https://codemirror.net/6/docs/ref/#commands.indentLess) - Ctrl-] (Cmd-] on macOS): [`indentMore`](https://codemirror.net/6/docs/ref/#commands.indentMore) - Ctrl-Alt-\\ (Cmd-Alt-\\ on macOS): [`indentSelection`](https://codemirror.net/6/docs/ref/#commands.indentSelection) - Shift-Ctrl-k (Shift-Cmd-k on macOS): [`deleteLine`](https://codemirror.net/6/docs/ref/#commands.deleteLine) - Shift-Ctrl-\\ (Shift-Cmd-\\ on macOS): [`cursorMatchingBracket`](https://codemirror.net/6/docs/ref/#commands.cursorMatchingBracket) - Ctrl-/ (Cmd-/ on macOS): [`toggleComment`](https://codemirror.net/6/docs/ref/#commands.toggleComment). - Shift-Alt-a: [`toggleBlockComment`](https://codemirror.net/6/docs/ref/#commands.toggleBlockComment). - Ctrl-m (Alt-Shift-m on macOS): [`toggleTabFocusMode`](https://codemirror.net/6/docs/ref/#commands.toggleTabFocusMode). */ const defaultKeymap = /*@__PURE__*/[ { key: "Alt-ArrowLeft", mac: "Ctrl-ArrowLeft", run: cursorSyntaxLeft, shift: selectSyntaxLeft }, { key: "Alt-ArrowRight", mac: "Ctrl-ArrowRight", run: cursorSyntaxRight, shift: selectSyntaxRight }, { key: "Alt-ArrowUp", run: moveLineUp }, { key: "Shift-Alt-ArrowUp", run: copyLineUp }, { key: "Alt-ArrowDown", run: moveLineDown }, { key: "Shift-Alt-ArrowDown", run: copyLineDown }, { key: "Escape", run: simplifySelection }, { key: "Mod-Enter", run: insertBlankLine }, { key: "Alt-l", mac: "Ctrl-l", run: selectLine }, { key: "Mod-i", run: selectParentSyntax, preventDefault: true }, { key: "Mod-[", run: indentLess }, { key: "Mod-]", run: indentMore }, { key: "Mod-Alt-\\", run: indentSelection }, { key: "Shift-Mod-k", run: deleteLine }, { key: "Shift-Mod-\\", run: cursorMatchingBracket }, { key: "Mod-/", run: toggleComment }, { key: "Alt-A", run: toggleBlockComment }, { key: "Ctrl-m", mac: "Shift-Alt-m", run: toggleTabFocusMode }, ].concat(standardKeymap); /** A binding that binds Tab to [`indentMore`](https://codemirror.net/6/docs/ref/#commands.indentMore) and Shift-Tab to [`indentLess`](https://codemirror.net/6/docs/ref/#commands.indentLess). Please see the [Tab example](../../examples/tab/) before using this. */ const indentWithTab = { key: "Tab", run: indentMore, shift: indentLess }; /***/ }), /***/ 194: /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { // EXPORTS __webpack_require__.d(__webpack_exports__, { KB: () => (/* binding */ IndentContext), SG: () => (/* binding */ bracketMatching), Zt: () => (/* binding */ defaultHighlightStyle), Lv: () => (/* binding */ foldGutter), f7: () => (/* binding */ foldKeymap), tp: () => (/* binding */ getIndentUnit), _v: () => (/* binding */ getIndentation), WD: () => (/* binding */ indentOnInput), EI: () => (/* binding */ indentString), Xt: () => (/* binding */ indentUnit), jU: () => (/* binding */ matchBrackets), y9: () => (/* binding */ syntaxHighlighting), mv: () => (/* binding */ syntaxTree) }); // UNUSED EXPORTS: DocInput, HighlightStyle, LRLanguage, Language, LanguageDescription, LanguageSupport, ParseContext, StreamLanguage, StringStream, TreeIndentContext, bidiIsolates, bracketMatchingHandle, codeFolding, continuedIndent, defineLanguageFacet, delimitedIndent, ensureSyntaxTree, flatIndent, foldAll, foldCode, foldEffect, foldInside, foldNodeProp, foldService, foldState, foldable, foldedRanges, forceParsing, highlightingFor, indentNodeProp, indentRange, indentService, language, languageDataProp, sublanguageProp, syntaxParserRunning, syntaxTreeAvailable, toggleFold, unfoldAll, unfoldCode, unfoldEffect // EXTERNAL MODULE: ../node_modules/@lezer/common/dist/index.js var dist = __webpack_require__(203); // EXTERNAL MODULE: external {"root":["CM","@codemirror/state"],"commonjs":"@codemirror/state","commonjs2":"@codemirror/state"} var state_ = __webpack_require__(60); // EXTERNAL MODULE: external {"root":["CM","@codemirror/view"],"commonjs":"@codemirror/view","commonjs2":"@codemirror/view"} var view_ = __webpack_require__(730); ;// CONCATENATED MODULE: ../node_modules/@lezer/highlight/dist/index.js let nextTagID = 0; /** Highlighting tags are markers that denote a highlighting category. They are [associated](#highlight.styleTags) with parts of a syntax tree by a language mode, and then mapped to an actual CSS style by a [highlighter](#highlight.Highlighter). Because syntax tree node types and highlight styles have to be able to talk the same language, CodeMirror uses a mostly _closed_ [vocabulary](#highlight.tags) of syntax tags (as opposed to traditional open string-based systems, which make it hard for highlighting themes to cover all the tokens produced by the various languages). It _is_ possible to [define](#highlight.Tag^define) your own highlighting tags for system-internal use (where you control both the language package and the highlighter), but such tags will not be picked up by regular highlighters (though you can derive them from standard tags to allow highlighters to fall back to those). */ class Tag { /** @internal */ constructor( /** The set of this tag and all its parent tags, starting with this one itself and sorted in order of decreasing specificity. */ set, /** The base unmodified tag that this one is based on, if it's modified @internal */ base, /** The modifiers applied to this.base @internal */ modified) { this.set = set; this.base = base; this.modified = modified; /** @internal */ this.id = nextTagID++; } /** Define a new tag. If `parent` is given, the tag is treated as a sub-tag of that parent, and [highlighters](#highlight.tagHighlighter) that don't mention this tag will try to fall back to the parent tag (or grandparent tag, etc). */ static define(parent) { if (parent === null || parent === void 0 ? void 0 : parent.base) throw new Error("Can not derive from a modified tag"); let tag = new Tag([], null, []); tag.set.push(tag); if (parent) for (let t of parent.set) tag.set.push(t); return tag; } /** Define a tag _modifier_, which is a function that, given a tag, will return a tag that is a subtag of the original. Applying the same modifier to a twice tag will return the same value (`m1(t1) == m1(t1)`) and applying multiple modifiers will, regardless or order, produce the same tag (`m1(m2(t1)) == m2(m1(t1))`). When multiple modifiers are applied to a given base tag, each smaller set of modifiers is registered as a parent, so that for example `m1(m2(m3(t1)))` is a subtype of `m1(m2(t1))`, `m1(m3(t1)`, and so on. */ static defineModifier() { let mod = new Modifier; return (tag) => { if (tag.modified.indexOf(mod) > -1) return tag; return Modifier.get(tag.base || tag, tag.modified.concat(mod).sort((a, b) => a.id - b.id)); }; } } let nextModifierID = 0; class Modifier { constructor() { this.instances = []; this.id = nextModifierID++; } static get(base, mods) { if (!mods.length) return base; let exists = mods[0].instances.find(t => t.base == base && sameArray(mods, t.modified)); if (exists) return exists; let set = [], tag = new Tag(set, base, mods); for (let m of mods) m.instances.push(tag); let configs = powerSet(mods); for (let parent of base.set) if (!parent.modified.length) for (let config of configs) set.push(Modifier.get(parent, config)); return tag; } } function sameArray(a, b) { return a.length == b.length && a.every((x, i) => x == b[i]); } function powerSet(array) { let sets = [[]]; for (let i = 0; i < array.length; i++) { for (let j = 0, e = sets.length; j < e; j++) { sets.push(sets[j].concat(array[i])); } } return sets.sort((a, b) => b.length - a.length); } /** This function is used to add a set of tags to a language syntax via [`NodeSet.extend`](#common.NodeSet.extend) or [`LRParser.configure`](#lr.LRParser.configure). The argument object maps node selectors to [highlighting tags](#highlight.Tag) or arrays of tags. Node selectors may hold one or more (space-separated) node paths. Such a path can be a [node name](#common.NodeType.name), or multiple node names (or `*` wildcards) separated by slash characters, as in `"Block/Declaration/VariableName"`. Such a path matches the final node but only if its direct parent nodes are the other nodes mentioned. A `*` in such a path matches any parent, but only a single level—wildcards that match multiple parents aren't supported, both for efficiency reasons and because Lezer trees make it rather hard to reason about what they would match.) A path can be ended with `/...` to indicate that the tag assigned to the node should also apply to all child nodes, even if they match their own style (by default, only the innermost style is used). When a path ends in `!`, as in `Attribute!`, no further matching happens for the node's child nodes, and the entire node gets the given style. In this notation, node names that contain `/`, `!`, `*`, or `...` must be quoted as JSON strings. For example: ```javascript parser.withProps( styleTags({ // Style Number and BigNumber nodes "Number BigNumber": tags.number, // Style Escape nodes whose parent is String "String/Escape": tags.escape, // Style anything inside Attributes nodes "Attributes!": tags.meta, // Add a style to all content inside Italic nodes "Italic/...": tags.emphasis, // Style InvalidString nodes as both `string` and `invalid` "InvalidString": [tags.string, tags.invalid], // Style the node named "/" as punctuation '"/"': tags.punctuation }) ) ``` */ function styleTags(spec) { let byName = Object.create(null); for (let prop in spec) { let tags = spec[prop]; if (!Array.isArray(tags)) tags = [tags]; for (let part of prop.split(" ")) if (part) { let pieces = [], mode = 2 /* Mode.Normal */, rest = part; for (let pos = 0;;) { if (rest == "..." && pos > 0 && pos + 3 == part.length) { mode = 1 /* Mode.Inherit */; break; } let m = /^"(?:[^"\\]|\\.)*?"|[^\/!]+/.exec(rest); if (!m) throw new RangeError("Invalid path: " + part); pieces.push(m[0] == "*" ? "" : m[0][0] == '"' ? JSON.parse(m[0]) : m[0]); pos += m[0].length; if (pos == part.length) break; let next = part[pos++]; if (pos == part.length && next == "!") { mode = 0 /* Mode.Opaque */; break; } if (next != "/") throw new RangeError("Invalid path: " + part); rest = part.slice(pos); } let last = pieces.length - 1, inner = pieces[last]; if (!inner) throw new RangeError("Invalid path: " + part); let rule = new Rule(tags, mode, last > 0 ? pieces.slice(0, last) : null); byName[inner] = rule.sort(byName[inner]); } } return ruleNodeProp.add(byName); } const ruleNodeProp = new dist/* NodeProp */.uY(); class Rule { constructor(tags, mode, context, next) { this.tags = tags; this.mode = mode; this.context = context; this.next = next; } get opaque() { return this.mode == 0 /* Mode.Opaque */; } get inherit() { return this.mode == 1 /* Mode.Inherit */; } sort(other) { if (!other || other.depth < this.depth) { this.next = other; return this; } other.next = this.sort(other.next); return other; } get depth() { return this.context ? this.context.length : 0; } } Rule.empty = new Rule([], 2 /* Mode.Normal */, null); /** Define a [highlighter](#highlight.Highlighter) from an array of tag/class pairs. Classes associated with more specific tags will take precedence. */ function tagHighlighter(tags, options) { let map = Object.create(null); for (let style of tags) { if (!Array.isArray(style.tag)) map[style.tag.id] = style.class; else for (let tag of style.tag) map[tag.id] = style.class; } let { scope, all = null } = options || {}; return { style: (tags) => { let cls = all; for (let tag of tags) { for (let sub of tag.set) { let tagClass = map[sub.id]; if (tagClass) { cls = cls ? cls + " " + tagClass : tagClass; break; } } } return cls; }, scope }; } function highlightTags(highlighters, tags) { let result = null; for (let highlighter of highlighters) { let value = highlighter.style(tags); if (value) result = result ? result + " " + value : value; } return result; } /** Highlight the given [tree](#common.Tree) with the given [highlighter](#highlight.Highlighter). Often, the higher-level [`highlightCode`](#highlight.highlightCode) function is easier to use. */ function highlightTree(tree, highlighter, /** Assign styling to a region of the text. Will be called, in order of position, for any ranges where more than zero classes apply. `classes` is a space separated string of CSS classes. */ putStyle, /** The start of the range to highlight. */ from = 0, /** The end of the range. */ to = tree.length) { let builder = new HighlightBuilder(from, Array.isArray(highlighter) ? highlighter : [highlighter], putStyle); builder.highlightRange(tree.cursor(), from, to, "", builder.highlighters); builder.flush(to); } /** Highlight the given tree with the given highlighter, calling `putText` for every piece of text, either with a set of classes or with the empty string when unstyled, and `putBreak` for every line break. */ function highlightCode(code, tree, highlighter, putText, putBreak, from = 0, to = code.length) { let pos = from; function writeTo(p, classes) { if (p <= pos) return; for (let text = code.slice(pos, p), i = 0;;) { let nextBreak = text.indexOf("\n", i); let upto = nextBreak < 0 ? text.length : nextBreak; if (upto > i) putText(text.slice(i, upto), classes); if (nextBreak < 0) break; putBreak(); i = nextBreak + 1; } pos = p; } highlightTree(tree, highlighter, (from, to, classes) => { writeTo(from, ""); writeTo(to, classes); }, from, to); writeTo(to, ""); } class HighlightBuilder { constructor(at, highlighters, span) { this.at = at; this.highlighters = highlighters; this.span = span; this.class = ""; } startSpan(at, cls) { if (cls != this.class) { this.flush(at); if (at > this.at) this.at = at; this.class = cls; } } flush(to) { if (to > this.at && this.class) this.span(this.at, to, this.class); } highlightRange(cursor, from, to, inheritedClass, highlighters) { let { type, from: start, to: end } = cursor; if (start >= to || end <= from) return; if (type.isTop) highlighters = this.highlighters.filter(h => !h.scope || h.scope(type)); let cls = inheritedClass; let rule = getStyleTags(cursor) || Rule.empty; let tagCls = highlightTags(highlighters, rule.tags); if (tagCls) { if (cls) cls += " "; cls += tagCls; if (rule.mode == 1 /* Mode.Inherit */) inheritedClass += (inheritedClass ? " " : "") + tagCls; } this.startSpan(Math.max(from, start), cls); if (rule.opaque) return; let mounted = cursor.tree && cursor.tree.prop(dist/* NodeProp */.uY.mounted); if (mounted && mounted.overlay) { let inner = cursor.node.enter(mounted.overlay[0].from + start, 1); let innerHighlighters = this.highlighters.filter(h => !h.scope || h.scope(mounted.tree.type)); let hasChild = cursor.firstChild(); for (let i = 0, pos = start;; i++) { let next = i < mounted.overlay.length ? mounted.overlay[i] : null; let nextPos = next ? next.from + start : end; let rangeFrom = Math.max(from, pos), rangeTo = Math.min(to, nextPos); if (rangeFrom < rangeTo && hasChild) { while (cursor.from < rangeTo) { this.highlightRange(cursor, rangeFrom, rangeTo, inheritedClass, highlighters); this.startSpan(Math.min(rangeTo, cursor.to), cls); if (cursor.to >= nextPos || !cursor.nextSibling()) break; } } if (!next || nextPos > to) break; pos = next.to + start; if (pos > from) { this.highlightRange(inner.cursor(), Math.max(from, next.from + start), Math.min(to, pos), "", innerHighlighters); this.startSpan(Math.min(to, pos), cls); } } if (hasChild) cursor.parent(); } else if (cursor.firstChild()) { if (mounted) inheritedClass = ""; do { if (cursor.to <= from) continue; if (cursor.from >= to) break; this.highlightRange(cursor, from, to, inheritedClass, highlighters); this.startSpan(Math.min(to, cursor.to), cls); } while (cursor.nextSibling()); cursor.parent(); } } } /** Match a syntax node's [highlight rules](#highlight.styleTags). If there's a match, return its set of tags, and whether it is opaque (uses a `!`) or applies to all child nodes (`/...`). */ function getStyleTags(node) { let rule = node.type.prop(ruleNodeProp); while (rule && rule.context && !node.matchContext(rule.context)) rule = rule.next; return rule || null; } const t = Tag.define; const comment = t(), dist_name = t(), typeName = t(dist_name), propertyName = t(dist_name), literal = t(), string = t(literal), number = t(literal), content = t(), heading = t(content), keyword = t(), operator = t(), punctuation = t(), bracket = t(punctuation), meta = t(); /** The default set of highlighting [tags](#highlight.Tag). This collection is heavily biased towards programming languages, and necessarily incomplete. A full ontology of syntactic constructs would fill a stack of books, and be impractical to write themes for. So try to make do with this set. If all else fails, [open an issue](https://github.com/codemirror/codemirror.next) to propose a new tag, or [define](#highlight.Tag^define) a local custom tag for your use case. Note that it is not obligatory to always attach the most specific tag possible to an element—if your grammar can't easily distinguish a certain type of element (such as a local variable), it is okay to style it as its more general variant (a variable). For tags that extend some parent tag, the documentation links to the parent. */ const tags = { /** A comment. */ comment, /** A line [comment](#highlight.tags.comment). */ lineComment: t(comment), /** A block [comment](#highlight.tags.comment). */ blockComment: t(comment), /** A documentation [comment](#highlight.tags.comment). */ docComment: t(comment), /** Any kind of identifier. */ name: dist_name, /** The [name](#highlight.tags.name) of a variable. */ variableName: t(dist_name), /** A type [name](#highlight.tags.name). */ typeName: typeName, /** A tag name (subtag of [`typeName`](#highlight.tags.typeName)). */ tagName: t(typeName), /** A property or field [name](#highlight.tags.name). */ propertyName: propertyName, /** An attribute name (subtag of [`propertyName`](#highlight.tags.propertyName)). */ attributeName: t(propertyName), /** The [name](#highlight.tags.name) of a class. */ className: t(dist_name), /** A label [name](#highlight.tags.name). */ labelName: t(dist_name), /** A namespace [name](#highlight.tags.name). */ namespace: t(dist_name), /** The [name](#highlight.tags.name) of a macro. */ macroName: t(dist_name), /** A literal value. */ literal, /** A string [literal](#highlight.tags.literal). */ string, /** A documentation [string](#highlight.tags.string). */ docString: t(string), /** A character literal (subtag of [string](#highlight.tags.string)). */ character: t(string), /** An attribute value (subtag of [string](#highlight.tags.string)). */ attributeValue: t(string), /** A number [literal](#highlight.tags.literal). */ number, /** An integer [number](#highlight.tags.number) literal. */ integer: t(number), /** A floating-point [number](#highlight.tags.number) literal. */ float: t(number), /** A boolean [literal](#highlight.tags.literal). */ bool: t(literal), /** Regular expression [literal](#highlight.tags.literal). */ regexp: t(literal), /** An escape [literal](#highlight.tags.literal), for example a backslash escape in a string. */ escape: t(literal), /** A color [literal](#highlight.tags.literal). */ color: t(literal), /** A URL [literal](#highlight.tags.literal). */ url: t(literal), /** A language keyword. */ keyword, /** The [keyword](#highlight.tags.keyword) for the self or this object. */ self: t(keyword), /** The [keyword](#highlight.tags.keyword) for null. */ null: t(keyword), /** A [keyword](#highlight.tags.keyword) denoting some atomic value. */ atom: t(keyword), /** A [keyword](#highlight.tags.keyword) that represents a unit. */ unit: t(keyword), /** A modifier [keyword](#highlight.tags.keyword). */ modifier: t(keyword), /** A [keyword](#highlight.tags.keyword) that acts as an operator. */ operatorKeyword: t(keyword), /** A control-flow related [keyword](#highlight.tags.keyword). */ controlKeyword: t(keyword), /** A [keyword](#highlight.tags.keyword) that defines something. */ definitionKeyword: t(keyword), /** A [keyword](#highlight.tags.keyword) related to defining or interfacing with modules. */ moduleKeyword: t(keyword), /** An operator. */ operator, /** An [operator](#highlight.tags.operator) that dereferences something. */ derefOperator: t(operator), /** Arithmetic-related [operator](#highlight.tags.operator). */ arithmeticOperator: t(operator), /** Logical [operator](#highlight.tags.operator). */ logicOperator: t(operator), /** Bit [operator](#highlight.tags.operator). */ bitwiseOperator: t(operator), /** Comparison [operator](#highlight.tags.operator). */ compareOperator: t(operator), /** [Operator](#highlight.tags.operator) that updates its operand. */ updateOperator: t(operator), /** [Operator](#highlight.tags.operator) that defines something. */ definitionOperator: t(operator), /** Type-related [operator](#highlight.tags.operator). */ typeOperator: t(operator), /** Control-flow [operator](#highlight.tags.operator). */ controlOperator: t(operator), /** Program or markup punctuation. */ punctuation, /** [Punctuation](#highlight.tags.punctuation) that separates things. */ separator: t(punctuation), /** Bracket-style [punctuation](#highlight.tags.punctuation). */ bracket, /** Angle [brackets](#highlight.tags.bracket) (usually `<` and `>` tokens). */ angleBracket: t(bracket), /** Square [brackets](#highlight.tags.bracket) (usually `[` and `]` tokens). */ squareBracket: t(bracket), /** Parentheses (usually `(` and `)` tokens). Subtag of [bracket](#highlight.tags.bracket). */ paren: t(bracket), /** Braces (usually `{` and `}` tokens). Subtag of [bracket](#highlight.tags.bracket). */ brace: t(bracket), /** Content, for example plain text in XML or markup documents. */ content, /** [Content](#highlight.tags.content) that represents a heading. */ heading, /** A level 1 [heading](#highlight.tags.heading). */ heading1: t(heading), /** A level 2 [heading](#highlight.tags.heading). */ heading2: t(heading), /** A level 3 [heading](#highlight.tags.heading). */ heading3: t(heading), /** A level 4 [heading](#highlight.tags.heading). */ heading4: t(heading), /** A level 5 [heading](#highlight.tags.heading). */ heading5: t(heading), /** A level 6 [heading](#highlight.tags.heading). */ heading6: t(heading), /** A prose separator (such as a horizontal rule). */ contentSeparator: t(content), /** [Content](#highlight.tags.content) that represents a list. */ list: t(content), /** [Content](#highlight.tags.content) that represents a quote. */ quote: t(content), /** [Content](#highlight.tags.content) that is emphasized. */ emphasis: t(content), /** [Content](#highlight.tags.content) that is styled strong. */ strong: t(content), /** [Content](#highlight.tags.content) that is part of a link. */ link: t(content), /** [Content](#highlight.tags.content) that is styled as code or monospace. */ monospace: t(content), /** [Content](#highlight.tags.content) that has a strike-through style. */ strikethrough: t(content), /** Inserted text in a change-tracking format. */ inserted: t(), /** Deleted text. */ deleted: t(), /** Changed text. */ changed: t(), /** An invalid or unsyntactic element. */ invalid: t(), /** Metadata or meta-instruction. */ meta, /** [Metadata](#highlight.tags.meta) that applies to the entire document. */ documentMeta: t(meta), /** [Metadata](#highlight.tags.meta) that annotates or adds attributes to a given syntactic element. */ annotation: t(meta), /** Processing instruction or preprocessor directive. Subtag of [meta](#highlight.tags.meta). */ processingInstruction: t(meta), /** [Modifier](#highlight.Tag^defineModifier) that indicates that a given element is being defined. Expected to be used with the various [name](#highlight.tags.name) tags. */ definition: Tag.defineModifier(), /** [Modifier](#highlight.Tag^defineModifier) that indicates that something is constant. Mostly expected to be used with [variable names](#highlight.tags.variableName). */ constant: Tag.defineModifier(), /** [Modifier](#highlight.Tag^defineModifier) used to indicate that a [variable](#highlight.tags.variableName) or [property name](#highlight.tags.propertyName) is being called or defined as a function. */ function: Tag.defineModifier(), /** [Modifier](#highlight.Tag^defineModifier) that can be applied to [names](#highlight.tags.name) to indicate that they belong to the language's standard environment. */ standard: Tag.defineModifier(), /** [Modifier](#highlight.Tag^defineModifier) that indicates a given [names](#highlight.tags.name) is local to some scope. */ local: Tag.defineModifier(), /** A generic variant [modifier](#highlight.Tag^defineModifier) that can be used to tag language-specific alternative variants of some common tag. It is recommended for themes to define special forms of at least the [string](#highlight.tags.string) and [variable name](#highlight.tags.variableName) tags, since those come up a lot. */ special: Tag.defineModifier() }; /** This is a highlighter that adds stable, predictable classes to tokens, for styling with external CSS. The following tags are mapped to their name prefixed with `"tok-"` (for example `"tok-comment"`): * [`link`](#highlight.tags.link) * [`heading`](#highlight.tags.heading) * [`emphasis`](#highlight.tags.emphasis) * [`strong`](#highlight.tags.strong) * [`keyword`](#highlight.tags.keyword) * [`atom`](#highlight.tags.atom) * [`bool`](#highlight.tags.bool) * [`url`](#highlight.tags.url) * [`labelName`](#highlight.tags.labelName) * [`inserted`](#highlight.tags.inserted) * [`deleted`](#highlight.tags.deleted) * [`literal`](#highlight.tags.literal) * [`string`](#highlight.tags.string) * [`number`](#highlight.tags.number) * [`variableName`](#highlight.tags.variableName) * [`typeName`](#highlight.tags.typeName) * [`namespace`](#highlight.tags.namespace) * [`className`](#highlight.tags.className) * [`macroName`](#highlight.tags.macroName) * [`propertyName`](#highlight.tags.propertyName) * [`operator`](#highlight.tags.operator) * [`comment`](#highlight.tags.comment) * [`meta`](#highlight.tags.meta) * [`punctuation`](#highlight.tags.punctuation) * [`invalid`](#highlight.tags.invalid) In addition, these mappings are provided: * [`regexp`](#highlight.tags.regexp), [`escape`](#highlight.tags.escape), and [`special`](#highlight.tags.special)[`(string)`](#highlight.tags.string) are mapped to `"tok-string2"` * [`special`](#highlight.tags.special)[`(variableName)`](#highlight.tags.variableName) to `"tok-variableName2"` * [`local`](#highlight.tags.local)[`(variableName)`](#highlight.tags.variableName) to `"tok-variableName tok-local"` * [`definition`](#highlight.tags.definition)[`(variableName)`](#highlight.tags.variableName) to `"tok-variableName tok-definition"` * [`definition`](#highlight.tags.definition)[`(propertyName)`](#highlight.tags.propertyName) to `"tok-propertyName tok-definition"` */ const classHighlighter = tagHighlighter([ { tag: tags.link, class: "tok-link" }, { tag: tags.heading, class: "tok-heading" }, { tag: tags.emphasis, class: "tok-emphasis" }, { tag: tags.strong, class: "tok-strong" }, { tag: tags.keyword, class: "tok-keyword" }, { tag: tags.atom, class: "tok-atom" }, { tag: tags.bool, class: "tok-bool" }, { tag: tags.url, class: "tok-url" }, { tag: tags.labelName, class: "tok-labelName" }, { tag: tags.inserted, class: "tok-inserted" }, { tag: tags.deleted, class: "tok-deleted" }, { tag: tags.literal, class: "tok-literal" }, { tag: tags.string, class: "tok-string" }, { tag: tags.number, class: "tok-number" }, { tag: [tags.regexp, tags.escape, tags.special(tags.string)], class: "tok-string2" }, { tag: tags.variableName, class: "tok-variableName" }, { tag: tags.local(tags.variableName), class: "tok-variableName tok-local" }, { tag: tags.definition(tags.variableName), class: "tok-variableName tok-definition" }, { tag: tags.special(tags.variableName), class: "tok-variableName2" }, { tag: tags.definition(tags.propertyName), class: "tok-propertyName tok-definition" }, { tag: tags.typeName, class: "tok-typeName" }, { tag: tags.namespace, class: "tok-namespace" }, { tag: tags.className, class: "tok-className" }, { tag: tags.macroName, class: "tok-macroName" }, { tag: tags.propertyName, class: "tok-propertyName" }, { tag: tags.operator, class: "tok-operator" }, { tag: tags.comment, class: "tok-comment" }, { tag: tags.meta, class: "tok-meta" }, { tag: tags.invalid, class: "tok-invalid" }, { tag: tags.punctuation, class: "tok-punctuation" } ]); ;// CONCATENATED MODULE: ../node_modules/style-mod/src/style-mod.js const C = "\u037c" const COUNT = typeof Symbol == "undefined" ? "__" + C : Symbol.for(C) const SET = typeof Symbol == "undefined" ? "__styleSet" + Math.floor(Math.random() * 1e8) : Symbol("styleSet") const style_mod_top = typeof globalThis != "undefined" ? globalThis : typeof window != "undefined" ? window : {} // :: - Style modules encapsulate a set of CSS rules defined from // JavaScript. Their definitions are only available in a given DOM // root after it has been _mounted_ there with `StyleModule.mount`. // // Style modules should be created once and stored somewhere, as // opposed to re-creating them every time you need them. The amount of // CSS rules generated for a given DOM root is bounded by the amount // of style modules that were used. So to avoid leaking rules, don't // create these dynamically, but treat them as one-time allocations. class StyleModule { // :: (Object