From 83b321ec47f1662b67ee16663e6c58cee4757355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Preu=C3=9F?= <1371300+Bizarrus@users.noreply.github.com> Date: Thu, 22 Aug 2024 12:38:03 +0200 Subject: [PATCH] Fix editor --- .gitignore | 2 +- default/js/codemirror/README.md | 6 + default/js/codemirror/build/bundle.js | 3862 ++++++++++++++++++++---- default/js/codemirror/package.json | 10 +- default/js/codemirror/rollup.config.js | 15 +- default/js/codemirror/source | 1 - default/js/codemirror/src/highlight.js | 38 + default/js/codemirror/src/index.html | 81 + default/js/codemirror/src/main.js | 87 + default/js/codemirror/src/theme.js | 178 ++ 10 files changed, 3600 insertions(+), 680 deletions(-) create mode 100644 default/js/codemirror/README.md delete mode 160000 default/js/codemirror/source create mode 100644 default/js/codemirror/src/highlight.js create mode 100644 default/js/codemirror/src/index.html create mode 100644 default/js/codemirror/src/main.js create mode 100644 default/js/codemirror/src/theme.js diff --git a/.gitignore b/.gitignore index 95b7725..f6920b6 100644 --- a/.gitignore +++ b/.gitignore @@ -8,5 +8,5 @@ .fruithost .idea/* temp/* -/default/js/codemirror/node_modules +default/js/codemirror/node_modules/ default/js/codemirror/package-lock.json diff --git a/default/js/codemirror/README.md b/default/js/codemirror/README.md new file mode 100644 index 0000000..31324a1 --- /dev/null +++ b/default/js/codemirror/README.md @@ -0,0 +1,6 @@ +# How to Build? + +> npm install +> npm start + +The builded editor will be bundled on `build/bundle.js`. \ No newline at end of file diff --git a/default/js/codemirror/build/bundle.js b/default/js/codemirror/build/bundle.js index d724a16..88f3955 100644 --- a/default/js/codemirror/build/bundle.js +++ b/default/js/codemirror/build/bundle.js @@ -5367,7 +5367,7 @@ } return changed; } - function getAttrs(dom) { + function getAttrs$1(dom) { let attrs = Object.create(null); for (let i = 0; i < dom.attributes.length; i++) { let attr = dom.attributes[i]; @@ -7551,7 +7551,7 @@ else if (parent != view.contentDOM) marks.push({ node: parent, deco: new MarkDecoration({ inclusive: true, - attributes: getAttrs(parent), + attributes: getAttrs$1(parent), tagName: parent.tagName.toLowerCase() }) }); else @@ -16859,7 +16859,415 @@ get lineChunks() { return false; } read(from, to) { return this.string.slice(from, to); } } - new NodeProp({ perNode: true }); + + /** + Create a parse wrapper that, after the inner parse completes, + scans its tree for mixed language regions with the `nest` + function, runs the resulting [inner parses](#common.NestedParse), + and then [mounts](#common.NodeProp^mounted) their results onto the + tree. + */ + function parseMixed(nest) { + return (parse, input, fragments, ranges) => new MixedParse(parse, nest, input, fragments, ranges); + } + class InnerParse { + constructor(parser, parse, overlay, target, from) { + this.parser = parser; + this.parse = parse; + this.overlay = overlay; + this.target = target; + this.from = from; + } + } + function checkRanges(ranges) { + if (!ranges.length || ranges.some(r => r.from >= r.to)) + throw new RangeError("Invalid inner parse ranges given: " + JSON.stringify(ranges)); + } + class ActiveOverlay { + constructor(parser, predicate, mounts, index, start, target, prev) { + this.parser = parser; + this.predicate = predicate; + this.mounts = mounts; + this.index = index; + this.start = start; + this.target = target; + this.prev = prev; + this.depth = 0; + this.ranges = []; + } + } + const stoppedInner = new NodeProp({ perNode: true }); + class MixedParse { + constructor(base, nest, input, fragments, ranges) { + this.nest = nest; + this.input = input; + this.fragments = fragments; + this.ranges = ranges; + this.inner = []; + this.innerDone = 0; + this.baseTree = null; + this.stoppedAt = null; + this.baseParse = base; + } + advance() { + if (this.baseParse) { + let done = this.baseParse.advance(); + if (!done) + return null; + this.baseParse = null; + this.baseTree = done; + this.startInner(); + if (this.stoppedAt != null) + for (let inner of this.inner) + inner.parse.stopAt(this.stoppedAt); + } + if (this.innerDone == this.inner.length) { + let result = this.baseTree; + if (this.stoppedAt != null) + result = new Tree(result.type, result.children, result.positions, result.length, result.propValues.concat([[stoppedInner, this.stoppedAt]])); + return result; + } + let inner = this.inner[this.innerDone], done = inner.parse.advance(); + if (done) { + this.innerDone++; + // This is a somewhat dodgy but super helpful hack where we + // patch up nodes created by the inner parse (and thus + // presumably not aliased anywhere else) to hold the information + // about the inner parse. + let props = Object.assign(Object.create(null), inner.target.props); + props[NodeProp.mounted.id] = new MountedTree(done, inner.overlay, inner.parser); + inner.target.props = props; + } + return null; + } + get parsedPos() { + if (this.baseParse) + return 0; + let pos = this.input.length; + for (let i = this.innerDone; i < this.inner.length; i++) { + if (this.inner[i].from < pos) + pos = Math.min(pos, this.inner[i].parse.parsedPos); + } + return pos; + } + stopAt(pos) { + this.stoppedAt = pos; + if (this.baseParse) + this.baseParse.stopAt(pos); + else + for (let i = this.innerDone; i < this.inner.length; i++) + this.inner[i].parse.stopAt(pos); + } + startInner() { + let fragmentCursor = new FragmentCursor$1(this.fragments); + let overlay = null; + let covered = null; + let cursor = new TreeCursor(new TreeNode(this.baseTree, this.ranges[0].from, 0, null), IterMode.IncludeAnonymous | IterMode.IgnoreMounts); + scan: for (let nest, isCovered;;) { + let enter = true, range; + if (this.stoppedAt != null && cursor.from >= this.stoppedAt) { + enter = false; + } + else if (fragmentCursor.hasNode(cursor)) { + if (overlay) { + let match = overlay.mounts.find(m => m.frag.from <= cursor.from && m.frag.to >= cursor.to && m.mount.overlay); + if (match) + for (let r of match.mount.overlay) { + let from = r.from + match.pos, to = r.to + match.pos; + if (from >= cursor.from && to <= cursor.to && !overlay.ranges.some(r => r.from < to && r.to > from)) + overlay.ranges.push({ from, to }); + } + } + enter = false; + } + else if (covered && (isCovered = checkCover(covered.ranges, cursor.from, cursor.to))) { + enter = isCovered != 2 /* Cover.Full */; + } + else if (!cursor.type.isAnonymous && (nest = this.nest(cursor, this.input)) && + (cursor.from < cursor.to || !nest.overlay)) { + if (!cursor.tree) + materialize(cursor); + let oldMounts = fragmentCursor.findMounts(cursor.from, nest.parser); + if (typeof nest.overlay == "function") { + overlay = new ActiveOverlay(nest.parser, nest.overlay, oldMounts, this.inner.length, cursor.from, cursor.tree, overlay); + } + else { + let ranges = punchRanges(this.ranges, nest.overlay || + (cursor.from < cursor.to ? [new Range(cursor.from, cursor.to)] : [])); + if (ranges.length) + checkRanges(ranges); + if (ranges.length || !nest.overlay) + this.inner.push(new InnerParse(nest.parser, ranges.length ? nest.parser.startParse(this.input, enterFragments(oldMounts, ranges), ranges) + : nest.parser.startParse(""), nest.overlay ? nest.overlay.map(r => new Range(r.from - cursor.from, r.to - cursor.from)) : null, cursor.tree, ranges.length ? ranges[0].from : cursor.from)); + if (!nest.overlay) + enter = false; + else if (ranges.length) + covered = { ranges, depth: 0, prev: covered }; + } + } + else if (overlay && (range = overlay.predicate(cursor))) { + if (range === true) + range = new Range(cursor.from, cursor.to); + if (range.from < range.to) + overlay.ranges.push(range); + } + if (enter && cursor.firstChild()) { + if (overlay) + overlay.depth++; + if (covered) + covered.depth++; + } + else { + for (;;) { + if (cursor.nextSibling()) + break; + if (!cursor.parent()) + break scan; + if (overlay && !--overlay.depth) { + let ranges = punchRanges(this.ranges, overlay.ranges); + if (ranges.length) { + checkRanges(ranges); + this.inner.splice(overlay.index, 0, new InnerParse(overlay.parser, overlay.parser.startParse(this.input, enterFragments(overlay.mounts, ranges), ranges), overlay.ranges.map(r => new Range(r.from - overlay.start, r.to - overlay.start)), overlay.target, ranges[0].from)); + } + overlay = overlay.prev; + } + if (covered && !--covered.depth) + covered = covered.prev; + } + } + } + } + } + function checkCover(covered, from, to) { + for (let range of covered) { + if (range.from >= to) + break; + if (range.to > from) + return range.from <= from && range.to >= to ? 2 /* Cover.Full */ : 1 /* Cover.Partial */; + } + return 0 /* Cover.None */; + } + // Take a piece of buffer and convert it into a stand-alone + // TreeBuffer. + function sliceBuf(buf, startI, endI, nodes, positions, off) { + if (startI < endI) { + let from = buf.buffer[startI + 1]; + nodes.push(buf.slice(startI, endI, from)); + positions.push(from - off); + } + } + // This function takes a node that's in a buffer, and converts it, and + // its parent buffer nodes, into a Tree. This is again acting on the + // assumption that the trees and buffers have been constructed by the + // parse that was ran via the mix parser, and thus aren't shared with + // any other code, making violations of the immutability safe. + function materialize(cursor) { + let { node } = cursor, stack = []; + let buffer = node.context.buffer; + // Scan up to the nearest tree + do { + stack.push(cursor.index); + cursor.parent(); + } while (!cursor.tree); + // Find the index of the buffer in that tree + let base = cursor.tree, i = base.children.indexOf(buffer); + let buf = base.children[i], b = buf.buffer, newStack = [i]; + // Split a level in the buffer, putting the nodes before and after + // the child that contains `node` into new buffers. + function split(startI, endI, type, innerOffset, length, stackPos) { + let targetI = stack[stackPos]; + let children = [], positions = []; + sliceBuf(buf, startI, targetI, children, positions, innerOffset); + let from = b[targetI + 1], to = b[targetI + 2]; + newStack.push(children.length); + let child = stackPos + ? split(targetI + 4, b[targetI + 3], buf.set.types[b[targetI]], from, to - from, stackPos - 1) + : node.toTree(); + children.push(child); + positions.push(from - innerOffset); + sliceBuf(buf, b[targetI + 3], endI, children, positions, innerOffset); + return new Tree(type, children, positions, length); + } + base.children[i] = split(0, b.length, NodeType.none, 0, buf.length, stack.length - 1); + // Move the cursor back to the target node + for (let index of newStack) { + let tree = cursor.tree.children[index], pos = cursor.tree.positions[index]; + cursor.yield(new TreeNode(tree, pos + cursor.from, index, cursor._tree)); + } + } + class StructureCursor { + constructor(root, offset) { + this.offset = offset; + this.done = false; + this.cursor = root.cursor(IterMode.IncludeAnonymous | IterMode.IgnoreMounts); + } + // Move to the first node (in pre-order) that starts at or after `pos`. + moveTo(pos) { + let { cursor } = this, p = pos - this.offset; + while (!this.done && cursor.from < p) { + if (cursor.to >= pos && cursor.enter(p, 1, IterMode.IgnoreOverlays | IterMode.ExcludeBuffers)) ; + else if (!cursor.next(false)) + this.done = true; + } + } + hasNode(cursor) { + this.moveTo(cursor.from); + if (!this.done && this.cursor.from + this.offset == cursor.from && this.cursor.tree) { + for (let tree = this.cursor.tree;;) { + if (tree == cursor.tree) + return true; + if (tree.children.length && tree.positions[0] == 0 && tree.children[0] instanceof Tree) + tree = tree.children[0]; + else + break; + } + } + return false; + } + } + let FragmentCursor$1 = class FragmentCursor { + constructor(fragments) { + var _a; + this.fragments = fragments; + this.curTo = 0; + this.fragI = 0; + if (fragments.length) { + let first = this.curFrag = fragments[0]; + this.curTo = (_a = first.tree.prop(stoppedInner)) !== null && _a !== void 0 ? _a : first.to; + this.inner = new StructureCursor(first.tree, -first.offset); + } + else { + this.curFrag = this.inner = null; + } + } + hasNode(node) { + while (this.curFrag && node.from >= this.curTo) + this.nextFrag(); + return this.curFrag && this.curFrag.from <= node.from && this.curTo >= node.to && this.inner.hasNode(node); + } + nextFrag() { + var _a; + this.fragI++; + if (this.fragI == this.fragments.length) { + this.curFrag = this.inner = null; + } + else { + let frag = this.curFrag = this.fragments[this.fragI]; + this.curTo = (_a = frag.tree.prop(stoppedInner)) !== null && _a !== void 0 ? _a : frag.to; + this.inner = new StructureCursor(frag.tree, -frag.offset); + } + } + findMounts(pos, parser) { + var _a; + let result = []; + if (this.inner) { + this.inner.cursor.moveTo(pos, 1); + for (let pos = this.inner.cursor.node; pos; pos = pos.parent) { + let mount = (_a = pos.tree) === null || _a === void 0 ? void 0 : _a.prop(NodeProp.mounted); + if (mount && mount.parser == parser) { + for (let i = this.fragI; i < this.fragments.length; i++) { + let frag = this.fragments[i]; + if (frag.from >= pos.to) + break; + if (frag.tree == this.curFrag.tree) + result.push({ + frag, + pos: pos.from - frag.offset, + mount + }); + } + } + } + } + return result; + } + }; + function punchRanges(outer, ranges) { + let copy = null, current = ranges; + for (let i = 1, j = 0; i < outer.length; i++) { + let gapFrom = outer[i - 1].to, gapTo = outer[i].from; + for (; j < current.length; j++) { + let r = current[j]; + if (r.from >= gapTo) + break; + if (r.to <= gapFrom) + continue; + if (!copy) + current = copy = ranges.slice(); + if (r.from < gapFrom) { + copy[j] = new Range(r.from, gapFrom); + if (r.to > gapTo) + copy.splice(j + 1, 0, new Range(gapTo, r.to)); + } + else if (r.to > gapTo) { + copy[j--] = new Range(gapTo, r.to); + } + else { + copy.splice(j--, 1); + } + } + } + return current; + } + function findCoverChanges(a, b, from, to) { + let iA = 0, iB = 0, inA = false, inB = false, pos = -1e9; + let result = []; + for (;;) { + let nextA = iA == a.length ? 1e9 : inA ? a[iA].to : a[iA].from; + let nextB = iB == b.length ? 1e9 : inB ? b[iB].to : b[iB].from; + if (inA != inB) { + let start = Math.max(pos, from), end = Math.min(nextA, nextB, to); + if (start < end) + result.push(new Range(start, end)); + } + pos = Math.min(nextA, nextB); + if (pos == 1e9) + break; + if (nextA == pos) { + if (!inA) + inA = true; + else { + inA = false; + iA++; + } + } + if (nextB == pos) { + if (!inB) + inB = true; + else { + inB = false; + iB++; + } + } + } + return result; + } + // Given a number of fragments for the outer tree, and a set of ranges + // to parse, find fragments for inner trees mounted around those + // ranges, if any. + function enterFragments(mounts, ranges) { + let result = []; + for (let { pos, mount, frag } of mounts) { + let startPos = pos + (mount.overlay ? mount.overlay[0].from : 0), endPos = startPos + mount.tree.length; + let from = Math.max(frag.from, startPos), to = Math.min(frag.to, endPos); + if (mount.overlay) { + let overlay = mount.overlay.map(r => new Range(r.from + pos, r.to + pos)); + let changes = findCoverChanges(ranges, overlay, from, to); + for (let i = 0, pos = from;; i++) { + let last = i == changes.length, end = last ? to : changes[i].from; + if (end > pos) + result.push(new TreeFragment(pos, end, mount.tree, -startPos, frag.from >= pos || frag.openStart, frag.to <= end || frag.openEnd)); + if (last) + break; + pos = changes[i].to; + } + } + else { + result.push(new TreeFragment(from, to, mount.tree, -startPos, frag.from >= startPos || frag.openStart, frag.to <= endPos || frag.openEnd)); + } + } + return result; + } let nextTagID = 0; /** @@ -17281,7 +17689,7 @@ For tags that extend some parent tag, the documentation links to the parent. */ - const tags = { + const tags$1 = { /** A comment. */ @@ -17647,8 +18055,8 @@ */ special: Tag.defineModifier("special") }; - for (let name in tags) { - let val = tags[name]; + for (let name in tags$1) { + let val = tags$1[name]; if (val instanceof Tag) val.name = name; } @@ -17701,36 +18109,36 @@ to `"tok-propertyName tok-definition"` */ 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" } + { tag: tags$1.link, class: "tok-link" }, + { tag: tags$1.heading, class: "tok-heading" }, + { tag: tags$1.emphasis, class: "tok-emphasis" }, + { tag: tags$1.strong, class: "tok-strong" }, + { tag: tags$1.keyword, class: "tok-keyword" }, + { tag: tags$1.atom, class: "tok-atom" }, + { tag: tags$1.bool, class: "tok-bool" }, + { tag: tags$1.url, class: "tok-url" }, + { tag: tags$1.labelName, class: "tok-labelName" }, + { tag: tags$1.inserted, class: "tok-inserted" }, + { tag: tags$1.deleted, class: "tok-deleted" }, + { tag: tags$1.literal, class: "tok-literal" }, + { tag: tags$1.string, class: "tok-string" }, + { tag: tags$1.number, class: "tok-number" }, + { tag: [tags$1.regexp, tags$1.escape, tags$1.special(tags$1.string)], class: "tok-string2" }, + { tag: tags$1.variableName, class: "tok-variableName" }, + { tag: tags$1.local(tags$1.variableName), class: "tok-variableName tok-local" }, + { tag: tags$1.definition(tags$1.variableName), class: "tok-variableName tok-definition" }, + { tag: tags$1.special(tags$1.variableName), class: "tok-variableName2" }, + { tag: tags$1.definition(tags$1.propertyName), class: "tok-propertyName tok-definition" }, + { tag: tags$1.typeName, class: "tok-typeName" }, + { tag: tags$1.namespace, class: "tok-namespace" }, + { tag: tags$1.className, class: "tok-className" }, + { tag: tags$1.macroName, class: "tok-macroName" }, + { tag: tags$1.propertyName, class: "tok-propertyName" }, + { tag: tags$1.operator, class: "tok-operator" }, + { tag: tags$1.comment, class: "tok-comment" }, + { tag: tags$1.meta, class: "tok-meta" }, + { tag: tags$1.invalid, class: "tok-invalid" }, + { tag: tags$1.punctuation, class: "tok-punctuation" } ]); var _a; @@ -18578,9 +18986,9 @@ let last = tree.lastChild, closed = last && close.indexOf(last.name) > -1; return cx => delimitedStrategy(cx, true, 1, undefined, closed && !ignoreClosed(cx) ? last.from : undefined); } - return tree.parent == null ? topIndent$1 : null; + return tree.parent == null ? topIndent : null; } - function topIndent$1() { return 0; } + function topIndent() { return 0; } /** Objects of this type provide context information and helper methods to indentation functions registered on syntax nodes. @@ -18701,6 +19109,25 @@ return closed ? context.column(aligned.from) : context.column(aligned.to); return context.baseIndent + (closed ? 0 : context.unit * units); } + /** + An indentation strategy that aligns a node's content to its base + indentation. + */ + const flatIndent = (context) => context.baseIndent; + /** + Creates an indentation strategy that, by default, indents + continued lines one unit more than the node's base indentation. + You can provide `except` to prevent indentation of lines that + match a pattern (for example `/^else\b/` in `if`/`else` + constructs), and you can change the amount of units used with the + `units` option. + */ + function continuedIndent({ except, units = 1 } = {}) { + return (context) => { + let matchExcept = except && except.test(context.textAfter); + return context.baseIndent + (matchExcept ? 0 : units * context.unit); + }; + } const DontIndentBeyond = 200; /** Enables reindentation on input. When a language defines an @@ -19256,44 +19683,44 @@ A default highlight style (works well with light themes). */ const defaultHighlightStyle = /*@__PURE__*/HighlightStyle.define([ - { tag: tags.meta, + { tag: tags$1.meta, color: "#404740" }, - { tag: tags.link, + { tag: tags$1.link, textDecoration: "underline" }, - { tag: tags.heading, + { tag: tags$1.heading, textDecoration: "underline", fontWeight: "bold" }, - { tag: tags.emphasis, + { tag: tags$1.emphasis, fontStyle: "italic" }, - { tag: tags.strong, + { tag: tags$1.strong, fontWeight: "bold" }, - { tag: tags.strikethrough, + { tag: tags$1.strikethrough, textDecoration: "line-through" }, - { tag: tags.keyword, + { tag: tags$1.keyword, color: "#708" }, - { tag: [tags.atom, tags.bool, tags.url, tags.contentSeparator, tags.labelName], + { tag: [tags$1.atom, tags$1.bool, tags$1.url, tags$1.contentSeparator, tags$1.labelName], color: "#219" }, - { tag: [tags.literal, tags.inserted], + { tag: [tags$1.literal, tags$1.inserted], color: "#164" }, - { tag: [tags.string, tags.deleted], + { tag: [tags$1.string, tags$1.deleted], color: "#a11" }, - { tag: [tags.regexp, tags.escape, /*@__PURE__*/tags.special(tags.string)], + { tag: [tags$1.regexp, tags$1.escape, /*@__PURE__*/tags$1.special(tags$1.string)], color: "#e40" }, - { tag: /*@__PURE__*/tags.definition(tags.variableName), + { tag: /*@__PURE__*/tags$1.definition(tags$1.variableName), color: "#00f" }, - { tag: /*@__PURE__*/tags.local(tags.variableName), + { tag: /*@__PURE__*/tags$1.local(tags$1.variableName), color: "#30a" }, - { tag: [tags.typeName, tags.namespace], + { tag: [tags$1.typeName, tags$1.namespace], color: "#085" }, - { tag: tags.className, + { tag: tags$1.className, color: "#167" }, - { tag: [/*@__PURE__*/tags.special(tags.variableName), tags.macroName], + { tag: [/*@__PURE__*/tags$1.special(tags$1.variableName), tags$1.macroName], color: "#256" }, - { tag: /*@__PURE__*/tags.definition(tags.propertyName), + { tag: /*@__PURE__*/tags$1.definition(tags$1.propertyName), color: "#00c" }, - { tag: tags.comment, + { tag: tags$1.comment, color: "#940" }, - { tag: tags.invalid, + { tag: tags$1.invalid, color: "#f00" } ]); @@ -19458,71 +19885,551 @@ } return iter.done ? { start: startToken, matched: false } : null; } - const noTokens = /*@__PURE__*/Object.create(null); - const typeArray = [NodeType.none]; - const warned = []; - // Cache of node types by name and tags - const byTag = /*@__PURE__*/Object.create(null); - const defaultTable = /*@__PURE__*/Object.create(null); - for (let [legacyName, name] of [ - ["variable", "variableName"], - ["variable-2", "variableName.special"], - ["string-2", "string.special"], - ["def", "variableName.definition"], - ["tag", "tagName"], - ["attribute", "attributeName"], - ["type", "typeName"], - ["builtin", "variableName.standard"], - ["qualifier", "modifier"], - ["error", "invalid"], - ["header", "heading"], - ["property", "propertyName"] - ]) - defaultTable[legacyName] = /*@__PURE__*/createTokenType(noTokens, name); - function warnForPart(part, msg) { - if (warned.indexOf(part) > -1) - return; - warned.push(part); - console.warn(msg); + + // Counts the column offset in a string, taking tabs into account. + // Used mostly to find indentation. + function countCol(string, end, tabSize, startIndex = 0, startValue = 0) { + if (end == null) { + end = string.search(/[^\s\u00a0]/); + if (end == -1) + end = string.length; + } + let n = startValue; + for (let i = startIndex; i < end; i++) { + if (string.charCodeAt(i) == 9) + n += tabSize - (n % tabSize); + else + n++; + } + return n; } - function createTokenType(extra, tagStr) { - let tags$1 = []; - for (let name of tagStr.split(" ")) { - let found = []; - for (let part of name.split(".")) { - let value = (extra[part] || tags[part]); - if (!value) { - warnForPart(part, `Unknown highlighting tag ${part}`); - } - else if (typeof value == "function") { - if (!found.length) - warnForPart(part, `Modifier ${part} used at start of tag`); - else - found = found.map(value); - } - else { - if (found.length) - warnForPart(part, `Tag ${part} used as modifier`); - else - found = Array.isArray(value) ? value : [value]; + /** + Encapsulates a single line of input. Given to stream syntax code, + which uses it to tokenize the content. + */ + class StringStream { + /** + Create a stream. + */ + constructor( + /** + The line. + */ + string, tabSize, + /** + The current indent unit size. + */ + indentUnit, overrideIndent) { + this.string = string; + this.tabSize = tabSize; + this.indentUnit = indentUnit; + this.overrideIndent = overrideIndent; + /** + The current position on the line. + */ + this.pos = 0; + /** + The start position of the current token. + */ + this.start = 0; + this.lastColumnPos = 0; + this.lastColumnValue = 0; + } + /** + True if we are at the end of the line. + */ + eol() { return this.pos >= this.string.length; } + /** + True if we are at the start of the line. + */ + sol() { return this.pos == 0; } + /** + Get the next code unit after the current position, or undefined + if we're at the end of the line. + */ + peek() { return this.string.charAt(this.pos) || undefined; } + /** + Read the next code unit and advance `this.pos`. + */ + next() { + if (this.pos < this.string.length) + return this.string.charAt(this.pos++); + } + /** + Match the next character against the given string, regular + expression, or predicate. Consume and return it if it matches. + */ + eat(match) { + let ch = this.string.charAt(this.pos); + let ok; + if (typeof match == "string") + ok = ch == match; + else + ok = ch && (match instanceof RegExp ? match.test(ch) : match(ch)); + if (ok) { + ++this.pos; + return ch; + } + } + /** + Continue matching characters that match the given string, + regular expression, or predicate function. Return true if any + characters were consumed. + */ + eatWhile(match) { + let start = this.pos; + while (this.eat(match)) { } + return this.pos > start; + } + /** + Consume whitespace ahead of `this.pos`. Return true if any was + found. + */ + eatSpace() { + let start = this.pos; + while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) + ++this.pos; + return this.pos > start; + } + /** + Move to the end of the line. + */ + skipToEnd() { this.pos = this.string.length; } + /** + Move to directly before the given character, if found on the + current line. + */ + skipTo(ch) { + let found = this.string.indexOf(ch, this.pos); + if (found > -1) { + this.pos = found; + return true; + } + } + /** + Move back `n` characters. + */ + backUp(n) { this.pos -= n; } + /** + Get the column position at `this.pos`. + */ + column() { + if (this.lastColumnPos < this.start) { + this.lastColumnValue = countCol(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue); + this.lastColumnPos = this.start; + } + return this.lastColumnValue; + } + /** + Get the indentation column of the current line. + */ + indentation() { + var _a; + return (_a = this.overrideIndent) !== null && _a !== void 0 ? _a : countCol(this.string, null, this.tabSize); + } + /** + Match the input against the given string or regular expression + (which should start with a `^`). Return true or the regexp match + if it matches. + + Unless `consume` is set to `false`, this will move `this.pos` + past the matched text. + + When matching a string `caseInsensitive` can be set to true to + make the match case-insensitive. + */ + match(pattern, consume, caseInsensitive) { + if (typeof pattern == "string") { + let cased = (str) => caseInsensitive ? str.toLowerCase() : str; + let substr = this.string.substr(this.pos, pattern.length); + if (cased(substr) == cased(pattern)) { + if (consume !== false) + this.pos += pattern.length; + return true; } + else + return null; + } + else { + let match = this.string.slice(this.pos).match(pattern); + if (match && match.index > 0) + return null; + if (match && consume !== false) + this.pos += match[0].length; + return match; } - for (let tag of found) - tags$1.push(tag); } - if (!tags$1.length) - return 0; - let name = tagStr.replace(/ /g, "_"), key = name + " " + tags$1.map(t => t.id); - let known = byTag[key]; - if (known) - return known.id; - let type = byTag[key] = NodeType.define({ - id: typeArray.length, - name, - props: [styleTags({ [name]: tags$1 })] - }); - typeArray.push(type); - return type.id; + /** + Get the current token. + */ + current() { return this.string.slice(this.start, this.pos); } + } + + function fullParser(spec) { + return { + name: spec.name || "", + token: spec.token, + blankLine: spec.blankLine || (() => { }), + startState: spec.startState || (() => true), + copyState: spec.copyState || defaultCopyState, + indent: spec.indent || (() => null), + languageData: spec.languageData || {}, + tokenTable: spec.tokenTable || noTokens + }; + } + function defaultCopyState(state) { + if (typeof state != "object") + return state; + let newState = {}; + for (let prop in state) { + let val = state[prop]; + newState[prop] = (val instanceof Array ? val.slice() : val); + } + return newState; + } + const IndentedFrom = /*@__PURE__*/new WeakMap(); + /** + A [language](https://codemirror.net/6/docs/ref/#language.Language) class based on a CodeMirror + 5-style [streaming parser](https://codemirror.net/6/docs/ref/#language.StreamParser). + */ + class StreamLanguage extends Language { + constructor(parser) { + let data = defineLanguageFacet(parser.languageData); + let p = fullParser(parser), self; + let impl = new class extends Parser { + createParse(input, fragments, ranges) { + return new Parse$1(self, input, fragments, ranges); + } + }; + super(data, impl, [indentService.of((cx, pos) => this.getIndent(cx, pos))], parser.name); + this.topNode = docID(data); + self = this; + this.streamParser = p; + this.stateAfter = new NodeProp({ perNode: true }); + this.tokenTable = parser.tokenTable ? new TokenTable(p.tokenTable) : defaultTokenTable; + } + /** + Define a stream language. + */ + static define(spec) { return new StreamLanguage(spec); } + getIndent(cx, pos) { + let tree = syntaxTree(cx.state), at = tree.resolve(pos); + while (at && at.type != this.topNode) + at = at.parent; + if (!at) + return null; + let from = undefined; + let { overrideIndentation } = cx.options; + if (overrideIndentation) { + from = IndentedFrom.get(cx.state); + if (from != null && from < pos - 1e4) + from = undefined; + } + let start = findState(this, tree, 0, at.from, from !== null && from !== void 0 ? from : pos), statePos, state; + if (start) { + state = start.state; + statePos = start.pos + 1; + } + else { + state = this.streamParser.startState(cx.unit); + statePos = 0; + } + if (pos - statePos > 10000 /* C.MaxIndentScanDist */) + return null; + while (statePos < pos) { + let line = cx.state.doc.lineAt(statePos), end = Math.min(pos, line.to); + if (line.length) { + let indentation = overrideIndentation ? overrideIndentation(line.from) : -1; + let stream = new StringStream(line.text, cx.state.tabSize, cx.unit, indentation < 0 ? undefined : indentation); + while (stream.pos < end - line.from) + readToken$1(this.streamParser.token, stream, state); + } + else { + this.streamParser.blankLine(state, cx.unit); + } + if (end == pos) + break; + statePos = line.to + 1; + } + let line = cx.lineAt(pos); + if (overrideIndentation && from == null) + IndentedFrom.set(cx.state, line.from); + return this.streamParser.indent(state, /^\s*(.*)/.exec(line.text)[1], cx); + } + get allowsNesting() { return false; } + } + function findState(lang, tree, off, startPos, before) { + let state = off >= startPos && off + tree.length <= before && tree.prop(lang.stateAfter); + if (state) + return { state: lang.streamParser.copyState(state), pos: off + tree.length }; + for (let i = tree.children.length - 1; i >= 0; i--) { + let child = tree.children[i], pos = off + tree.positions[i]; + let found = child instanceof Tree && pos < before && findState(lang, child, pos, startPos, before); + if (found) + return found; + } + return null; + } + function cutTree(lang, tree, from, to, inside) { + if (inside && from <= 0 && to >= tree.length) + return tree; + if (!inside && tree.type == lang.topNode) + inside = true; + for (let i = tree.children.length - 1; i >= 0; i--) { + let pos = tree.positions[i], child = tree.children[i], inner; + if (pos < to && child instanceof Tree) { + if (!(inner = cutTree(lang, child, from - pos, to - pos, inside))) + break; + return !inside ? inner + : new Tree(tree.type, tree.children.slice(0, i).concat(inner), tree.positions.slice(0, i + 1), pos + inner.length); + } + } + return null; + } + function findStartInFragments(lang, fragments, startPos, editorState) { + for (let f of fragments) { + let from = f.from + (f.openStart ? 25 : 0), to = f.to - (f.openEnd ? 25 : 0); + let found = from <= startPos && to > startPos && findState(lang, f.tree, 0 - f.offset, startPos, to), tree; + if (found && (tree = cutTree(lang, f.tree, startPos + f.offset, found.pos + f.offset, false))) + return { state: found.state, tree }; + } + return { state: lang.streamParser.startState(editorState ? getIndentUnit(editorState) : 4), tree: Tree.empty }; + } + let Parse$1 = class Parse { + constructor(lang, input, fragments, ranges) { + this.lang = lang; + this.input = input; + this.fragments = fragments; + this.ranges = ranges; + this.stoppedAt = null; + this.chunks = []; + this.chunkPos = []; + this.chunk = []; + this.chunkReused = undefined; + this.rangeIndex = 0; + this.to = ranges[ranges.length - 1].to; + let context = ParseContext.get(), from = ranges[0].from; + let { state, tree } = findStartInFragments(lang, fragments, from, context === null || context === void 0 ? void 0 : context.state); + this.state = state; + this.parsedPos = this.chunkStart = from + tree.length; + for (let i = 0; i < tree.children.length; i++) { + this.chunks.push(tree.children[i]); + this.chunkPos.push(tree.positions[i]); + } + if (context && this.parsedPos < context.viewport.from - 100000 /* C.MaxDistanceBeforeViewport */) { + this.state = this.lang.streamParser.startState(getIndentUnit(context.state)); + context.skipUntilInView(this.parsedPos, context.viewport.from); + this.parsedPos = context.viewport.from; + } + this.moveRangeIndex(); + } + advance() { + let context = ParseContext.get(); + let parseEnd = this.stoppedAt == null ? this.to : Math.min(this.to, this.stoppedAt); + let end = Math.min(parseEnd, this.chunkStart + 2048 /* C.ChunkSize */); + if (context) + end = Math.min(end, context.viewport.to); + while (this.parsedPos < end) + this.parseLine(context); + if (this.chunkStart < this.parsedPos) + this.finishChunk(); + if (this.parsedPos >= parseEnd) + return this.finish(); + if (context && this.parsedPos >= context.viewport.to) { + context.skipUntilInView(this.parsedPos, parseEnd); + return this.finish(); + } + return null; + } + stopAt(pos) { + this.stoppedAt = pos; + } + lineAfter(pos) { + let chunk = this.input.chunk(pos); + if (!this.input.lineChunks) { + let eol = chunk.indexOf("\n"); + if (eol > -1) + chunk = chunk.slice(0, eol); + } + else if (chunk == "\n") { + chunk = ""; + } + return pos + chunk.length <= this.to ? chunk : chunk.slice(0, this.to - pos); + } + nextLine() { + let from = this.parsedPos, line = this.lineAfter(from), end = from + line.length; + for (let index = this.rangeIndex;;) { + let rangeEnd = this.ranges[index].to; + if (rangeEnd >= end) + break; + line = line.slice(0, rangeEnd - (end - line.length)); + index++; + if (index == this.ranges.length) + break; + let rangeStart = this.ranges[index].from; + let after = this.lineAfter(rangeStart); + line += after; + end = rangeStart + after.length; + } + return { line, end }; + } + skipGapsTo(pos, offset, side) { + for (;;) { + let end = this.ranges[this.rangeIndex].to, offPos = pos + offset; + if (side > 0 ? end > offPos : end >= offPos) + break; + let start = this.ranges[++this.rangeIndex].from; + offset += start - end; + } + return offset; + } + moveRangeIndex() { + while (this.ranges[this.rangeIndex].to < this.parsedPos) + this.rangeIndex++; + } + emitToken(id, from, to, size, offset) { + if (this.ranges.length > 1) { + offset = this.skipGapsTo(from, offset, 1); + from += offset; + let len0 = this.chunk.length; + offset = this.skipGapsTo(to, offset, -1); + to += offset; + size += this.chunk.length - len0; + } + this.chunk.push(id, from, to, size); + return offset; + } + parseLine(context) { + let { line, end } = this.nextLine(), offset = 0, { streamParser } = this.lang; + let stream = new StringStream(line, context ? context.state.tabSize : 4, context ? getIndentUnit(context.state) : 2); + if (stream.eol()) { + streamParser.blankLine(this.state, stream.indentUnit); + } + else { + while (!stream.eol()) { + let token = readToken$1(streamParser.token, stream, this.state); + if (token) + offset = this.emitToken(this.lang.tokenTable.resolve(token), this.parsedPos + stream.start, this.parsedPos + stream.pos, 4, offset); + if (stream.start > 10000 /* C.MaxLineLength */) + break; + } + } + this.parsedPos = end; + this.moveRangeIndex(); + if (this.parsedPos < this.to) + this.parsedPos++; + } + finishChunk() { + let tree = Tree.build({ + buffer: this.chunk, + start: this.chunkStart, + length: this.parsedPos - this.chunkStart, + nodeSet, + topID: 0, + maxBufferLength: 2048 /* C.ChunkSize */, + reused: this.chunkReused + }); + tree = new Tree(tree.type, tree.children, tree.positions, tree.length, [[this.lang.stateAfter, this.lang.streamParser.copyState(this.state)]]); + this.chunks.push(tree); + this.chunkPos.push(this.chunkStart - this.ranges[0].from); + this.chunk = []; + this.chunkReused = undefined; + this.chunkStart = this.parsedPos; + } + finish() { + return new Tree(this.lang.topNode, this.chunks, this.chunkPos, this.parsedPos - this.ranges[0].from).balance(); + } + }; + function readToken$1(token, stream, state) { + stream.start = stream.pos; + for (let i = 0; i < 10; i++) { + let result = token(stream, state); + if (stream.pos > stream.start) + return result; + } + throw new Error("Stream parser failed to advance stream."); + } + const noTokens = /*@__PURE__*/Object.create(null); + const typeArray = [NodeType.none]; + const nodeSet = /*@__PURE__*/new NodeSet(typeArray); + const warned = []; + // Cache of node types by name and tags + const byTag = /*@__PURE__*/Object.create(null); + const defaultTable = /*@__PURE__*/Object.create(null); + for (let [legacyName, name] of [ + ["variable", "variableName"], + ["variable-2", "variableName.special"], + ["string-2", "string.special"], + ["def", "variableName.definition"], + ["tag", "tagName"], + ["attribute", "attributeName"], + ["type", "typeName"], + ["builtin", "variableName.standard"], + ["qualifier", "modifier"], + ["error", "invalid"], + ["header", "heading"], + ["property", "propertyName"] + ]) + defaultTable[legacyName] = /*@__PURE__*/createTokenType(noTokens, name); + class TokenTable { + constructor(extra) { + this.extra = extra; + this.table = Object.assign(Object.create(null), defaultTable); + } + resolve(tag) { + return !tag ? 0 : this.table[tag] || (this.table[tag] = createTokenType(this.extra, tag)); + } + } + const defaultTokenTable = /*@__PURE__*/new TokenTable(noTokens); + function warnForPart(part, msg) { + if (warned.indexOf(part) > -1) + return; + warned.push(part); + console.warn(msg); + } + function createTokenType(extra, tagStr) { + let tags$1$1 = []; + for (let name of tagStr.split(" ")) { + let found = []; + for (let part of name.split(".")) { + let value = (extra[part] || tags$1[part]); + if (!value) { + warnForPart(part, `Unknown highlighting tag ${part}`); + } + else if (typeof value == "function") { + if (!found.length) + warnForPart(part, `Modifier ${part} used at start of tag`); + else + found = found.map(value); + } + else { + if (found.length) + warnForPart(part, `Tag ${part} used as modifier`); + else + found = Array.isArray(value) ? value : [value]; + } + } + for (let tag of found) + tags$1$1.push(tag); + } + if (!tags$1$1.length) + return 0; + let name = tagStr.replace(/ /g, "_"), key = name + " " + tags$1$1.map(t => t.id); + let known = byTag[key]; + if (known) + return known.id; + let type = byTag[key] = NodeType.define({ + id: typeArray.length, + name, + props: [styleTags({ [name]: tags$1$1 })] + }); + typeArray.push(type); + return type.id; + } + function docID(data) { + let type = NodeType.define({ id: typeArray.length, name: "Document", props: [languageDataProp.add(() => data)], top: true }); + typeArray.push(type); + return type; } ({ rtl: /*@__PURE__*/Decoration.mark({ class: "cm-iso", inclusive: true, attributes: { dir: "rtl" }, bidiIsolate: Direction.RTL }), @@ -23841,9 +24748,9 @@ function config(state, pos) { return state.languageDataAt("closeBrackets", pos)[0] || defaults; } - const android = typeof navigator == "object" && /*@__PURE__*//Android\b/.test(navigator.userAgent); + const android$1 = typeof navigator == "object" && /*@__PURE__*//Android\b/.test(navigator.userAgent); const inputHandler = /*@__PURE__*/EditorView.inputHandler.of((view, from, to, insert) => { - if ((android ? view.composing : view.compositionStarted) || view.state.readOnly) + if ((android$1 ? view.composing : view.compositionStarted) || view.state.readOnly) return false; let sel = view.state.selection.main; if (insert.length > 2 || insert.length == 2 && codePointSize(codePointAt(insert, 0)) == 1 || @@ -25568,7 +26475,37 @@ } } TokenGroup.prototype.contextual = TokenGroup.prototype.fallback = TokenGroup.prototype.extend = false; - TokenGroup.prototype.fallback = TokenGroup.prototype.extend = false; + /** + @hide + */ + class LocalTokenGroup { + constructor(data, precTable, elseToken) { + this.precTable = precTable; + this.elseToken = elseToken; + this.data = typeof data == "string" ? decodeArray(data) : data; + } + token(input, stack) { + let start = input.pos, skipped = 0; + for (;;) { + let atEof = input.next < 0, nextPos = input.resolveOffset(1, 1); + readToken(this.data, input, stack, 0, this.data, this.precTable); + if (input.token.value > -1) + break; + if (this.elseToken == null) + return; + if (!atEof) + skipped++; + if (nextPos == null) + break; + input.reset(nextPos, input.token); + } + if (skipped) { + input.reset(start, input.token); + input.acceptToken(this.elseToken, skipped); + } + } + } + LocalTokenGroup.prototype.contextual = TokenGroup.prototype.fallback = TokenGroup.prototype.extend = false; /** `@external tokens` declarations in the grammar should resolve to an instance of this class. @@ -26512,383 +27449,1023 @@ } // This file was generated by lezer-generator. You probably shouldn't edit it. - const printKeyword = 1, - indent = 194, - dedent = 195, - newline$1 = 196, - blankLineStart = 197, - newlineBracketed = 198, - eof = 199, - stringContent = 200, - Escape = 2, - replacementStart = 3, - stringEnd = 201, - ParenL = 24, - ParenthesizedExpression = 25, - TupleExpression = 49, - ComprehensionExpression = 50, - BracketL = 55, - ArrayExpression = 56, - ArrayComprehensionExpression = 57, - BraceL = 59, - DictionaryExpression = 60, - DictionaryComprehensionExpression = 61, - SetExpression = 62, - SetComprehensionExpression = 63, - ArgList = 65, - subscript = 238, - String$1 = 71, - stringStart = 241, - stringStartD = 242, - stringStartL = 243, - stringStartLD = 244, - stringStartR = 245, - stringStartRD = 246, - stringStartRL = 247, - stringStartRLD = 248, - FormatString = 72, - stringStartF = 249, - stringStartFD = 250, - stringStartFL = 251, - stringStartFLD = 252, - stringStartFR = 253, - stringStartFRD = 254, - stringStartFRL = 255, - stringStartFRLD = 256, - FormatReplacement = 73, - nestedFormatReplacement = 77, - importList = 263, - TypeParamList = 112, - ParamList = 130, - SequencePattern = 151, - MappingPattern = 152, - PatternArgList = 155; - - const newline = 10, carriageReturn = 13, space = 32, tab = 9, hash = 35, parenOpen = 40, dot = 46, - braceOpen = 123, braceClose = 125, singleQuote = 39, doubleQuote = 34, backslash = 92, - letter_o = 111, letter_x = 120, letter_N = 78, letter_u = 117, letter_U = 85; - - const bracketed = new Set([ - ParenthesizedExpression, TupleExpression, ComprehensionExpression, importList, ArgList, ParamList, - ArrayExpression, ArrayComprehensionExpression, subscript, - SetExpression, SetComprehensionExpression, FormatString, FormatReplacement, nestedFormatReplacement, - DictionaryExpression, DictionaryComprehensionExpression, - SequencePattern, MappingPattern, PatternArgList, TypeParamList - ]); + const scriptText = 54, + StartCloseScriptTag = 1, + styleText = 55, + StartCloseStyleTag = 2, + textareaText = 56, + StartCloseTextareaTag = 3, + EndTag = 4, + SelfClosingEndTag = 5, + StartTag = 6, + StartScriptTag = 7, + StartStyleTag = 8, + StartTextareaTag = 9, + StartSelfClosingTag = 10, + StartCloseTag = 11, + NoMatchStartCloseTag = 12, + MismatchedStartCloseTag = 13, + missingCloseTag = 57, + IncompleteCloseTag = 14, + commentContent$1 = 58, + Element = 20, + TagName = 22, + Attribute = 23, + AttributeName = 24, + AttributeValue = 26, + UnquotedAttributeValue = 27, + ScriptText = 28, + StyleText = 31, + TextareaText = 34, + OpenTag = 36, + CloseTag = 37, + Dialect_noMatch = 0, + Dialect_selfClosing = 1; - function isLineBreak(ch) { - return ch == newline || ch == carriageReturn - } + /* Hand-written tokenizers for HTML. */ + + const selfClosers$1 = { + area: true, base: true, br: true, col: true, command: true, + embed: true, frame: true, hr: true, img: true, input: true, + keygen: true, link: true, meta: true, param: true, source: true, + track: true, wbr: true, menuitem: true + }; + + const implicitlyClosed = { + dd: true, li: true, optgroup: true, option: true, p: true, + rp: true, rt: true, tbody: true, td: true, tfoot: true, + th: true, tr: true + }; + + const closeOnOpen = { + dd: {dd: true, dt: true}, + dt: {dd: true, dt: true}, + li: {li: true}, + option: {option: true, optgroup: true}, + optgroup: {optgroup: true}, + p: { + address: true, article: true, aside: true, blockquote: true, dir: true, + div: true, dl: true, fieldset: true, footer: true, form: true, + h1: true, h2: true, h3: true, h4: true, h5: true, h6: true, + header: true, hgroup: true, hr: true, menu: true, nav: true, ol: true, + p: true, pre: true, section: true, table: true, ul: true + }, + rp: {rp: true, rt: true}, + rt: {rp: true, rt: true}, + tbody: {tbody: true, tfoot: true}, + td: {td: true, th: true}, + tfoot: {tbody: true}, + th: {td: true, th: true}, + thead: {tbody: true, tfoot: true}, + tr: {tr: true} + }; - function isHex(ch) { - return ch >= 48 && ch <= 57 || ch >= 65 && ch <= 70 || ch >= 97 && ch <= 102 + function nameChar(ch) { + return ch == 45 || ch == 46 || ch == 58 || ch >= 65 && ch <= 90 || ch == 95 || ch >= 97 && ch <= 122 || ch >= 161 } - const newlines = new ExternalTokenizer((input, stack) => { - let prev; - if (input.next < 0) { - input.acceptToken(eof); - } else if (stack.context.flags & cx_Bracketed) { - if (isLineBreak(input.next)) input.acceptToken(newlineBracketed, 1); - } else if (((prev = input.peek(-1)) < 0 || isLineBreak(prev)) && - stack.canShift(blankLineStart)) { - let spaces = 0; - while (input.next == space || input.next == tab) { input.advance(); spaces++; } - if (input.next == newline || input.next == carriageReturn || input.next == hash) - input.acceptToken(blankLineStart, -spaces); - } else if (isLineBreak(input.next)) { - input.acceptToken(newline$1, 1); - } - }, {contextual: true}); + function isSpace(ch) { + return ch == 9 || ch == 10 || ch == 13 || ch == 32 + } - const indentation = new ExternalTokenizer((input, stack) => { - let context = stack.context; - if (context.flags) return - let prev = input.peek(-1); - if (prev == newline || prev == carriageReturn) { - let depth = 0, chars = 0; - for (;;) { - if (input.next == space) depth++; - else if (input.next == tab) depth += 8 - (depth % 8); - else break - input.advance(); - chars++; - } - if (depth != context.indent && - input.next != newline && input.next != carriageReturn && input.next != hash) { - if (depth < context.indent) input.acceptToken(dedent, -chars); - else input.acceptToken(indent); - } + let cachedName = null, cachedInput = null, cachedPos = 0; + function tagNameAfter(input, offset) { + let pos = input.pos + offset; + if (cachedPos == pos && cachedInput == input) return cachedName + let next = input.peek(offset); + while (isSpace(next)) next = input.peek(++offset); + let name = ""; + for (;;) { + if (!nameChar(next)) break + name += String.fromCharCode(next); + next = input.peek(++offset); } - }); + // Undefined to signal there's a [term, flags | cx_String])); - - const trackIndent = new ContextTracker({ - start: topIndent, - reduce(context, term, _, input) { - if ((context.flags & cx_Bracketed) && bracketed.has(term) || - (term == String$1 || term == FormatString) && (context.flags & cx_String)) - return context.parent - return context - }, + } + + const startTagTerms = [StartTag, StartSelfClosingTag, StartScriptTag, StartStyleTag, StartTextareaTag]; + + const elementContext = new ContextTracker({ + start: null, shift(context, term, stack, input) { - if (term == indent) - return new Context(context, countIndent(input.read(input.pos, stack.pos)), 0) - if (term == dedent) - return context.parent - if (term == ParenL || term == BracketL || term == BraceL || term == replacementStart) - return new Context(context, 0, cx_Bracketed) - if (stringFlags.has(term)) - return new Context(context, 0, stringFlags.get(term) | (context.flags & cx_Bracketed)) - return context + return startTagTerms.indexOf(term) > -1 ? new ElementContext(tagNameAfter(input, 1) || "", context) : context }, - hash(context) { return context.hash } + reduce(context, term) { + return term == Element && context ? context.parent : context + }, + reuse(context, node, stack, input) { + let type = node.type.id; + return type == StartTag || type == OpenTag + ? new ElementContext(tagNameAfter(input, 1) || "", context) : context + }, + strict: false }); - const legacyPrint = new ExternalTokenizer(input => { - for (let i = 0; i < 5; i++) { - if (input.next != "print".charCodeAt(i)) return - input.advance(); - } - if (/\w/.test(String.fromCharCode(input.next))) return - for (let off = 0;; off++) { - let next = input.peek(off); - if (next == space || next == tab) continue - if (next != parenOpen && next != dot && next != newline && next != carriageReturn && next != hash) - input.acceptToken(printKeyword); + const tagStart = new ExternalTokenizer((input, stack) => { + if (input.next != lessThan) { + // End of file, close any open tags + if (input.next < 0 && stack.context) input.acceptToken(missingCloseTag); return } - }); + input.advance(); + let close = input.next == slash$1; + if (close) input.advance(); + let name = tagNameAfter(input, 0); + if (name === undefined) return + if (!name) return input.acceptToken(close ? IncompleteCloseTag : StartTag) - const strings = new ExternalTokenizer((input, stack) => { - let {flags} = stack.context; - let quote = (flags & cx_DoubleQuote) ? doubleQuote : singleQuote; - let long = (flags & cx_Long) > 0; - let escapes = !(flags & cx_Raw); - let format = (flags & cx_Format) > 0; + let parent = stack.context ? stack.context.name : null; + if (close) { + if (name == parent) return input.acceptToken(StartCloseTag) + if (parent && implicitlyClosed[parent]) return input.acceptToken(missingCloseTag, -2) + if (stack.dialectEnabled(Dialect_noMatch)) return input.acceptToken(NoMatchStartCloseTag) + for (let cx = stack.context; cx; cx = cx.parent) if (cx.name == name) return + input.acceptToken(MismatchedStartCloseTag); + } else { + if (name == "script") return input.acceptToken(StartScriptTag) + if (name == "style") return input.acceptToken(StartStyleTag) + if (name == "textarea") return input.acceptToken(StartTextareaTag) + if (selfClosers$1.hasOwnProperty(name)) return input.acceptToken(StartSelfClosingTag) + if (parent && closeOnOpen[parent] && closeOnOpen[parent][name]) input.acceptToken(missingCloseTag, -1); + else input.acceptToken(StartTag); + } + }, {contextual: true}); - let start = input.pos; - for (;;) { + const commentContent = new ExternalTokenizer(input => { + for (let dashes = 0, i = 0;; i++) { if (input.next < 0) { + if (i) input.acceptToken(commentContent$1); break - } else if (format && input.next == braceOpen) { - if (input.peek(1) == braceOpen) { - input.advance(2); - } else { - if (input.pos == start) { - input.acceptToken(replacementStart, 1); - return - } - break - } - } else if (escapes && input.next == backslash) { - if (input.pos == start) { - input.advance(); - let escaped = input.next; - if (escaped >= 0) { - input.advance(); - skipEscape(input, escaped); - } - input.acceptToken(Escape); - return - } - break - } else if (input.next == quote && (!long || input.peek(1) == quote && input.peek(2) == quote)) { - if (input.pos == start) { - input.acceptToken(stringEnd, long ? 3 : 1); - return - } - break - } else if (input.next == newline) { - if (long) { - input.advance(); - } else if (input.pos == start) { - input.acceptToken(stringEnd); - return - } + } + if (input.next == dash$1) { + dashes++; + } else if (input.next == greaterThan && dashes >= 2) { + if (i >= 3) input.acceptToken(commentContent$1, -2); break } else { - input.advance(); + dashes = 0; } + input.advance(); + } + }); + + function inForeignElement(context) { + for (; context; context = context.parent) + if (context.name == "svg" || context.name == "math") return true + return false + } + + const endTag = new ExternalTokenizer((input, stack) => { + if (input.next == slash$1 && input.peek(1) == greaterThan) { + let selfClosing = stack.dialectEnabled(Dialect_selfClosing) || inForeignElement(stack.context); + input.acceptToken(selfClosing ? SelfClosingEndTag : EndTag, 2); + } else if (input.next == greaterThan) { + input.acceptToken(EndTag, 1); } - if (input.pos > start) input.acceptToken(stringContent); }); - function skipEscape(input, ch) { - if (ch == letter_o) { - for (let i = 0; i < 2 && input.next >= 48 && input.next <= 55; i++) input.advance(); - } else if (ch == letter_x) { - for (let i = 0; i < 2 && isHex(input.next); i++) input.advance(); - } else if (ch == letter_u) { - for (let i = 0; i < 4 && isHex(input.next); i++) input.advance(); - } else if (ch == letter_U) { - for (let i = 0; i < 8 && isHex(input.next); i++) input.advance(); - } else if (ch == letter_N) { - if (input.next == braceOpen) { + function contentTokenizer(tag, textToken, endToken) { + let lastState = 2 + tag.length; + return new ExternalTokenizer(input => { + // state means: + // - 0 nothing matched + // - 1 '<' matched + // - 2 '= 2 && state < lastState && input.next == tag.charCodeAt(state - 2)) { + state++; + matchedLen++; + } else if ((state == 2 || state == lastState) && isSpace(input.next)) { + matchedLen++; + } else if (state == lastState && input.next == greaterThan) { + if (i > matchedLen) + input.acceptToken(textToken, -matchedLen); + else + input.acceptToken(endToken, -(matchedLen - 2)); + break + } else if ((input.next == 10 /* '\n' */ || input.next == 13 /* '\r' */) && i) { + input.acceptToken(textToken, 1); + break + } else { + state = matchedLen = 0; + } input.advance(); - while (input.next >= 0 && input.next != braceClose && input.next != singleQuote && - input.next != doubleQuote && input.next != newline) input.advance(); - if (input.next == braceClose) input.advance(); } - } + }) } - const pythonHighlighting = styleTags({ - "async \"*\" \"**\" FormatConversion FormatSpec": tags.modifier, - "for while if elif else try except finally return raise break continue with pass assert await yield match case": tags.controlKeyword, - "in not and or is del": tags.operatorKeyword, - "from def class global nonlocal lambda": tags.definitionKeyword, - import: tags.moduleKeyword, - "with as print": tags.keyword, - Boolean: tags.bool, - None: tags.null, - VariableName: tags.variableName, - "CallExpression/VariableName": tags.function(tags.variableName), - "FunctionDefinition/VariableName": tags.function(tags.definition(tags.variableName)), - "ClassDefinition/VariableName": tags.definition(tags.className), - PropertyName: tags.propertyName, - "CallExpression/MemberExpression/PropertyName": tags.function(tags.propertyName), - Comment: tags.lineComment, - Number: tags.number, - String: tags.string, - FormatString: tags.special(tags.string), - Escape: tags.escape, - UpdateOp: tags.updateOperator, - "ArithOp!": tags.arithmeticOperator, - BitOp: tags.bitwiseOperator, - CompareOp: tags.compareOperator, - AssignOp: tags.definitionOperator, - Ellipsis: tags.punctuation, - At: tags.meta, - "( )": tags.paren, - "[ ]": tags.squareBracket, - "{ }": tags.brace, - ".": tags.derefOperator, - ", ;": tags.separator + const scriptTokens = contentTokenizer("script", scriptText, StartCloseScriptTag); + + const styleTokens = contentTokenizer("style", styleText, StartCloseStyleTag); + + const textareaTokens = contentTokenizer("textarea", textareaText, StartCloseTextareaTag); + + const htmlHighlighting = styleTags({ + "Text RawText": tags$1.content, + "StartTag StartCloseTag SelfClosingEndTag EndTag": tags$1.angleBracket, + TagName: tags$1.tagName, + "MismatchedCloseTag/TagName": [tags$1.tagName, tags$1.invalid], + AttributeName: tags$1.attributeName, + "AttributeValue UnquotedAttributeValue": tags$1.attributeValue, + Is: tags$1.definitionOperator, + "EntityReference CharacterReference": tags$1.character, + Comment: tags$1.blockComment, + ProcessingInst: tags$1.processingInstruction, + DoctypeDecl: tags$1.documentMeta }); // This file was generated by lezer-generator. You probably shouldn't edit it. - const spec_identifier = {__proto__:null,await:44, or:54, and:56, in:60, not:62, is:64, if:70, else:72, lambda:76, yield:94, from:96, async:102, for:104, None:162, True:164, False:164, del:178, pass:182, break:186, continue:190, return:194, raise:202, import:206, as:208, global:212, nonlocal:214, assert:218, type:223, elif:236, while:240, try:246, except:248, finally:250, with:254, def:258, class:268, match:279, case:285}; - const parser = LRParser.deserialize({ + const parser$3 = LRParser.deserialize({ version: 14, - states: "##jO`QeOOP$}OSOOO&WQtO'#HUOOQS'#Co'#CoOOQS'#Cp'#CpO'vQdO'#CnO*UQtO'#HTOOQS'#HU'#HUOOQS'#DU'#DUOOQS'#HT'#HTO*rQdO'#D_O+VQdO'#DfO+gQdO'#DjO+zOWO'#DuO,VOWO'#DvO.[QtO'#GuOOQS'#Gu'#GuO'vQdO'#GtO0ZQtO'#GtOOQS'#Eb'#EbO0rQdO'#EcOOQS'#Gs'#GsO0|QdO'#GrOOQV'#Gr'#GrO1XQdO'#FYOOQS'#G^'#G^O1^QdO'#FXOOQV'#IS'#ISOOQV'#Gq'#GqOOQV'#Fq'#FqQ`QeOOO'vQdO'#CqO1lQdO'#C}O1sQdO'#DRO2RQdO'#HYO2cQtO'#EVO'vQdO'#EWOOQS'#EY'#EYOOQS'#E['#E[OOQS'#E^'#E^O2wQdO'#E`O3_QdO'#EdO3rQdO'#EfO3zQtO'#EfO1XQdO'#EiO0rQdO'#ElO1XQdO'#EnO0rQdO'#EtO0rQdO'#EwO4VQdO'#EyO4^QdO'#FOO4iQdO'#EzO0rQdO'#FOO1XQdO'#FQO1XQdO'#FVO4nQdO'#F[P4uOdO'#GpPOOO)CBd)CBdOOQS'#Ce'#CeOOQS'#Cf'#CfOOQS'#Cg'#CgOOQS'#Ch'#ChOOQS'#Ci'#CiOOQS'#Cj'#CjOOQS'#Cl'#ClO'vQdO,59OO'vQdO,59OO'vQdO,59OO'vQdO,59OO'vQdO,59OO'vQdO,59OO5QQdO'#DoOOQS,5:Y,5:YO5eQdO'#HdOOQS,5:],5:]O5rQ!fO,5:]O5wQtO,59YO1lQdO,59bO1lQdO,59bO1lQdO,59bO8gQdO,59bO8lQdO,59bO8sQdO,59jO8zQdO'#HTO:QQdO'#HSOOQS'#HS'#HSOOQS'#D['#D[O:iQdO,59aO'vQdO,59aO:wQdO,59aOOQS,59y,59yO:|QdO,5:RO'vQdO,5:ROOQS,5:Q,5:QO;[QdO,5:QO;aQdO,5:XO'vQdO,5:XO'vQdO,5:VOOQS,5:U,5:UO;rQdO,5:UO;wQdO,5:WOOOW'#Fy'#FyO;|OWO,5:aOOQS,5:a,5:aOOOOQS'#Ds'#DsOOQS1G/w1G/wOOQS1G.|1G.|O!/RQtO1G.|O!/YQtO1G.|O1lQdO1G.|O!/uQdO1G/UOOQS'#DZ'#DZO0rQdO,59tOOQS1G.{1G.{O!/|QdO1G/eO!0^QdO1G/eO!0fQdO1G/fO'vQdO'#H[O!0kQdO'#H[O!0pQtO1G.{O!1QQdO,59iO!2WQdO,5=zO!2hQdO,5=zO!2pQdO1G/mO!2uQtO1G/mOOQS1G/l1G/lO!3VQdO,5=uO!3|QdO,5=uO0rQdO1G/qO!4kQdO1G/sO!4pQtO1G/sO!5QQtO1G/qOOQS1G/p1G/pOOQS1G/r1G/rOOOW-E9w-E9wOOQS1G/{1G/{O!5bQdO'#HxO0rQdO'#HxO!5sQdO,5>cOOOW-E9x-E9xOOQS1G/|1G/|OOQS-E9{-E9{O!6RQ#xO1G2zO!6rQtO1G2zO'vQdO,5kOOQS1G1`1G1`O!7xQdO1G1`OOQS'#DV'#DVO0rQdO,5=qOOQS,5=q,5=qO!7}QdO'#FrO!8YQdO,59oO!8bQdO1G/XO!8lQtO,5=uOOQS1G3`1G3`OOQS,5:m,5:mO!9]QdO'#GtOOQS,5jO!;QQdO,5>jO1XQdO,5>jO!;cQdO,5>iOOQS-E:R-E:RO!;hQdO1G0lO!;sQdO1G0lO!;xQdO,5>lO!lO!hO!<|QdO,5>hO!=_QdO'#EpO0rQdO1G0tO!=jQdO1G0tO!=oQgO1G0zO!AmQgO1G0}O!EhQdO,5>oO!ErQdO,5>oO!EzQtO,5>oO0rQdO1G1PO!FUQdO1G1PO4iQdO1G1UO!!sQdO1G1WOOQV,5;a,5;aO!FZQfO,5;aO!F`QgO1G1QO!JaQdO'#GZO4iQdO1G1QO4iQdO1G1QO!JqQdO,5>pO!KOQdO,5>pO1XQdO,5>pOOQV1G1U1G1UO!KWQdO'#FSO!KiQ!fO1G1WO!KqQdO1G1WOOQV1G1]1G1]O4iQdO1G1]O!KvQdO1G1]O!LOQdO'#F^OOQV1G1b1G1bO!#WQtO1G1bPOOO1G2v1G2vP!LTOSO1G2vOOQS,5=},5=}OOQS'#Dp'#DpO0rQdO,5=}O!LYQdO,5=|O!LmQdO,5=|OOQS1G/u1G/uO!LuQdO,5>PO!MVQdO,5>PO!M_QdO,5>PO!MrQdO,5>PO!NSQdO,5>POOQS1G3j1G3jOOQS7+$h7+$hO!8bQdO7+$pO# uQdO1G.|O# |QdO1G.|OOQS1G/`1G/`OOQS,5<`,5<`O'vQdO,5<`OOQS7+%P7+%PO#!TQdO7+%POOQS-E9r-E9rOOQS7+%Q7+%QO#!eQdO,5=vO'vQdO,5=vOOQS7+$g7+$gO#!jQdO7+%PO#!rQdO7+%QO#!wQdO1G3fOOQS7+%X7+%XO##XQdO1G3fO##aQdO7+%XOOQS,5<_,5<_O'vQdO,5<_O##fQdO1G3aOOQS-E9q-E9qO#$]QdO7+%]OOQS7+%_7+%_O#$kQdO1G3aO#%YQdO7+%_O#%_QdO1G3gO#%oQdO1G3gO#%wQdO7+%]O#%|QdO,5>dO#&gQdO,5>dO#&gQdO,5>dOOQS'#Dx'#DxO#&xO&jO'#DzO#'TO`O'#HyOOOW1G3}1G3}O#'YQdO1G3}O#'bQdO1G3}O#'mQ#xO7+(fO#(^QtO1G2UP#(wQdO'#GOOOQS,5bQdO,5gQdO1G4OOOQS-E9y-E9yO#?QQdO1G4OOe,5>eOOOW7+)i7+)iO#?nQdO7+)iO#?vQdO1G2zO#@aQdO1G2zP'vQdO'#FuO0rQdO<mO#AtQdO,5>mOOQS1G0v1G0vOOQS<rO#KZQdO,5>rOOQS,5>r,5>rO#KfQdO,5>qO#KwQdO,5>qOOQS1G1Y1G1YOOQS,5;p,5;pOOQV<VAN>VO$ WQdO<cAN>cO0rQdO1G1|O$ hQtO1G1|P$ rQdO'#FvOOQS1G2R1G2RP$!PQdO'#F{O$!^QdO7+)jO$!wQdO,5>gOOOO-E9z-E9zOOOW<tO$4dQdO,5>tO1XQdO,5vO$)VQdO,5>vOOQS1G1p1G1pO$8[QtO,5<[OOQU7+'P7+'PO$+cQdO1G/iO$)VQdO,5wO$8jQdO,5>wOOQS1G1s1G1sOOQS7+'S7+'SP$)VQdO'#GdO$8rQdO1G4bO$8|QdO1G4bO$9UQdO1G4bOOQS7+%T7+%TO$9dQdO1G1tO$9rQtO'#FaO$9yQdO,5<}OOQS,5<},5<}O$:XQdO1G4cOOQS-E:a-E:aO$)VQdO,5<|O$:`QdO,5<|O$:eQdO7+)|OOQS-E:`-E:`O$:oQdO7+)|O$)VQdO,5m>pPP'Z'ZPP?PPP'Z'ZPP'Z'Z'Z'Z'Z?T?}'ZP@QP@WD_G{HPPHSH^Hb'ZPPPHeHn'RP'R'RP'RP'RP'RP'RP'R'R'RP'RPP'RPP'RP'RPHtIQIYPIaIgPIaPIaIaPPPIaPKuPLOLYL`KuPIaLiPIaPLpLvPLzM`M}NhLzLzNnN{LzLzLzLz! a! g! j! o! r! |!!S!!`!!r!!x!#S!#Y!#v!#|!$S!$^!$d!$j!$|!%W!%^!%d!%n!%t!%z!&Q!&W!&^!&h!&n!&x!'O!'X!'_!'n!'v!(Q!(XPPPPPPPPPPP!(_!(b!(h!(q!({!)WPPPPPPPPPPPP!-z!/`!3`!6pPP!6x!7X!7b!8Z!8Q!8d!8j!8m!8p!8s!8{!9lPPPPPPPPPPPPPPPPP!9o!9s!9yP!:_!:c!:o!:x!;U!;l!;o!;r!;x!_![!]Do!]!^Es!^!_FZ!_!`Gk!`!aHX!a!b%T!b!cIf!c!dJU!d!eK^!e!hJU!h!i!#f!i!tJU!t!u!,|!u!wJU!w!x!.t!x!}JU!}#O!0S#O#P&o#P#Q!0j#Q#R!1Q#R#SJU#S#T%T#T#UJU#U#VK^#V#YJU#Y#Z!#f#Z#fJU#f#g!,|#g#iJU#i#j!.t#j#oJU#o#p!1n#p#q!1s#q#r!2a#r#s!2f#s$g%T$g;'SJU;'S;=`KW<%lOJU`%YT&n`O#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%T`%lP;=`<%l%To%v]&n`%c_OX%TXY%oY[%T[]%o]p%Tpq%oq#O%T#O#P&o#P#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%To&tX&n`OY%TYZ%oZ]%T]^%o^#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tc'f[&n`O!_%T!_!`([!`#T%T#T#U(r#U#f%T#f#g(r#g#h(r#h#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tc(cTmR&n`O#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tc(yT!mR&n`O#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk)aV&n`&[ZOr%Trs)vs#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk){V&n`Or%Trs*bs#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk*iT&n`&^ZO#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%To+PZS_&n`OY*xYZ%TZ]*x]^%T^#o*x#o#p+r#p#q*x#q#r+r#r;'S*x;'S;=`,^<%lO*x_+wTS_OY+rZ]+r^;'S+r;'S;=`,W<%lO+r_,ZP;=`<%l+ro,aP;=`<%l*xj,kV%rQ&n`O!_%T!_!`-Q!`#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tj-XT!xY&n`O#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tj-oV%lQ&n`O!_%T!_!`-Q!`#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk.]V&n`&ZZOw%Twx.rx#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk.wV&n`Ow%Twx/^x#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk/eT&n`&]ZO#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk/{ThZ&n`O#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tc0cTgR&n`O#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk0yXVZ&n`Oz%Tz{1f{!_%T!_!`-Q!`#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk1mVaR&n`O!_%T!_!`-Q!`#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk2ZV%oZ&n`O!_%T!_!`-Q!`#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tc2wTzR&n`O#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%To3_W%pZ&n`O!_%T!_!`-Q!`!a3w!a#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Td4OT&{S&n`O#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk4fX!fQ&n`O!O%T!O!P5R!P!Q%T!Q![6T![#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk5WV&n`O!O%T!O!P5m!P#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk5tT!rZ&n`O#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Ti6[a!hX&n`O!Q%T!Q![6T![!g%T!g!h7a!h!l%T!l!m9s!m#R%T#R#S6T#S#X%T#X#Y7a#Y#^%T#^#_9s#_#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Ti7fZ&n`O{%T{|8X|}%T}!O8X!O!Q%T!Q![8s![#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Ti8^V&n`O!Q%T!Q![8s![#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Ti8z]!hX&n`O!Q%T!Q![8s![!l%T!l!m9s!m#R%T#R#S8s#S#^%T#^#_9s#_#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Ti9zT!hX&n`O#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk:bX%qR&n`O!P%T!P!Q:}!Q!_%T!_!`-Q!`#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tj;UV%sQ&n`O!_%T!_!`-Q!`#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Ti;ro!hX&n`O!O%T!O!P=s!P!Q%T!Q![>_![!d%T!d!e?q!e!g%T!g!h7a!h!l%T!l!m9s!m!q%T!q!rA]!r!z%T!z!{Bq!{#R%T#R#S>_#S#U%T#U#V?q#V#X%T#X#Y7a#Y#^%T#^#_9s#_#c%T#c#dA]#d#l%T#l#mBq#m#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Ti=xV&n`O!Q%T!Q![6T![#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Ti>fc!hX&n`O!O%T!O!P=s!P!Q%T!Q![>_![!g%T!g!h7a!h!l%T!l!m9s!m#R%T#R#S>_#S#X%T#X#Y7a#Y#^%T#^#_9s#_#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Ti?vY&n`O!Q%T!Q!R@f!R!S@f!S#R%T#R#S@f#S#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Ti@mY!hX&n`O!Q%T!Q!R@f!R!S@f!S#R%T#R#S@f#S#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%TiAbX&n`O!Q%T!Q!YA}!Y#R%T#R#SA}#S#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%TiBUX!hX&n`O!Q%T!Q!YA}!Y#R%T#R#SA}#S#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%TiBv]&n`O!Q%T!Q![Co![!c%T!c!iCo!i#R%T#R#SCo#S#T%T#T#ZCo#Z#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%TiCv]!hX&n`O!Q%T!Q![Co![!c%T!c!iCo!i#R%T#R#SCo#S#T%T#T#ZCo#Z#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%ToDvV{_&n`O!_%T!_!`E]!`#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%TcEdT%{R&n`O#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%TkEzT#gZ&n`O#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%TkFbXmR&n`O!^%T!^!_F}!_!`([!`!a([!a#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%TjGUV%mQ&n`O!_%T!_!`-Q!`#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%TkGrV%zZ&n`O!_%T!_!`([!`#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%TkH`WmR&n`O!_%T!_!`([!`!aHx!a#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%TjIPV%nQ&n`O!_%T!_!`-Q!`#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%TkIoV_Q#}P&n`O!_%T!_!`-Q!`#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%ToJ_]&n`&YS%uZO!Q%T!Q![JU![!c%T!c!}JU!}#R%T#R#SJU#S#T%T#T#oJU#p#q%T#r$g%T$g;'SJU;'S;=`KW<%lOJUoKZP;=`<%lJUoKge&n`&YS%uZOr%Trs)Ysw%Twx.Ux!Q%T!Q![JU![!c%T!c!tJU!t!uLx!u!}JU!}#R%T#R#SJU#S#T%T#T#fJU#f#gLx#g#oJU#p#q%T#r$g%T$g;'SJU;'S;=`KW<%lOJUoMRa&n`&YS%uZOr%TrsNWsw%Twx! vx!Q%T!Q![JU![!c%T!c!}JU!}#R%T#R#SJU#S#T%T#T#oJU#p#q%T#r$g%T$g;'SJU;'S;=`KW<%lOJUkN_V&n`&`ZOr%TrsNts#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%TkNyV&n`Or%Trs! `s#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk! gT&n`&bZO#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk! }V&n`&_ZOw%Twx!!dx#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk!!iV&n`Ow%Twx!#Ox#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk!#VT&n`&aZO#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%To!#oe&n`&YS%uZOr%Trs!%Qsw%Twx!&px!Q%T!Q![JU![!c%T!c!tJU!t!u!(`!u!}JU!}#R%T#R#SJU#S#T%T#T#fJU#f#g!(`#g#oJU#p#q%T#r$g%T$g;'SJU;'S;=`KW<%lOJUk!%XV&n`&dZOr%Trs!%ns#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk!%sV&n`Or%Trs!&Ys#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk!&aT&n`&fZO#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk!&wV&n`&cZOw%Twx!'^x#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk!'cV&n`Ow%Twx!'xx#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk!(PT&n`&eZO#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%To!(ia&n`&YS%uZOr%Trs!)nsw%Twx!+^x!Q%T!Q![JU![!c%T!c!}JU!}#R%T#R#SJU#S#T%T#T#oJU#p#q%T#r$g%T$g;'SJU;'S;=`KW<%lOJUk!)uV&n`&hZOr%Trs!*[s#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk!*aV&n`Or%Trs!*vs#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk!*}T&n`&jZO#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk!+eV&n`&gZOw%Twx!+zx#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk!,PV&n`Ow%Twx!,fx#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tk!,mT&n`&iZO#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%To!-Vi&n`&YS%uZOr%TrsNWsw%Twx! vx!Q%T!Q![JU![!c%T!c!dJU!d!eLx!e!hJU!h!i!(`!i!}JU!}#R%T#R#SJU#S#T%T#T#UJU#U#VLx#V#YJU#Y#Z!(`#Z#oJU#p#q%T#r$g%T$g;'SJU;'S;=`KW<%lOJUo!.}a&n`&YS%uZOr%Trs)Ysw%Twx.Ux!Q%T!Q![JU![!c%T!c!}JU!}#R%T#R#SJU#S#T%T#T#oJU#p#q%T#r$g%T$g;'SJU;'S;=`KW<%lOJUk!0ZT!XZ&n`O#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tc!0qT!WR&n`O#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%Tj!1XV%kQ&n`O!_%T!_!`-Q!`#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%T~!1sO!]~k!1zV%jR&n`O!_%T!_!`-Q!`#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%T~!2fO![~i!2mT%tX&n`O#o%T#p#q%T#r;'S%T;'S;=`%i<%lO%T", - tokenizers: [legacyPrint, indentation, newlines, strings, 0, 1, 2, 3, 4], - topRules: {"Script":[0,5]}, - specialized: [{term: 221, get: (value) => spec_identifier[value] || -1}], - tokenPrec: 7652 + propSources: [htmlHighlighting], + skippedNodes: [0], + repeatNodeCount: 9, + tokenData: "!]tw8twx7Sx!P8t!P!Q5u!Q!]8t!]!^/^!^!a7S!a#S8t#S#T;{#T#s8t#s$f5u$f;'S8t;'S;=`>V<%l?Ah8t?Ah?BY5u?BY?Mn8t?MnO5u!Z5zbkWOX5uXZ7SZ[5u[^7S^p5uqr5urs7Sst+Ptw5uwx7Sx!]5u!]!^7w!^!a7S!a#S5u#S#T7S#T;'S5u;'S;=`8n<%lO5u!R7VVOp7Sqs7St!]7S!]!^7l!^;'S7S;'S;=`7q<%lO7S!R7qOa!R!R7tP;=`<%l7S!Z8OYkWa!ROX+PZ[+P^p+Pqr+Psw+Px!^+P!a#S+P#T;'S+P;'S;=`+t<%lO+P!Z8qP;=`<%l5u!_8{ihSkWOX5uXZ7SZ[5u[^7S^p5uqr8trs7Sst/^tw8twx7Sx!P8t!P!Q5u!Q!]8t!]!^:j!^!a7S!a#S8t#S#T;{#T#s8t#s$f5u$f;'S8t;'S;=`>V<%l?Ah8t?Ah?BY5u?BY?Mn8t?MnO5u!_:sbhSkWa!ROX+PZ[+P^p+Pqr/^sw/^x!P/^!P!Q+P!Q!^/^!a#S/^#S#T0m#T#s/^#s$f+P$f;'S/^;'S;=`1e<%l?Ah/^?Ah?BY+P?BY?Mn/^?MnO+P!VP<%l?Ah;{?Ah?BY7S?BY?Mn;{?MnO7S!V=dXhSa!Rqr0msw0mx!P0m!Q!^0m!a#s0m$f;'S0m;'S;=`1_<%l?Ah0m?BY?Mn0m!V>SP;=`<%l;{!_>YP;=`<%l8t!_>dhhSkWOX@OXZAYZ[@O[^AY^p@OqrBwrsAYswBwwxAYx!PBw!P!Q@O!Q!]Bw!]!^/^!^!aAY!a#SBw#S#TE{#T#sBw#s$f@O$f;'SBw;'S;=`HS<%l?AhBw?Ah?BY@O?BY?MnBw?MnO@O!Z@TakWOX@OXZAYZ[@O[^AY^p@Oqr@OrsAYsw@OwxAYx!]@O!]!^Az!^!aAY!a#S@O#S#TAY#T;'S@O;'S;=`Bq<%lO@O!RA]UOpAYq!]AY!]!^Ao!^;'SAY;'S;=`At<%lOAY!RAtOb!R!RAwP;=`<%lAY!ZBRYkWb!ROX+PZ[+P^p+Pqr+Psw+Px!^+P!a#S+P#T;'S+P;'S;=`+t<%lO+P!ZBtP;=`<%l@O!_COhhSkWOX@OXZAYZ[@O[^AY^p@OqrBwrsAYswBwwxAYx!PBw!P!Q@O!Q!]Bw!]!^Dj!^!aAY!a#SBw#S#TE{#T#sBw#s$f@O$f;'SBw;'S;=`HS<%l?AhBw?Ah?BY@O?BY?MnBw?MnO@O!_DsbhSkWb!ROX+PZ[+P^p+Pqr/^sw/^x!P/^!P!Q+P!Q!^/^!a#S/^#S#T0m#T#s/^#s$f+P$f;'S/^;'S;=`1e<%l?Ah/^?Ah?BY+P?BY?Mn/^?MnO+P!VFQbhSOpAYqrE{rsAYswE{wxAYx!PE{!P!QAY!Q!]E{!]!^GY!^!aAY!a#sE{#s$fAY$f;'SE{;'S;=`G|<%l?AhE{?Ah?BYAY?BY?MnE{?MnOAY!VGaXhSb!Rqr0msw0mx!P0m!Q!^0m!a#s0m$f;'S0m;'S;=`1_<%l?Ah0m?BY?Mn0m!VHPP;=`<%lE{!_HVP;=`<%lBw!ZHcW!bx`P!a`Or(trs'ksv(tw!^(t!^!_)e!_;'S(t;'S;=`*P<%lO(t!aIYlhS`PkW!a`!cpOX$qXZ&XZ[$q[^&X^p$qpq&Xqr-_rs&}sv-_vw/^wx(tx}-_}!OKQ!O!P-_!P!Q$q!Q!^-_!^!_*V!_!a&X!a#S-_#S#T1k#T#s-_#s$f$q$f;'S-_;'S;=`3X<%l?Ah-_?Ah?BY$q?BY?Mn-_?MnO$q!aK_khS`PkW!a`!cpOX$qXZ&XZ[$q[^&X^p$qpq&Xqr-_rs&}sv-_vw/^wx(tx!P-_!P!Q$q!Q!^-_!^!_*V!_!`&X!`!aMS!a#S-_#S#T1k#T#s-_#s$f$q$f;'S-_;'S;=`3X<%l?Ah-_?Ah?BY$q?BY?Mn-_?MnO$q!TM_X`P!a`!cp!eQOr&Xrs&}sv&Xwx(tx!^&X!^!_*V!_;'S&X;'S;=`*y<%lO&X!aNZ!ZhSfQ`PkW!a`!cpOX$qXZ&XZ[$q[^&X^p$qpq&Xqr-_rs&}sv-_vw/^wx(tx}-_}!OMz!O!PMz!P!Q$q!Q![Mz![!]Mz!]!^-_!^!_*V!_!a&X!a!c-_!c!}Mz!}#R-_#R#SMz#S#T1k#T#oMz#o#s-_#s$f$q$f$}-_$}%OMz%O%W-_%W%oMz%o%p-_%p&aMz&a&b-_&b1pMz1p4UMz4U4dMz4d4e-_4e$ISMz$IS$I`-_$I`$IbMz$Ib$Je-_$Je$JgMz$Jg$Kh-_$Kh%#tMz%#t&/x-_&/x&EtMz&Et&FV-_&FV;'SMz;'S;:j!#|;:j;=`3X<%l?&r-_?&r?AhMz?Ah?BY$q?BY?MnMz?MnO$q!a!$PP;=`<%lMz!R!$ZY!a`!cpOq*Vqr!$yrs(Vsv*Vwx)ex!a*V!a!b!4t!b;'S*V;'S;=`*s<%lO*V!R!%Q]!a`!cpOr*Vrs(Vsv*Vwx)ex}*V}!O!%y!O!f*V!f!g!']!g#W*V#W#X!0`#X;'S*V;'S;=`*s<%lO*V!R!&QX!a`!cpOr*Vrs(Vsv*Vwx)ex}*V}!O!&m!O;'S*V;'S;=`*s<%lO*V!R!&vV!a`!cp!dPOr*Vrs(Vsv*Vwx)ex;'S*V;'S;=`*s<%lO*V!R!'dX!a`!cpOr*Vrs(Vsv*Vwx)ex!q*V!q!r!(P!r;'S*V;'S;=`*s<%lO*V!R!(WX!a`!cpOr*Vrs(Vsv*Vwx)ex!e*V!e!f!(s!f;'S*V;'S;=`*s<%lO*V!R!(zX!a`!cpOr*Vrs(Vsv*Vwx)ex!v*V!v!w!)g!w;'S*V;'S;=`*s<%lO*V!R!)nX!a`!cpOr*Vrs(Vsv*Vwx)ex!{*V!{!|!*Z!|;'S*V;'S;=`*s<%lO*V!R!*bX!a`!cpOr*Vrs(Vsv*Vwx)ex!r*V!r!s!*}!s;'S*V;'S;=`*s<%lO*V!R!+UX!a`!cpOr*Vrs(Vsv*Vwx)ex!g*V!g!h!+q!h;'S*V;'S;=`*s<%lO*V!R!+xY!a`!cpOr!+qrs!,hsv!+qvw!-Swx!.[x!`!+q!`!a!/j!a;'S!+q;'S;=`!0Y<%lO!+qq!,mV!cpOv!,hvx!-Sx!`!,h!`!a!-q!a;'S!,h;'S;=`!.U<%lO!,hP!-VTO!`!-S!`!a!-f!a;'S!-S;'S;=`!-k<%lO!-SP!-kO{PP!-nP;=`<%l!-Sq!-xS!cp{POv(Vx;'S(V;'S;=`(h<%lO(Vq!.XP;=`<%l!,ha!.aX!a`Or!.[rs!-Ssv!.[vw!-Sw!`!.[!`!a!.|!a;'S!.[;'S;=`!/d<%lO!.[a!/TT!a`{POr)esv)ew;'S)e;'S;=`)y<%lO)ea!/gP;=`<%l!.[!R!/sV!a`!cp{POr*Vrs(Vsv*Vwx)ex;'S*V;'S;=`*s<%lO*V!R!0]P;=`<%l!+q!R!0gX!a`!cpOr*Vrs(Vsv*Vwx)ex#c*V#c#d!1S#d;'S*V;'S;=`*s<%lO*V!R!1ZX!a`!cpOr*Vrs(Vsv*Vwx)ex#V*V#V#W!1v#W;'S*V;'S;=`*s<%lO*V!R!1}X!a`!cpOr*Vrs(Vsv*Vwx)ex#h*V#h#i!2j#i;'S*V;'S;=`*s<%lO*V!R!2qX!a`!cpOr*Vrs(Vsv*Vwx)ex#m*V#m#n!3^#n;'S*V;'S;=`*s<%lO*V!R!3eX!a`!cpOr*Vrs(Vsv*Vwx)ex#d*V#d#e!4Q#e;'S*V;'S;=`*s<%lO*V!R!4XX!a`!cpOr*Vrs(Vsv*Vwx)ex#X*V#X#Y!+q#Y;'S*V;'S;=`*s<%lO*V!R!4{Y!a`!cpOr!4trs!5ksv!4tvw!6Vwx!8]x!a!4t!a!b!:]!b;'S!4t;'S;=`!;r<%lO!4tq!5pV!cpOv!5kvx!6Vx!a!5k!a!b!7W!b;'S!5k;'S;=`!8V<%lO!5kP!6YTO!a!6V!a!b!6i!b;'S!6V;'S;=`!7Q<%lO!6VP!6lTO!`!6V!`!a!6{!a;'S!6V;'S;=`!7Q<%lO!6VP!7QOxPP!7TP;=`<%l!6Vq!7]V!cpOv!5kvx!6Vx!`!5k!`!a!7r!a;'S!5k;'S;=`!8V<%lO!5kq!7yS!cpxPOv(Vx;'S(V;'S;=`(h<%lO(Vq!8YP;=`<%l!5ka!8bX!a`Or!8]rs!6Vsv!8]vw!6Vw!a!8]!a!b!8}!b;'S!8];'S;=`!:V<%lO!8]a!9SX!a`Or!8]rs!6Vsv!8]vw!6Vw!`!8]!`!a!9o!a;'S!8];'S;=`!:V<%lO!8]a!9vT!a`xPOr)esv)ew;'S)e;'S;=`)y<%lO)ea!:YP;=`<%l!8]!R!:dY!a`!cpOr!4trs!5ksv!4tvw!6Vwx!8]x!`!4t!`!a!;S!a;'S!4t;'S;=`!;r<%lO!4t!R!;]V!a`!cpxPOr*Vrs(Vsv*Vwx)ex;'S*V;'S;=`*s<%lO*V!R!;uP;=`<%l!4t!V! { - if (outer) - return false; - let id = node.node.getChild("VariableName"); - if (id) - def(id, type); - return true; - }; + function getAttrs(openTag, input) { + let attrs = Object.create(null); + for (let att of openTag.getChildren(Attribute)) { + let name = att.getChild(AttributeName), value = att.getChild(AttributeValue) || att.getChild(UnquotedAttributeValue); + if (name) attrs[input.read(name.from, name.to)] = + !value ? "" : value.type.id == AttributeValue ? input.read(value.from + 1, value.to - 1) : input.read(value.from, value.to); + } + return attrs } - const gatherCompletions = { - FunctionDefinition: /*@__PURE__*/defID("function"), - ClassDefinition: /*@__PURE__*/defID("class"), - ForStatement(node, def, outer) { - if (outer) - for (let child = node.node.firstChild; child; child = child.nextSibling) { - if (child.name == "VariableName") - def(child, "variable"); - else if (child.name == "in") - break; - } - }, - ImportStatement(_node, def) { - var _a, _b; - let { node } = _node; - let isFrom = ((_a = node.firstChild) === null || _a === void 0 ? void 0 : _a.name) == "from"; - for (let ch = node.getChild("import"); ch; ch = ch.nextSibling) { - if (ch.name == "VariableName" && ((_b = ch.nextSibling) === null || _b === void 0 ? void 0 : _b.name) != "as") - def(ch, isFrom ? "variable" : "namespace"); - } - }, - AssignStatement(node, def) { - for (let child = node.node.firstChild; child; child = child.nextSibling) { - if (child.name == "VariableName") - def(child, "variable"); - else if (child.name == ":" || child.name == "AssignOp") - break; + + function findTagName(openTag, input) { + let tagNameNode = openTag.getChild(TagName); + return tagNameNode ? input.read(tagNameNode.from, tagNameNode.to) : " " + } + + function maybeNest(node, input, tags) { + let attrs; + for (let tag of tags) { + if (!tag.attrs || tag.attrs(attrs || (attrs = getAttrs(node.node.parent.firstChild, input)))) + return {parser: tag.parser} + } + return null + } + + // tags?: { + // tag: string, + // attrs?: ({[attr: string]: string}) => boolean, + // parser: Parser + // }[] + // attributes?: { + // name: string, + // tagName?: string, + // parser: Parser + // }[] + + function configureNesting(tags = [], attributes = []) { + let script = [], style = [], textarea = [], other = []; + for (let tag of tags) { + let array = tag.tag == "script" ? script : tag.tag == "style" ? style : tag.tag == "textarea" ? textarea : other; + array.push(tag); + } + let attrs = attributes.length ? Object.create(null) : null; + for (let attr of attributes) (attrs[attr.name] || (attrs[attr.name] = [])).push(attr); + + return parseMixed((node, input) => { + let id = node.type.id; + if (id == ScriptText) return maybeNest(node, input, script) + if (id == StyleText) return maybeNest(node, input, style) + if (id == TextareaText) return maybeNest(node, input, textarea) + + if (id == Element && other.length) { + let n = node.node, open = n.firstChild, tagName = open && findTagName(open, input), attrs; + if (tagName) for (let tag of other) { + if (tag.tag == tagName && (!tag.attrs || tag.attrs(attrs || (attrs = getAttrs(open, input))))) { + let close = n.lastChild; + let to = close.type.id == CloseTag ? close.from : n.to; + if (to > open.to) + return {parser: tag.parser, overlay: [{from: open.to, to}]} } - }, - ParamList(node, def) { - for (let prev = null, child = node.node.firstChild; child; child = child.nextSibling) { - if (child.name == "VariableName" && (!prev || !/\*|AssignOp/.test(prev.name))) - def(child, "variable"); - prev = child; + } + } + + if (attrs && id == Attribute) { + let n = node.node, nameNode; + if (nameNode = n.firstChild) { + let matches = attrs[input.read(nameNode.from, nameNode.to)]; + if (matches) for (let attr of matches) { + if (attr.tagName && attr.tagName != findTagName(n.parent, input)) continue + let value = n.lastChild; + if (value.type.id == AttributeValue) { + let from = value.from + 1; + let last = value.lastChild, to = value.to - (last && last.isError ? 0 : 1); + if (to > from) return {parser: attr.parser, overlay: [{from, to}]} + } else if (value.type.id == UnquotedAttributeValue) { + return {parser: attr.parser, overlay: [{from: value.from, to: value.to}]} + } } - }, - CapturePattern: /*@__PURE__*/defID("variable"), - AsPattern: /*@__PURE__*/defID("variable"), - __proto__: null - }; - function getScope(doc, node) { - let cached = cache.get(node); - if (cached) + } + } + return null + }) + } + + // This file was generated by lezer-generator. You probably shouldn't edit it. + const descendantOp = 99, + Unit = 1, + callee = 100, + identifier$2 = 101, + VariableName = 2; + + /* Hand-written tokenizers for CSS tokens that can't be + expressed by Lezer's built-in tokenizer. */ + + const space$1 = [9, 10, 11, 12, 13, 32, 133, 160, 5760, 8192, 8193, 8194, 8195, 8196, 8197, + 8198, 8199, 8200, 8201, 8202, 8232, 8233, 8239, 8287, 12288]; + const colon = 58, parenL = 40, underscore = 95, bracketL = 91, dash = 45, period = 46, + hash = 35, percent = 37, ampersand = 38, backslash = 92, newline$1 = 10; + + function isAlpha(ch) { return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || ch >= 161 } + + function isDigit(ch) { return ch >= 48 && ch <= 57 } + + const identifiers = new ExternalTokenizer((input, stack) => { + for (let inside = false, dashes = 0, i = 0;; i++) { + let {next} = input; + if (isAlpha(next) || next == dash || next == underscore || (inside && isDigit(next))) { + if (!inside && (next != dash || i > 0)) inside = true; + if (dashes === i && next == dash) dashes++; + input.advance(); + } else if (next == backslash && input.peek(1) != newline$1) { + input.advance(); + if (input.next > -1) input.advance(); + inside = true; + } else { + if (inside) + input.acceptToken(next == parenL ? callee : dashes == 2 && stack.canShift(VariableName) ? VariableName : identifier$2); + break + } + } + }); + + const descendant = new ExternalTokenizer(input => { + if (space$1.includes(input.peek(-1))) { + let {next} = input; + if (isAlpha(next) || next == underscore || next == hash || next == period || + next == bracketL || next == colon && isAlpha(input.peek(1)) || + next == dash || next == ampersand) + input.acceptToken(descendantOp); + } + }); + + const unitToken = new ExternalTokenizer(input => { + if (!space$1.includes(input.peek(-1))) { + let {next} = input; + if (next == percent) { input.advance(); input.acceptToken(Unit); } + if (isAlpha(next)) { + do { input.advance(); } while (isAlpha(input.next) || isDigit(input.next)) + input.acceptToken(Unit); + } + } + }); + + const cssHighlighting = styleTags({ + "AtKeyword import charset namespace keyframes media supports": tags$1.definitionKeyword, + "from to selector": tags$1.keyword, + NamespaceName: tags$1.namespace, + KeyframeName: tags$1.labelName, + KeyframeRangeName: tags$1.operatorKeyword, + TagName: tags$1.tagName, + ClassName: tags$1.className, + PseudoClassName: tags$1.constant(tags$1.className), + IdName: tags$1.labelName, + "FeatureName PropertyName": tags$1.propertyName, + AttributeName: tags$1.attributeName, + NumberLiteral: tags$1.number, + KeywordQuery: tags$1.keyword, + UnaryQueryOp: tags$1.operatorKeyword, + "CallTag ValueName": tags$1.atom, + VariableName: tags$1.variableName, + Callee: tags$1.operatorKeyword, + Unit: tags$1.unit, + "UniversalSelector NestingSelector": tags$1.definitionOperator, + MatchOp: tags$1.compareOperator, + "ChildOp SiblingOp, LogicOp": tags$1.logicOperator, + BinOp: tags$1.arithmeticOperator, + Important: tags$1.modifier, + Comment: tags$1.blockComment, + ColorLiteral: tags$1.color, + "ParenthesizedContent StringLiteral": tags$1.string, + ":": tags$1.punctuation, + "PseudoOp #": tags$1.derefOperator, + "; ,": tags$1.separator, + "( )": tags$1.paren, + "[ ]": tags$1.squareBracket, + "{ }": tags$1.brace + }); + + // This file was generated by lezer-generator. You probably shouldn't edit it. + const spec_callee = {__proto__:null,lang:32, "nth-child":32, "nth-last-child":32, "nth-of-type":32, "nth-last-of-type":32, dir:32, "host-context":32, url:60, "url-prefix":60, domain:60, regexp:60, selector:138}; + const spec_AtKeyword = {__proto__:null,"@import":118, "@media":142, "@charset":146, "@namespace":150, "@keyframes":156, "@supports":168}; + const spec_identifier$1 = {__proto__:null,not:132, only:132}; + const parser$2 = LRParser.deserialize({ + version: 14, + states: ":^QYQ[OOO#_Q[OOP#fOWOOOOQP'#Cd'#CdOOQP'#Cc'#CcO#kQ[O'#CfO$_QXO'#CaO$fQ[O'#ChO$qQ[O'#DTO$vQ[O'#DWOOQP'#Em'#EmO${QdO'#DgO%jQ[O'#DtO${QdO'#DvO%{Q[O'#DxO&WQ[O'#D{O&`Q[O'#ERO&nQ[O'#ETOOQS'#El'#ElOOQS'#EW'#EWQYQ[OOO&uQXO'#CdO'jQWO'#DcO'oQWO'#EsO'zQ[O'#EsQOQWOOP(UO#tO'#C_POOO)C@[)C@[OOQP'#Cg'#CgOOQP,59Q,59QO#kQ[O,59QO(aQ[O'#E[O({QWO,58{O)TQ[O,59SO$qQ[O,59oO$vQ[O,59rO(aQ[O,59uO(aQ[O,59wO(aQ[O,59xO)`Q[O'#DbOOQS,58{,58{OOQP'#Ck'#CkOOQO'#DR'#DROOQP,59S,59SO)gQWO,59SO)lQWO,59SOOQP'#DV'#DVOOQP,59o,59oOOQO'#DX'#DXO)qQ`O,59rOOQS'#Cp'#CpO${QdO'#CqO)yQvO'#CsO+ZQtO,5:ROOQO'#Cx'#CxO)lQWO'#CwO+oQWO'#CyO+tQ[O'#DOOOQS'#Ep'#EpOOQO'#Dj'#DjO+|Q[O'#DqO,[QWO'#EtO&`Q[O'#DoO,jQWO'#DrOOQO'#Eu'#EuO)OQWO,5:`O,oQpO,5:bOOQS'#Dz'#DzO,wQWO,5:dO,|Q[O,5:dOOQO'#D}'#D}O-UQWO,5:gO-ZQWO,5:mO-cQWO,5:oOOQS-E8U-E8UO${QdO,59}O-kQ[O'#E^O-xQWO,5;_O-xQWO,5;_POOO'#EV'#EVP.TO#tO,58yPOOO,58y,58yOOQP1G.l1G.lO.zQXO,5:vOOQO-E8Y-E8YOOQS1G.g1G.gOOQP1G.n1G.nO)gQWO1G.nO)lQWO1G.nOOQP1G/Z1G/ZO/XQ`O1G/^O/rQXO1G/aO0YQXO1G/cO0pQXO1G/dO1WQWO,59|O1]Q[O'#DSO1dQdO'#CoOOQP1G/^1G/^O${QdO1G/^O1kQpO,59]OOQS,59_,59_O${QdO,59aO1sQWO1G/mOOQS,59c,59cO1xQ!bO,59eOOQS'#DP'#DPOOQS'#EY'#EYO2QQ[O,59jOOQS,59j,59jO2YQWO'#DjO2eQWO,5:VO2jQWO,5:]O&`Q[O,5:XO&`Q[O'#E_O2rQWO,5;`O2}QWO,5:ZO(aQ[O,5:^OOQS1G/z1G/zOOQS1G/|1G/|OOQS1G0O1G0OO3`QWO1G0OO3eQdO'#EOOOQS1G0R1G0ROOQS1G0X1G0XOOQS1G0Z1G0ZO3pQtO1G/iOOQO,5:x,5:xO4WQ[O,5:xOOQO-E8[-E8[O4eQWO1G0yPOOO-E8T-E8TPOOO1G.e1G.eOOQP7+$Y7+$YOOQP7+$x7+$xO${QdO7+$xOOQS1G/h1G/hO4pQXO'#ErO4wQWO,59nO4|QtO'#EXO5tQdO'#EoO6OQWO,59ZO6TQpO7+$xOOQS1G.w1G.wOOQS1G.{1G.{OOQS7+%X7+%XO6]QWO1G/POOQS-E8W-E8WOOQS1G/U1G/UO${QdO1G/qOOQO1G/w1G/wOOQO1G/s1G/sO6bQWO,5:yOOQO-E8]-E8]O6pQXO1G/xOOQS7+%j7+%jO6wQYO'#CsOOQO'#EQ'#EQO7SQ`O'#EPOOQO'#EP'#EPO7_QWO'#E`O7gQdO,5:jOOQS,5:j,5:jO7rQtO'#E]O${QdO'#E]O8sQdO7+%TOOQO7+%T7+%TOOQO1G0d1G0dO9WQpO<OAN>OO:xQdO,5:uOOQO-E8X-E8XOOQO<T![;'S%^;'S;=`%o<%lO%^l;TUo`Oy%^z!Q%^!Q![;g![;'S%^;'S;=`%o<%lO%^l;nYo`#e[Oy%^z!Q%^!Q![;g![!g%^!g!h<^!h#X%^#X#Y<^#Y;'S%^;'S;=`%o<%lO%^l[[o`#e[Oy%^z!O%^!O!P;g!P!Q%^!Q![>T![!g%^!g!h<^!h#X%^#X#Y<^#Y;'S%^;'S;=`%o<%lO%^n?VSt^Oy%^z;'S%^;'S;=`%o<%lO%^l?hWjWOy%^z!O%^!O!P;O!P!Q%^!Q![>T![;'S%^;'S;=`%o<%lO%^n@VU#bQOy%^z!Q%^!Q![;g![;'S%^;'S;=`%o<%lO%^~@nTjWOy%^z{@}{;'S%^;'S;=`%o<%lO%^~AUSo`#[~Oy%^z;'S%^;'S;=`%o<%lO%^lAg[#e[Oy%^z!O%^!O!P;g!P!Q%^!Q![>T![!g%^!g!h<^!h#X%^#X#Y<^#Y;'S%^;'S;=`%o<%lO%^bBbU]QOy%^z![%^![!]Bt!];'S%^;'S;=`%o<%lO%^bB{S^Qo`Oy%^z;'S%^;'S;=`%o<%lO%^nC^S!Y^Oy%^z;'S%^;'S;=`%o<%lO%^dCoS|SOy%^z;'S%^;'S;=`%o<%lO%^bDQU!OQOy%^z!`%^!`!aDd!a;'S%^;'S;=`%o<%lO%^bDkS!OQo`Oy%^z;'S%^;'S;=`%o<%lO%^bDzWOy%^z!c%^!c!}Ed!}#T%^#T#oEd#o;'S%^;'S;=`%o<%lO%^bEk[![Qo`Oy%^z}%^}!OEd!O!Q%^!Q![Ed![!c%^!c!}Ed!}#T%^#T#oEd#o;'S%^;'S;=`%o<%lO%^nFfSq^Oy%^z;'S%^;'S;=`%o<%lO%^nFwSp^Oy%^z;'S%^;'S;=`%o<%lO%^bGWUOy%^z#b%^#b#cGj#c;'S%^;'S;=`%o<%lO%^bGoUo`Oy%^z#W%^#W#XHR#X;'S%^;'S;=`%o<%lO%^bHYS!bQo`Oy%^z;'S%^;'S;=`%o<%lO%^bHiUOy%^z#f%^#f#gHR#g;'S%^;'S;=`%o<%lO%^fIQS!TUOy%^z;'S%^;'S;=`%o<%lO%^nIcS!S^Oy%^z;'S%^;'S;=`%o<%lO%^fItU!RQOy%^z!_%^!_!`6y!`;'S%^;'S;=`%o<%lO%^`JZP;=`<%l$}", + tokenizers: [descendant, unitToken, identifiers, 1, 2, 3, 4, new LocalTokenGroup("m~RRYZ[z{a~~g~aO#^~~dP!P!Qg~lO#_~~", 28, 105)], + topRules: {"StyleSheet":[0,4],"Styles":[1,86]}, + specialized: [{term: 100, get: (value) => spec_callee[value] || -1},{term: 58, get: (value) => spec_AtKeyword[value] || -1},{term: 101, get: (value) => spec_identifier$1[value] || -1}], + tokenPrec: 1200 + }); + + let _properties = null; + function properties$1() { + if (!_properties && typeof document == "object" && document.body) { + let { style } = document.body, names = [], seen = new Set; + for (let prop in style) + if (prop != "cssText" && prop != "cssFloat") { + if (typeof style[prop] == "string") { + if (/[A-Z]/.test(prop)) + prop = prop.replace(/[A-Z]/g, ch => "-" + ch.toLowerCase()); + if (!seen.has(prop)) { + names.push(prop); + seen.add(prop); + } + } + } + _properties = names.sort().map(name => ({ type: "property", label: name })); + } + return _properties || []; + } + const pseudoClasses = /*@__PURE__*/[ + "active", "after", "any-link", "autofill", "backdrop", "before", + "checked", "cue", "default", "defined", "disabled", "empty", + "enabled", "file-selector-button", "first", "first-child", + "first-letter", "first-line", "first-of-type", "focus", + "focus-visible", "focus-within", "fullscreen", "has", "host", + "host-context", "hover", "in-range", "indeterminate", "invalid", + "is", "lang", "last-child", "last-of-type", "left", "link", "marker", + "modal", "not", "nth-child", "nth-last-child", "nth-last-of-type", + "nth-of-type", "only-child", "only-of-type", "optional", "out-of-range", + "part", "placeholder", "placeholder-shown", "read-only", "read-write", + "required", "right", "root", "scope", "selection", "slotted", "target", + "target-text", "valid", "visited", "where" + ].map(name => ({ type: "class", label: name })); + const values = /*@__PURE__*/[ + "above", "absolute", "activeborder", "additive", "activecaption", "after-white-space", + "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate", "always", + "antialiased", "appworkspace", "asterisks", "attr", "auto", "auto-flow", "avoid", "avoid-column", + "avoid-page", "avoid-region", "axis-pan", "background", "backwards", "baseline", "below", + "bidi-override", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box", + "both", "bottom", "break", "break-all", "break-word", "bullets", "button", "button-bevel", + "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "capitalize", + "caps-lock-indicator", "caption", "captiontext", "caret", "cell", "center", "checkbox", "circle", + "cjk-decimal", "clear", "clip", "close-quote", "col-resize", "collapse", "color", "color-burn", + "color-dodge", "column", "column-reverse", "compact", "condensed", "contain", "content", + "contents", "content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", + "crop", "cross", "crosshair", "currentcolor", "cursive", "cyclic", "darken", "dashed", "decimal", + "decimal-leading-zero", "default", "default-button", "dense", "destination-atop", "destination-in", + "destination-out", "destination-over", "difference", "disc", "discard", "disclosure-closed", + "disclosure-open", "document", "dot-dash", "dot-dot-dash", "dotted", "double", "down", "e-resize", + "ease", "ease-in", "ease-in-out", "ease-out", "element", "ellipse", "ellipsis", "embed", "end", + "ethiopic-abegede-gez", "ethiopic-halehame-aa-er", "ethiopic-halehame-gez", "ew-resize", "exclusion", + "expanded", "extends", "extra-condensed", "extra-expanded", "fantasy", "fast", "fill", "fill-box", + "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes", "forwards", "from", + "geometricPrecision", "graytext", "grid", "groove", "hand", "hard-light", "help", "hidden", "hide", + "higher", "highlight", "highlighttext", "horizontal", "hsl", "hsla", "hue", "icon", "ignore", + "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite", "infobackground", "infotext", + "inherit", "initial", "inline", "inline-axis", "inline-block", "inline-flex", "inline-grid", + "inline-table", "inset", "inside", "intrinsic", "invert", "italic", "justify", "keep-all", + "landscape", "large", "larger", "left", "level", "lighter", "lighten", "line-through", "linear", + "linear-gradient", "lines", "list-item", "listbox", "listitem", "local", "logical", "loud", "lower", + "lower-hexadecimal", "lower-latin", "lower-norwegian", "lowercase", "ltr", "luminosity", "manipulation", + "match", "matrix", "matrix3d", "medium", "menu", "menutext", "message-box", "middle", "min-intrinsic", + "mix", "monospace", "move", "multiple", "multiple_mask_images", "multiply", "n-resize", "narrower", + "ne-resize", "nesw-resize", "no-close-quote", "no-drop", "no-open-quote", "no-repeat", "none", + "normal", "not-allowed", "nowrap", "ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", + "oblique", "opacity", "open-quote", "optimizeLegibility", "optimizeSpeed", "outset", "outside", + "outside-shape", "overlay", "overline", "padding", "padding-box", "painted", "page", "paused", + "perspective", "pinch-zoom", "plus-darker", "plus-lighter", "pointer", "polygon", "portrait", + "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button", "radial-gradient", "radio", + "read-only", "read-write", "read-write-plaintext-only", "rectangle", "region", "relative", "repeat", + "repeating-linear-gradient", "repeating-radial-gradient", "repeat-x", "repeat-y", "reset", "reverse", + "rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY", "rotateZ", "round", + "row", "row-resize", "row-reverse", "rtl", "run-in", "running", "s-resize", "sans-serif", "saturation", + "scale", "scale3d", "scaleX", "scaleY", "scaleZ", "screen", "scroll", "scrollbar", "scroll-position", + "se-resize", "self-start", "self-end", "semi-condensed", "semi-expanded", "separate", "serif", "show", + "single", "skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal", + "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow", "small", "small-caps", + "small-caption", "smaller", "soft-light", "solid", "source-atop", "source-in", "source-out", + "source-over", "space", "space-around", "space-between", "space-evenly", "spell-out", "square", "start", + "static", "status-bar", "stretch", "stroke", "stroke-box", "sub", "subpixel-antialiased", "svg_masks", + "super", "sw-resize", "symbolic", "symbols", "system-ui", "table", "table-caption", "table-cell", + "table-column", "table-column-group", "table-footer-group", "table-header-group", "table-row", + "table-row-group", "text", "text-bottom", "text-top", "textarea", "textfield", "thick", "thin", + "threeddarkshadow", "threedface", "threedhighlight", "threedlightshadow", "threedshadow", "to", "top", + "transform", "translate", "translate3d", "translateX", "translateY", "translateZ", "transparent", + "ultra-condensed", "ultra-expanded", "underline", "unidirectional-pan", "unset", "up", "upper-latin", + "uppercase", "url", "var", "vertical", "vertical-text", "view-box", "visible", "visibleFill", + "visiblePainted", "visibleStroke", "visual", "w-resize", "wait", "wave", "wider", "window", "windowframe", + "windowtext", "words", "wrap", "wrap-reverse", "x-large", "x-small", "xor", "xx-large", "xx-small" + ].map(name => ({ type: "keyword", label: name })).concat(/*@__PURE__*/[ + "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige", + "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown", + "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue", + "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod", + "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen", + "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen", + "darkslateblue", "darkslategray", "darkturquoise", "darkviolet", + "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick", + "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite", + "gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew", + "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender", + "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral", + "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink", + "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", + "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta", + "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple", + "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise", + "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin", + "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered", + "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred", + "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue", + "purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown", + "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue", + "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan", + "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white", + "whitesmoke", "yellow", "yellowgreen" + ].map(name => ({ type: "constant", label: name }))); + const tags = /*@__PURE__*/[ + "a", "abbr", "address", "article", "aside", "b", "bdi", "bdo", "blockquote", "body", + "br", "button", "canvas", "caption", "cite", "code", "col", "colgroup", "dd", "del", + "details", "dfn", "dialog", "div", "dl", "dt", "em", "figcaption", "figure", "footer", + "form", "header", "hgroup", "h1", "h2", "h3", "h4", "h5", "h6", "hr", "html", "i", "iframe", + "img", "input", "ins", "kbd", "label", "legend", "li", "main", "meter", "nav", "ol", "output", + "p", "pre", "ruby", "section", "select", "small", "source", "span", "strong", "sub", "summary", + "sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "tr", "u", "ul" + ].map(name => ({ type: "type", label: name })); + const identifier$1 = /^(\w[\w-]*|-\w[\w-]*|)$/, variable = /^-(-[\w-]*)?$/; + function isVarArg(node, doc) { + var _a; + if (node.name == "(" || node.type.isError) + node = node.parent || node; + if (node.name != "ArgList") + return false; + let callee = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.firstChild; + if ((callee === null || callee === void 0 ? void 0 : callee.name) != "Callee") + return false; + return doc.sliceString(callee.from, callee.to) == "var"; + } + const VariablesByNode = /*@__PURE__*/new NodeWeakMap(); + const declSelector = ["Declaration"]; + function astTop(node) { + for (let cur = node;;) { + if (cur.type.isTop) + return cur; + if (!(cur = cur.parent)) + return node; + } + } + function variableNames(doc, node, isVariable) { + if (node.to - node.from > 4096) { + let known = VariablesByNode.get(node); + if (known) + return known; + let result = [], seen = new Set, cursor = node.cursor(IterMode.IncludeAnonymous); + if (cursor.firstChild()) + do { + for (let option of variableNames(doc, cursor.node, isVariable)) + if (!seen.has(option.label)) { + seen.add(option.label); + result.push(option); + } + } while (cursor.nextSibling()); + VariablesByNode.set(node, result); + return result; + } + else { + let result = [], seen = new Set; + node.cursor().iterate(node => { + var _a; + if (isVariable(node) && node.matchContext(declSelector) && ((_a = node.node.nextSibling) === null || _a === void 0 ? void 0 : _a.name) == ":") { + let name = doc.sliceString(node.from, node.to); + if (!seen.has(name)) { + seen.add(name); + result.push({ label: name, type: "variable" }); + } + } + }); + return result; + } + } + /** + Create a completion source for a CSS dialect, providing a + predicate for determining what kind of syntax node can act as a + completable variable. This is used by language modes like Sass and + Less to reuse this package's completion logic. + */ + const defineCSSCompletionSource = (isVariable) => context => { + let { state, pos } = context, node = syntaxTree(state).resolveInner(pos, -1); + let isDash = node.type.isError && node.from == node.to - 1 && state.doc.sliceString(node.from, node.to) == "-"; + if (node.name == "PropertyName" || + (isDash || node.name == "TagName") && /^(Block|Styles)$/.test(node.resolve(node.to).name)) + return { from: node.from, options: properties$1(), validFor: identifier$1 }; + if (node.name == "ValueName") + return { from: node.from, options: values, validFor: identifier$1 }; + if (node.name == "PseudoClassName") + return { from: node.from, options: pseudoClasses, validFor: identifier$1 }; + if (isVariable(node) || (context.explicit || isDash) && isVarArg(node, state.doc)) + return { from: isVariable(node) || isDash ? node.from : pos, + options: variableNames(state.doc, astTop(node), isVariable), + validFor: variable }; + if (node.name == "TagName") { + for (let { parent } = node; parent; parent = parent.parent) + if (parent.name == "Block") + return { from: node.from, options: properties$1(), validFor: identifier$1 }; + return { from: node.from, options: tags, validFor: identifier$1 }; + } + if (!context.explicit) + return null; + let above = node.resolve(pos), before = above.childBefore(pos); + if (before && before.name == ":" && above.name == "PseudoClassSelector") + return { from: pos, options: pseudoClasses, validFor: identifier$1 }; + if (before && before.name == ":" && above.name == "Declaration" || above.name == "ArgList") + return { from: pos, options: values, validFor: identifier$1 }; + if (above.name == "Block" || above.name == "Styles") + return { from: pos, options: properties$1(), validFor: identifier$1 }; + return null; + }; + /** + CSS property, variable, and value keyword completion source. + */ + const cssCompletionSource = /*@__PURE__*/defineCSSCompletionSource(n => n.name == "VariableName"); + + /** + A language provider based on the [Lezer CSS + parser](https://github.com/lezer-parser/css), extended with + highlighting and indentation information. + */ + const cssLanguage = /*@__PURE__*/LRLanguage.define({ + name: "css", + parser: /*@__PURE__*/parser$2.configure({ + props: [ + /*@__PURE__*/indentNodeProp.add({ + Declaration: /*@__PURE__*/continuedIndent() + }), + /*@__PURE__*/foldNodeProp.add({ + "Block KeyframeList": foldInside + }) + ] + }), + languageData: { + commentTokens: { block: { open: "/*", close: "*/" } }, + indentOnInput: /^\s*\}$/, + wordChars: "-" + } + }); + /** + Language support for CSS. + */ + function css() { + return new LanguageSupport(cssLanguage, cssLanguage.data.of({ autocomplete: cssCompletionSource })); + } + + // This file was generated by lezer-generator. You probably shouldn't edit it. + const noSemi = 312, + incdec = 1, + incdecPrefix = 2, + questionDot = 3, + JSXStartTag = 4, + insertSemi = 313, + spaces = 315, + newline = 316, + LineComment = 5, + BlockComment = 6, + Dialect_jsx = 0; + + /* Hand-written tokenizers for JavaScript tokens that can't be + expressed by lezer's built-in tokenizer. */ + + const space = [9, 10, 11, 12, 13, 32, 133, 160, 5760, 8192, 8193, 8194, 8195, 8196, 8197, 8198, 8199, 8200, + 8201, 8202, 8232, 8233, 8239, 8287, 12288]; + + const braceR = 125, semicolon = 59, slash = 47, star = 42, plus = 43, minus = 45, lt = 60, comma = 44, + question = 63, dot = 46; + + const trackNewline = new ContextTracker({ + start: false, + shift(context, term) { + return term == LineComment || term == BlockComment || term == spaces ? context : term == newline + }, + strict: false + }); + + const insertSemicolon = new ExternalTokenizer((input, stack) => { + let {next} = input; + if (next == braceR || next == -1 || stack.context) + input.acceptToken(insertSemi); + }, {contextual: true, fallback: true}); + + const noSemicolon = new ExternalTokenizer((input, stack) => { + let {next} = input, after; + if (space.indexOf(next) > -1) return + if (next == slash && ((after = input.peek(1)) == slash || after == star)) return + if (next != braceR && next != semicolon && next != -1 && !stack.context) + input.acceptToken(noSemi); + }, {contextual: true}); + + const operatorToken = new ExternalTokenizer((input, stack) => { + let {next} = input; + if (next == plus || next == minus) { + input.advance(); + if (next == input.next) { + input.advance(); + let mayPostfix = !stack.context && stack.canShift(incdec); + input.acceptToken(mayPostfix ? incdec : incdecPrefix); + } + } else if (next == question && input.peek(1) == dot) { + input.advance(); input.advance(); + if (input.next < 48 || input.next > 57) // No digit after + input.acceptToken(questionDot); + } + }, {contextual: true}); + + function identifierChar(ch, start) { + return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || ch == 95 || ch >= 192 || + !start && ch >= 48 && ch <= 57 + } + + const jsx = new ExternalTokenizer((input, stack) => { + if (input.next != lt || !stack.dialectEnabled(Dialect_jsx)) return + input.advance(); + if (input.next == slash) return + // Scan for an identifier followed by a comma or 'extends', don't + // treat this as a start tag if present. + let back = 0; + while (space.indexOf(input.next) > -1) { input.advance(); back++; } + if (identifierChar(input.next, true)) { + input.advance(); + back++; + while (identifierChar(input.next, false)) { input.advance(); back++; } + while (space.indexOf(input.next) > -1) { input.advance(); back++; } + if (input.next == comma) return + for (let i = 0;; i++) { + if (i == 7) { + if (!identifierChar(input.next, true)) return + break + } + if (input.next != "extends".charCodeAt(i)) break + input.advance(); + back++; + } + } + input.acceptToken(JSXStartTag, -back); + }); + + const jsHighlight = styleTags({ + "get set async static": tags$1.modifier, + "for while do if else switch try catch finally return throw break continue default case": tags$1.controlKeyword, + "in of await yield void typeof delete instanceof": tags$1.operatorKeyword, + "let var const using function class extends": tags$1.definitionKeyword, + "import export from": tags$1.moduleKeyword, + "with debugger as new": tags$1.keyword, + TemplateString: tags$1.special(tags$1.string), + super: tags$1.atom, + BooleanLiteral: tags$1.bool, + this: tags$1.self, + null: tags$1.null, + Star: tags$1.modifier, + VariableName: tags$1.variableName, + "CallExpression/VariableName TaggedTemplateExpression/VariableName": tags$1.function(tags$1.variableName), + VariableDefinition: tags$1.definition(tags$1.variableName), + Label: tags$1.labelName, + PropertyName: tags$1.propertyName, + PrivatePropertyName: tags$1.special(tags$1.propertyName), + "CallExpression/MemberExpression/PropertyName": tags$1.function(tags$1.propertyName), + "FunctionDeclaration/VariableDefinition": tags$1.function(tags$1.definition(tags$1.variableName)), + "ClassDeclaration/VariableDefinition": tags$1.definition(tags$1.className), + PropertyDefinition: tags$1.definition(tags$1.propertyName), + PrivatePropertyDefinition: tags$1.definition(tags$1.special(tags$1.propertyName)), + UpdateOp: tags$1.updateOperator, + "LineComment Hashbang": tags$1.lineComment, + BlockComment: tags$1.blockComment, + Number: tags$1.number, + String: tags$1.string, + Escape: tags$1.escape, + ArithOp: tags$1.arithmeticOperator, + LogicOp: tags$1.logicOperator, + BitOp: tags$1.bitwiseOperator, + CompareOp: tags$1.compareOperator, + RegExp: tags$1.regexp, + Equals: tags$1.definitionOperator, + Arrow: tags$1.function(tags$1.punctuation), + ": Spread": tags$1.punctuation, + "( )": tags$1.paren, + "[ ]": tags$1.squareBracket, + "{ }": tags$1.brace, + "InterpolationStart InterpolationEnd": tags$1.special(tags$1.brace), + ".": tags$1.derefOperator, + ", ;": tags$1.separator, + "@": tags$1.meta, + + TypeName: tags$1.typeName, + TypeDefinition: tags$1.definition(tags$1.typeName), + "type enum interface implements namespace module declare": tags$1.definitionKeyword, + "abstract global Privacy readonly override": tags$1.modifier, + "is keyof unique infer": tags$1.operatorKeyword, + + JSXAttributeValue: tags$1.attributeValue, + JSXText: tags$1.content, + "JSXStartTag JSXStartCloseTag JSXSelfCloseEndTag JSXEndTag": tags$1.angleBracket, + "JSXIdentifier JSXNameSpacedName": tags$1.tagName, + "JSXAttribute/JSXIdentifier JSXAttribute/JSXNameSpacedName": tags$1.attributeName, + "JSXBuiltin/JSXIdentifier": tags$1.standard(tags$1.tagName) + }); + + // This file was generated by lezer-generator. You probably shouldn't edit it. + const spec_identifier = {__proto__:null,export:20, as:25, from:33, default:36, async:41, function:42, extends:54, this:58, true:66, false:66, null:78, void:82, typeof:86, super:102, new:136, delete:148, yield:157, await:161, class:166, public:229, private:229, protected:229, readonly:231, instanceof:250, satisfies:253, in:254, const:256, import:290, keyof:345, unique:349, infer:355, is:391, abstract:411, implements:413, type:415, let:418, var:420, using:423, interface:429, enum:433, namespace:439, module:441, declare:445, global:449, for:468, of:477, while:480, with:484, do:488, if:492, else:494, switch:498, case:504, try:510, catch:514, finally:518, return:522, throw:526, break:530, continue:534, debugger:538}; + const spec_word = {__proto__:null,async:123, get:125, set:127, declare:189, public:191, private:191, protected:191, static:193, abstract:195, override:197, readonly:203, accessor:205, new:395}; + const spec_LessThan = {__proto__:null,"<":187}; + const parser$1 = LRParser.deserialize({ + version: 14, + states: "$@QO%TQ^OOO%[Q^OOO'_Q`OOP(lOWOOO*zQ?NdO'#CiO+RO!bO'#CjO+aO#tO'#CjO+oO!0LbO'#D^O.QQ^O'#DdO.bQ^O'#DoO%[Q^O'#DwO0fQ^O'#EPOOQ?Mr'#EX'#EXO1PQWO'#EUOOQO'#Em'#EmOOQO'#Ih'#IhO1XQWO'#GpO1dQWO'#ElO1iQWO'#ElO3hQ?NdO'#JmO6[Q?NdO'#JnO6uQWO'#F[O6zQ&jO'#FsOOQ?Mr'#Fe'#FeO7VO,YO'#FeO7eQ7[O'#FzO9RQWO'#FyOOQ?Mr'#Jn'#JnOOQ?Mp'#Jm'#JmO9WQWO'#GtOOQU'#KZ'#KZO9cQWO'#IUO9hQ?MxO'#IVOOQU'#JZ'#JZOOQU'#IZ'#IZQ`Q^OOO`Q^OOO9pQMnO'#DsO9wQ^O'#D{O:OQ^O'#D}O9^QWO'#GpO:VQ7[O'#CoO:eQWO'#EkO:pQWO'#EvO:uQ7[O'#FdO;dQWO'#GpOOQO'#K['#K[O;iQWO'#K[O;wQWO'#GxO;wQWO'#GyO;wQWO'#G{O9^QWO'#HOOVQWO'#CeO>gQWO'#H_O>oQWO'#HeO>oQWO'#HgO`Q^O'#HiO>oQWO'#HkO>oQWO'#HnO>tQWO'#HtO>yQ?MyO'#HzO%[Q^O'#H|O?UQ?MyO'#IOO?aQ?MyO'#IQO9hQ?MxO'#ISO?lQ?NdO'#CiO@nQ`O'#DiQOQWOOO%[Q^O'#D}OAUQWO'#EQO:VQ7[O'#EkOAaQWO'#EkOAlQpO'#FdOOQU'#Cg'#CgOOQ?Mp'#Dn'#DnOOQ?Mp'#Jq'#JqO%[Q^O'#JqOOQO'#Jt'#JtOOQO'#Id'#IdOBlQ`O'#EdOOQ?Mp'#Ec'#EcOOQ?Mp'#Jx'#JxOChQ?NQO'#EdOCrQ`O'#ETOOQO'#Js'#JsODWQ`O'#JtOEeQ`O'#ETOCrQ`O'#EdPErO#@ItO'#CbPOOO)CDx)CDxOOOO'#I['#I[OE}O!bO,59UOOQ?Mr,59U,59UOOOO'#I]'#I]OF]O#tO,59UO%[Q^O'#D`OOOO'#I_'#I_OFkO!0LbO,59xOOQ?Mr,59x,59xOFyQ^O'#I`OG^QWO'#JoOI]QrO'#JoO+}Q^O'#JoOIdQWO,5:OOIzQWO'#EmOJXQWO'#KOOJdQWO'#J}OJdQWO'#J}OJlQWO,5;ZOJqQWO'#J|OOQ?Mv,5:Z,5:ZOJxQ^O,5:ZOLvQ?NdO,5:cOMgQWO,5:kONQQ?MxO'#J{ONXQWO'#JzO9WQWO'#JzONmQWO'#JzONuQWO,5;YONzQWO'#JzO!#PQrO'#JnOOQ?Mr'#Ci'#CiO%[Q^O'#EPO!#oQrO,5:pOOQQ'#Ju'#JuOOQO-EpOOQU'#Jc'#JcOOQU,5>q,5>qOOQU-EtQWO'#HTO9^QWO'#HVO!DgQWO'#HVO:VQ7[O'#HXO!DlQWO'#HXOOQU,5=m,5=mO!DqQWO'#HYO!ESQWO'#CoO!EXQWO,59PO!EcQWO,59PO!GhQ^O,59POOQU,59P,59PO!GxQ?MxO,59PO%[Q^O,59PO!JTQ^O'#HaOOQU'#Hb'#HbOOQU'#Hc'#HcO`Q^O,5=yO!JkQWO,5=yO`Q^O,5>PO`Q^O,5>RO!JpQWO,5>TO`Q^O,5>VO!JuQWO,5>YO!JzQ^O,5>`OOQU,5>f,5>fO%[Q^O,5>fO9hQ?MxO,5>hOOQU,5>j,5>jO# UQWO,5>jOOQU,5>l,5>lO# UQWO,5>lOOQU,5>n,5>nO# rQ`O'#D[O%[Q^O'#JqO# |Q`O'#JqO#!kQ`O'#DjO#!|Q`O'#DjO#%_Q^O'#DjO#%fQWO'#JpO#%nQWO,5:TO#%sQWO'#EqO#&RQWO'#KPO#&ZQWO,5;[O#&`Q`O'#DjO#&mQ`O'#ESOOQ?Mr,5:l,5:lO%[Q^O,5:lO#&tQWO,5:lO>tQWO,5;VO!A}Q`O,5;VO!BVQ7[O,5;VO:VQ7[O,5;VO#&|QWO,5@]O#'RQ(CYO,5:pOOQO-EzO+}Q^O,5>zOOQO,5?Q,5?QO#*ZQ^O'#I`OOQO-E<^-E<^O#*hQWO,5@ZO#*pQrO,5@ZO#*wQWO,5@iOOQ?Mr1G/j1G/jO%[Q^O,5@jO#+PQWO'#IfOOQO-EuQ?NdO1G0|O#>|Q?NdO1G0|O#AZQ07bO'#CiO#CUQ07bO1G1_O#C]Q07bO'#JnO#CpQ?NdO,5?WOOQ?Mp-EoQWO1G3oO$3VQ^O1G3qO$7ZQ^O'#HpOOQU1G3t1G3tO$7hQWO'#HvO>tQWO'#HxOOQU1G3z1G3zO$7pQ^O1G3zO9hQ?MxO1G4QOOQU1G4S1G4SOOQ?Mp'#G]'#G]O9hQ?MxO1G4UO9hQ?MxO1G4WO$;wQWO,5@]O!(oQ^O,5;]O9WQWO,5;]O>tQWO,5:UO!(oQ^O,5:UO!A}Q`O,5:UO$;|Q07bO,5:UOOQO,5;],5;]O$tQWO1G0qO!A}Q`O1G0qO!BVQ7[O1G0qOOQ?Mp1G5w1G5wO!ArQ?MxO1G0ZOOQO1G0j1G0jO%[Q^O1G0jO$=aQ?MxO1G0jO$=lQ?MxO1G0jO!A}Q`O1G0ZOCrQ`O1G0ZO$=zQ?MxO1G0jOOQO1G0Z1G0ZO$>`Q?NdO1G0jPOOO-EjQpO,5rQrO1G4fOOQO1G4l1G4lO%[Q^O,5>zO$>|QWO1G5uO$?UQWO1G6TO$?^QrO1G6UO9WQWO,5?QO$?hQ?NdO1G6RO%[Q^O1G6RO$?xQ?MxO1G6RO$@ZQWO1G6QO$@ZQWO1G6QO9WQWO1G6QO$@cQWO,5?TO9WQWO,5?TOOQO,5?T,5?TO$@wQWO,5?TO$(PQWO,5?TOOQO-E[OOQU,5>[,5>[O%[Q^O'#HqO%8mQWO'#HsOOQU,5>b,5>bO9WQWO,5>bOOQU,5>d,5>dOOQU7+)f7+)fOOQU7+)l7+)lOOQU7+)p7+)pOOQU7+)r7+)rO%8rQ`O1G5wO%9WQ07bO1G0wO%9bQWO1G0wOOQO1G/p1G/pO%9mQ07bO1G/pO>tQWO1G/pO!(oQ^O'#DjOOQO,5>{,5>{OOQO-E<_-E<_OOQO,5?R,5?ROOQO-EtQWO7+&]O!A}Q`O7+&]OOQO7+%u7+%uO$>`Q?NdO7+&UOOQO7+&U7+&UO%[Q^O7+&UO%9wQ?MxO7+&UO!ArQ?MxO7+%uO!A}Q`O7+%uO%:SQ?MxO7+&UO%:bQ?NdO7++mO%[Q^O7++mO%:rQWO7++lO%:rQWO7++lOOQO1G4o1G4oO9WQWO1G4oO%:zQWO1G4oOOQQ7+%z7+%zO#&wQWO<|O%[Q^O,5>|OOQO-E<`-E<`O%FwQWO1G5xOOQ?Mr<]OOQU,5>_,5>_O&8uQWO1G3|O9WQWO7+&cO!(oQ^O7+&cOOQO7+%[7+%[O&8zQ07bO1G6UO>tQWO7+%[OOQ?Mr<tQWO<`Q?NdO<pQ?NdO,5?_O&@xQ?NdO7+'zO&CWQrO1G4hO&CbQ07bO7+&^O&EcQ07bO,5=UO&GgQ07bO,5=WO&GwQ07bO,5=UO&HXQ07bO,5=WO&HiQ07bO,59rO&JlQ07bO,5tQWO7+)hO'(OQWO<`Q?NdOAN?[OOQOAN>{AN>{O%[Q^OAN?[OOQO<`Q?NdOG24vO#&wQWOLD,nOOQULD,nLD,nO!&_Q7[OLD,nO'5TQrOLD,nO'5[Q07bO7+'xO'6}Q07bO,5?]O'8}Q07bO,5?_O':}Q07bO7+'zO'kOh%VOk+aO![']O%f+`O~O!d+cOa(WX![(WX'u(WX!Y(WX~Oa%lO![XO'u%lO~Oh%VO!i%cO~Oh%VO!i%cO(O%eO~O!d#vO#h(tO~Ob+nO%g+oO(O+kO(QTO(TUO!Z)TP~O!Y+pO`)SX~O[+tO~O`+uO~O![%}O(O%eO(P!lO`)SP~Oh%VO#]+zO~Oh%VOk+}O![$|O~O![,PO~O},RO![XO~O%k%tO~O!u,WO~Oe,]O~Ob,^O(O#nO(QTO(TUO!Z)RP~Oe%{O~O%g!QO(O&WO~P=RO[,cO`,bO~OPYOQYOSfOdzOeyOmkOoYOpkOqkOwkOyYO{YO!PWO!TkO!UkO!fuO!iZO!lYO!mYO!nYO!pvO!uxO!y]O%e}O(QTO(TUO([VO(j[O(yiO~O![!eO!r!gO$V!kO(O!dO~P!EkO`,bOa%lO'u%lO~OPYOQYOSfOd!jOe!iOmkOoYOpkOqkOwkOyYO{YO!PWO!TkO!UkO![!eO!fuO!iZO!lYO!mYO!nYO!pvO!u!hO$V!kO(O!dO(QTO(TUO([VO(j[O(yiO~Oa,hO!rwO#t!OO%i!OO%j!OO%k!OO~P!HTO!i&lO~O&Y,nO~O![,pO~O&k,rO&m,sOP&haQ&haS&haY&haa&had&hae&ham&hao&hap&haq&haw&hay&ha{&ha!P&ha!T&ha!U&ha![&ha!f&ha!i&ha!l&ha!m&ha!n&ha!p&ha!r&ha!u&ha!y&ha#t&ha$V&ha%e&ha%g&ha%i&ha%j&ha%k&ha%n&ha%p&ha%s&ha%t&ha%v&ha&S&ha&Y&ha&[&ha&^&ha&`&ha&c&ha&i&ha&o&ha&q&ha&s&ha&u&ha&w&ha's&ha(O&ha(Q&ha(T&ha([&ha(j&ha(y&ha!Z&ha&a&hab&ha&f&ha~O(O,xO~Oh!bX!Y!OX!Z!OX!d!OX!d!bX!i!bX#]!OX~O!Y!bX!Z!bX~P# ZO!d,}O#],|Oh(eX!Y#eX!Y(eX!Z#eX!Z(eX!d(eX!i(eX~Oh%VO!d-PO!i%cO!Y!^X!Z!^X~Op!nO!P!oO(QTO(TUO(`!mO~OP;POQ;POSfOdkOg'XX!Y'XX~P!+hO!Y.wOg(ka~OSfO![3uO$c3vO~O!Z3zO~Os3{O~P#.aOa$lq!Y$lq'u$lq's$lq!V$lq!h$lqs$lq![$lq%f$lq!d$lq~P!9mO!V3|O~P#.aO})zO!P){O(u%POk'ea(t'ea!Y'ea#]'ea~Og'ea#}'ea~P%)nO})zO!P){Ok'ga(t'ga(u'ga!Y'ga#]'ga~Og'ga#}'ga~P%*aO(m$YO~P#.aO!VfX!V$xX!YfX!Y$xX!d%PX#]fX~P!/gO(OQ#>g#@V#@e#@l#BR#Ba#C|#D[#Db#Dh#Dn#Dx#EO#EU#E`#Er#ExPPPPPPPPPP#FOPPPPPPP#Fs#Iz#KZ#Kb#KjPPP$!sP$!|$%t$,^$,a$,d$-P$-S$-Z$-cP$-i$-lP$.Y$.^$/U$0d$0i$1PPP$1U$1[$1`P$1c$1g$1k$2a$2x$3a$3e$3h$3k$3q$3t$3x$3|R!|RoqOXst!Z#d%k&o&q&r&t,k,p1|2PY!vQ']-]1a5eQ%rvQ%zyQ&R|Q&g!VS'T!e-TQ'c!iS'i!r!yU*e$|*V*jQ+i%{Q+v&TQ,[&aQ-Z'[Q-e'dQ-m'jQ0R*lQ1k,]R;v;T%QdOPWXYZstuvw!Z!`!g!o#S#W#Z#d#o#u#x#{$O$P$Q$R$S$T$U$V$W$X$_$a$e%k%r&P&h&k&o&q&r&t&x'Q'_'o(P(R(X(`(t(v(z)y+R+V,h,k,p-a-i-w-}.l.s/f0a0g0v1d1t1u1w1y1|2P2R2r2x3^5b5m5}6O6R6f8R8X8h8rS#q];Q!r)Z$Z$n'U)o,|-P.}2b3u5`6]9h9y;P;S;T;W;X;Y;Z;[;];^;_;`;a;b;c;d;f;i;v;x;y;{ < TypeParamList TypeDefinition extends ThisType this LiteralType ArithOp Number BooleanLiteral TemplateType InterpolationEnd Interpolation InterpolationStart NullType null VoidType void TypeofType typeof MemberExpression . PropertyName [ TemplateString Escape Interpolation super RegExp ] ArrayExpression Spread , } { ObjectExpression Property async get set PropertyDefinition Block : NewTarget new NewExpression ) ( ArgList UnaryExpression delete LogicOp BitOp YieldExpression yield AwaitExpression await ParenthesizedExpression ClassExpression class ClassBody MethodDeclaration Decorator @ MemberExpression PrivatePropertyName CallExpression TypeArgList CompareOp < declare Privacy static abstract override PrivatePropertyDefinition PropertyDeclaration readonly accessor Optional TypeAnnotation Equals StaticBlock FunctionExpression ArrowFunction ParamList ParamList ArrayPattern ObjectPattern PatternProperty Privacy readonly Arrow MemberExpression BinaryExpression ArithOp ArithOp ArithOp ArithOp BitOp CompareOp instanceof satisfies in const CompareOp BitOp BitOp BitOp LogicOp LogicOp ConditionalExpression LogicOp LogicOp AssignmentExpression UpdateOp PostfixExpression CallExpression InstantiationExpression TaggedTemplateExpression DynamicImport import ImportMeta JSXElement JSXSelfCloseEndTag JSXSelfClosingTag JSXIdentifier JSXBuiltin JSXIdentifier JSXNamespacedName JSXMemberExpression JSXSpreadAttribute JSXAttribute JSXAttributeValue JSXEscape JSXEndTag JSXOpenTag JSXFragmentTag JSXText JSXEscape JSXStartCloseTag JSXCloseTag PrefixCast ArrowFunction TypeParamList SequenceExpression InstantiationExpression KeyofType keyof UniqueType unique ImportType InferredType infer TypeName ParenthesizedType FunctionSignature ParamList NewSignature IndexedType TupleType Label ArrayType ReadonlyType ObjectType MethodType PropertyType IndexSignature PropertyDefinition CallSignature TypePredicate is NewSignature new UnionType LogicOp IntersectionType LogicOp ConditionalType ParameterizedType ClassDeclaration abstract implements type VariableDeclaration let var using TypeAliasDeclaration InterfaceDeclaration interface EnumDeclaration enum EnumBody NamespaceDeclaration namespace module AmbientDeclaration declare GlobalDeclaration global ClassDeclaration ClassBody AmbientFunctionDeclaration ExportGroup VariableName VariableName ImportDeclaration ImportGroup ForStatement for ForSpec ForInSpec ForOfSpec of WhileStatement while WithStatement with DoStatement do IfStatement if else SwitchStatement switch SwitchBody CaseLabel case DefaultLabel TryStatement try CatchClause catch FinallyClause finally ReturnStatement return ThrowStatement throw BreakStatement break ContinueStatement continue DebuggerStatement debugger LabeledStatement ExpressionStatement SingleExpression SingleClassItem", + maxTerm: 376, + context: trackNewline, + nodeProps: [ + ["isolate", -8,5,6,14,34,36,48,50,52,""], + ["group", -26,9,17,19,65,204,208,212,213,215,218,221,231,233,239,241,243,245,248,254,260,262,264,266,268,270,271,"Statement",-34,13,14,29,32,33,39,48,51,52,54,59,67,69,73,77,79,81,82,107,108,117,118,135,138,140,141,142,143,144,146,147,166,167,169,"Expression",-23,28,30,34,38,40,42,171,173,175,176,178,179,180,182,183,184,186,187,188,198,200,202,203,"Type",-3,85,100,106,"ClassItem"], + ["openedBy", 23,"<",35,"InterpolationStart",53,"[",57,"{",70,"(",159,"JSXStartCloseTag"], + ["closedBy", 24,">",37,"InterpolationEnd",47,"]",58,"}",71,")",164,"JSXEndTag"] + ], + propSources: [jsHighlight], + skippedNodes: [0,5,6,274], + repeatNodeCount: 37, + tokenData: "$Fq07[R!bOX%ZXY+gYZ-yZ[+g[]%Z]^.c^p%Zpq+gqr/mrs3cst:_tuEruvJSvwLkwx! Yxy!'iyz!(sz{!)}{|!,q|}!.O}!O!,q!O!P!/Y!P!Q!9j!Q!R#:O!R![#<_![!]#I_!]!^#Jk!^!_#Ku!_!`$![!`!a$$v!a!b$*T!b!c$,r!c!}Er!}#O$-|#O#P$/W#P#Q$4o#Q#R$5y#R#SEr#S#T$7W#T#o$8b#o#p$x#r#s$@U#s$f%Z$f$g+g$g#BYEr#BY#BZ$A`#BZ$ISEr$IS$I_$A`$I_$I|Er$I|$I}$Dk$I}$JO$Dk$JO$JTEr$JT$JU$A`$JU$KVEr$KV$KW$A`$KW&FUEr&FU&FV$A`&FV;'SEr;'S;=`I|<%l?HTEr?HT?HU$A`?HUOEr(n%d_$h&j(Rp(U!bOY%ZYZ&cZr%Zrs&}sw%Zwx(rx!^%Z!^!_*g!_#O%Z#O#P&c#P#o%Z#o#p*g#p;'S%Z;'S;=`+a<%lO%Z&j&hT$h&jO!^&c!_#o&c#p;'S&c;'S;=`&w<%lO&c&j&zP;=`<%l&c'|'U]$h&j(U!bOY&}YZ&cZw&}wx&cx!^&}!^!_'}!_#O&}#O#P&c#P#o&}#o#p'}#p;'S&};'S;=`(l<%lO&}!b(SU(U!bOY'}Zw'}x#O'}#P;'S'};'S;=`(f<%lO'}!b(iP;=`<%l'}'|(oP;=`<%l&}'[(y]$h&j(RpOY(rYZ&cZr(rrs&cs!^(r!^!_)r!_#O(r#O#P&c#P#o(r#o#p)r#p;'S(r;'S;=`*a<%lO(rp)wU(RpOY)rZr)rs#O)r#P;'S)r;'S;=`*Z<%lO)rp*^P;=`<%l)r'[*dP;=`<%l(r#S*nX(Rp(U!bOY*gZr*grs'}sw*gwx)rx#O*g#P;'S*g;'S;=`+Z<%lO*g#S+^P;=`<%l*g(n+dP;=`<%l%Z07[+rq$h&j(Rp(U!b'w0/lOX%ZXY+gYZ&cZ[+g[p%Zpq+gqr%Zrs&}sw%Zwx(rx!^%Z!^!_*g!_#O%Z#O#P&c#P#o%Z#o#p*g#p$f%Z$f$g+g$g#BY%Z#BY#BZ+g#BZ$IS%Z$IS$I_+g$I_$JT%Z$JT$JU+g$JU$KV%Z$KV$KW+g$KW&FU%Z&FU&FV+g&FV;'S%Z;'S;=`+a<%l?HT%Z?HT?HU+g?HUO%Z07[.ST(S#S$h&j'x0/lO!^&c!_#o&c#p;'S&c;'S;=`&w<%lO&c07[.n_$h&j(Rp(U!b'x0/lOY%ZYZ&cZr%Zrs&}sw%Zwx(rx!^%Z!^!_*g!_#O%Z#O#P&c#P#o%Z#o#p*g#p;'S%Z;'S;=`+a<%lO%Z)3p/x`$h&j!m),Q(Rp(U!bOY%ZYZ&cZr%Zrs&}sw%Zwx(rx!^%Z!^!_*g!_!`0z!`#O%Z#O#P&c#P#o%Z#o#p*g#p;'S%Z;'S;=`+a<%lO%Z(KW1V`#u(Ch$h&j(Rp(U!bOY%ZYZ&cZr%Zrs&}sw%Zwx(rx!^%Z!^!_*g!_!`2X!`#O%Z#O#P&c#P#o%Z#o#p*g#p;'S%Z;'S;=`+a<%lO%Z(KW2d_#u(Ch$h&j(Rp(U!bOY%ZYZ&cZr%Zrs&}sw%Zwx(rx!^%Z!^!_*g!_#O%Z#O#P&c#P#o%Z#o#p*g#p;'S%Z;'S;=`+a<%lO%Z'At3l_(Q':f$h&j(U!bOY4kYZ5qZr4krs7nsw4kwx5qx!^4k!^!_8p!_#O4k#O#P5q#P#o4k#o#p8p#p;'S4k;'S;=`:X<%lO4k(^4r_$h&j(U!bOY4kYZ5qZr4krs7nsw4kwx5qx!^4k!^!_8p!_#O4k#O#P5q#P#o4k#o#p8p#p;'S4k;'S;=`:X<%lO4k&z5vX$h&jOr5qrs6cs!^5q!^!_6y!_#o5q#o#p6y#p;'S5q;'S;=`7h<%lO5q&z6jT$c`$h&jO!^&c!_#o&c#p;'S&c;'S;=`&w<%lO&c`6|TOr6yrs7]s;'S6y;'S;=`7b<%lO6y`7bO$c``7eP;=`<%l6y&z7kP;=`<%l5q(^7w]$c`$h&j(U!bOY&}YZ&cZw&}wx&cx!^&}!^!_'}!_#O&}#O#P&c#P#o&}#o#p'}#p;'S&};'S;=`(l<%lO&}!r8uZ(U!bOY8pYZ6yZr8prs9hsw8pwx6yx#O8p#O#P6y#P;'S8p;'S;=`:R<%lO8p!r9oU$c`(U!bOY'}Zw'}x#O'}#P;'S'};'S;=`(f<%lO'}!r:UP;=`<%l8p(^:[P;=`<%l4k%9[:hh$h&j(Rp(U!bOY%ZYZ&cZq%Zqr`#P#o`x!^=^!^!_?q!_#O=^#O#P>`#P#o=^#o#p?q#p;'S=^;'S;=`@h<%lO=^&n>gXWS$h&jOY>`YZ&cZ!^>`!^!_?S!_#o>`#o#p?S#p;'S>`;'S;=`?k<%lO>`S?XSWSOY?SZ;'S?S;'S;=`?e<%lO?SS?hP;=`<%l?S&n?nP;=`<%l>`!f?xWWS(U!bOY?qZw?qwx?Sx#O?q#O#P?S#P;'S?q;'S;=`@b<%lO?q!f@eP;=`<%l?q(Q@kP;=`<%l=^'`@w]WS$h&j(RpOY@nYZ&cZr@nrs>`s!^@n!^!_Ap!_#O@n#O#P>`#P#o@n#o#pAp#p;'S@n;'S;=`Bg<%lO@ntAwWWS(RpOYApZrAprs?Ss#OAp#O#P?S#P;'SAp;'S;=`Ba<%lOAptBdP;=`<%lAp'`BjP;=`<%l@n#WBvYWS(Rp(U!bOYBmZrBmrs?qswBmwxApx#OBm#O#P?S#P;'SBm;'S;=`Cf<%lOBm#WCiP;=`<%lBm(rCoP;=`<%l^!Q^$h&j!U7`OY!=yYZ&cZ!P!=y!P!Q!>|!Q!^!=y!^!_!@c!_!}!=y!}#O!CW#O#P!Dy#P#o!=y#o#p!@c#p;'S!=y;'S;=`!Ek<%lO!=y|#X#Z&c#Z#[!>|#[#]&c#]#^!>|#^#a&c#a#b!>|#b#g&c#g#h!>|#h#i&c#i#j!>|#j#k!>|#k#m&c#m#n!>|#n#o&c#p;'S&c;'S;=`&w<%lO&c7`!@hX!U7`OY!@cZ!P!@c!P!Q!AT!Q!}!@c!}#O!Ar#O#P!Bq#P;'S!@c;'S;=`!CQ<%lO!@c7`!AYW!U7`#W#X!AT#Z#[!AT#]#^!AT#a#b!AT#g#h!AT#i#j!AT#j#k!AT#m#n!AT7`!AuVOY!ArZ#O!Ar#O#P!B[#P#Q!@c#Q;'S!Ar;'S;=`!Bk<%lO!Ar7`!B_SOY!ArZ;'S!Ar;'S;=`!Bk<%lO!Ar7`!BnP;=`<%l!Ar7`!BtSOY!@cZ;'S!@c;'S;=`!CQ<%lO!@c7`!CTP;=`<%l!@c^!Ezl$h&j(U!b!U7`OY&}YZ&cZw&}wx&cx!^&}!^!_'}!_#O&}#O#P&c#P#W&}#W#X!Eq#X#Z&}#Z#[!Eq#[#]&}#]#^!Eq#^#a&}#a#b!Eq#b#g&}#g#h!Eq#h#i&}#i#j!Eq#j#k!Eq#k#m&}#m#n!Eq#n#o&}#o#p'}#p;'S&};'S;=`(l<%lO&}8r!GyZ(U!b!U7`OY!GrZw!Grwx!@cx!P!Gr!P!Q!Hl!Q!}!Gr!}#O!JU#O#P!Bq#P;'S!Gr;'S;=`!J|<%lO!Gr8r!Hse(U!b!U7`OY'}Zw'}x#O'}#P#W'}#W#X!Hl#X#Z'}#Z#[!Hl#[#]'}#]#^!Hl#^#a'}#a#b!Hl#b#g'}#g#h!Hl#h#i'}#i#j!Hl#j#k!Hl#k#m'}#m#n!Hl#n;'S'};'S;=`(f<%lO'}8r!JZX(U!bOY!JUZw!JUwx!Arx#O!JU#O#P!B[#P#Q!Gr#Q;'S!JU;'S;=`!Jv<%lO!JU8r!JyP;=`<%l!JU8r!KPP;=`<%l!Gr>^!KZ^$h&j(U!bOY!KSYZ&cZw!KSwx!CWx!^!KS!^!_!JU!_#O!KS#O#P!DR#P#Q!^!LYP;=`<%l!KS>^!L`P;=`<%l!_#c#d#Bq#d#l%Z#l#m#Es#m#o%Z#o#p*g#p;'S%Z;'S;=`+a<%lO%Z'Ad#_#c#o%Z#o#p*g#p;'S%Z;'S;=`+a<%lO%Z'Ad#>j_$h&j(Rp(U!bp'9tOY%ZYZ&cZr%Zrs&}sw%Zwx(rx!^%Z!^!_*g!_#O%Z#O#P&c#P#o%Z#o#p*g#p;'S%Z;'S;=`+a<%lO%Z'Ad#?rd$h&j(Rp(U!bOY%ZYZ&cZr%Zrs&}sw%Zwx(rx!Q%Z!Q!R#AQ!R!S#AQ!S!^%Z!^!_*g!_#O%Z#O#P&c#P#R%Z#R#S#AQ#S#o%Z#o#p*g#p;'S%Z;'S;=`+a<%lO%Z'Ad#A]f$h&j(Rp(U!bp'9tOY%ZYZ&cZr%Zrs&}sw%Zwx(rx!Q%Z!Q!R#AQ!R!S#AQ!S!^%Z!^!_*g!_#O%Z#O#P&c#P#R%Z#R#S#AQ#S#b%Z#b#c#>_#c#o%Z#o#p*g#p;'S%Z;'S;=`+a<%lO%Z'Ad#Bzc$h&j(Rp(U!bOY%ZYZ&cZr%Zrs&}sw%Zwx(rx!Q%Z!Q!Y#DV!Y!^%Z!^!_*g!_#O%Z#O#P&c#P#R%Z#R#S#DV#S#o%Z#o#p*g#p;'S%Z;'S;=`+a<%lO%Z'Ad#Dbe$h&j(Rp(U!bp'9tOY%ZYZ&cZr%Zrs&}sw%Zwx(rx!Q%Z!Q!Y#DV!Y!^%Z!^!_*g!_#O%Z#O#P&c#P#R%Z#R#S#DV#S#b%Z#b#c#>_#c#o%Z#o#p*g#p;'S%Z;'S;=`+a<%lO%Z'Ad#E|g$h&j(Rp(U!bOY%ZYZ&cZr%Zrs&}sw%Zwx(rx!Q%Z!Q![#Ge![!^%Z!^!_*g!_!c%Z!c!i#Ge!i#O%Z#O#P&c#P#R%Z#R#S#Ge#S#T%Z#T#Z#Ge#Z#o%Z#o#p*g#p;'S%Z;'S;=`+a<%lO%Z'Ad#Gpi$h&j(Rp(U!bp'9tOY%ZYZ&cZr%Zrs&}sw%Zwx(rx!Q%Z!Q![#Ge![!^%Z!^!_*g!_!c%Z!c!i#Ge!i#O%Z#O#P&c#P#R%Z#R#S#Ge#S#T%Z#T#Z#Ge#Z#b%Z#b#c#>_#c#o%Z#o#p*g#p;'S%Z;'S;=`+a<%lO%Z*)x#Il_!d$b$h&j#})Lv(Rp(U!bOY%ZYZ&cZr%Zrs&}sw%Zwx(rx!^%Z!^!_*g!_#O%Z#O#P&c#P#o%Z#o#p*g#p;'S%Z;'S;=`+a<%lO%Z)[#Jv_al$h&j(Rp(U!bOY%ZYZ&cZr%Zrs&}sw%Zwx(rx!^%Z!^!_*g!_#O%Z#O#P&c#P#o%Z#o#p*g#p;'S%Z;'S;=`+a<%lO%Z04f#LS^h#)`#O- spec_identifier[value] || -1},{term: 338, get: (value) => spec_word[value] || -1},{term: 92, get: (value) => spec_LessThan[value] || -1}], + tokenPrec: 14749 + }); + + /** + A collection of JavaScript-related + [snippets](https://codemirror.net/6/docs/ref/#autocomplete.snippet). + */ + const snippets = [ + /*@__PURE__*/snippetCompletion("function ${name}(${params}) {\n\t${}\n}", { + label: "function", + detail: "definition", + type: "keyword" + }), + /*@__PURE__*/snippetCompletion("for (let ${index} = 0; ${index} < ${bound}; ${index}++) {\n\t${}\n}", { + label: "for", + detail: "loop", + type: "keyword" + }), + /*@__PURE__*/snippetCompletion("for (let ${name} of ${collection}) {\n\t${}\n}", { + label: "for", + detail: "of loop", + type: "keyword" + }), + /*@__PURE__*/snippetCompletion("do {\n\t${}\n} while (${})", { + label: "do", + detail: "loop", + type: "keyword" + }), + /*@__PURE__*/snippetCompletion("while (${}) {\n\t${}\n}", { + label: "while", + detail: "loop", + type: "keyword" + }), + /*@__PURE__*/snippetCompletion("try {\n\t${}\n} catch (${error}) {\n\t${}\n}", { + label: "try", + detail: "/ catch block", + type: "keyword" + }), + /*@__PURE__*/snippetCompletion("if (${}) {\n\t${}\n}", { + label: "if", + detail: "block", + type: "keyword" + }), + /*@__PURE__*/snippetCompletion("if (${}) {\n\t${}\n} else {\n\t${}\n}", { + label: "if", + detail: "/ else block", + type: "keyword" + }), + /*@__PURE__*/snippetCompletion("class ${name} {\n\tconstructor(${params}) {\n\t\t${}\n\t}\n}", { + label: "class", + detail: "definition", + type: "keyword" + }), + /*@__PURE__*/snippetCompletion("import {${names}} from \"${module}\"\n${}", { + label: "import", + detail: "named", + type: "keyword" + }), + /*@__PURE__*/snippetCompletion("import ${name} from \"${module}\"\n${}", { + label: "import", + detail: "default", + type: "keyword" + }) + ]; + /** + A collection of snippet completions for TypeScript. Includes the + JavaScript [snippets](https://codemirror.net/6/docs/ref/#lang-javascript.snippets). + */ + const typescriptSnippets = /*@__PURE__*/snippets.concat([ + /*@__PURE__*/snippetCompletion("interface ${name} {\n\t${}\n}", { + label: "interface", + detail: "definition", + type: "keyword" + }), + /*@__PURE__*/snippetCompletion("type ${name} = ${type}", { + label: "type", + detail: "definition", + type: "keyword" + }), + /*@__PURE__*/snippetCompletion("enum ${name} {\n\t${}\n}", { + label: "enum", + detail: "definition", + type: "keyword" + }) + ]); + + const cache = /*@__PURE__*/new NodeWeakMap(); + const ScopeNodes = /*@__PURE__*/new Set([ + "Script", "Block", + "FunctionExpression", "FunctionDeclaration", "ArrowFunction", "MethodDeclaration", + "ForStatement" + ]); + function defID(type) { + return (node, def) => { + let id = node.node.getChild("VariableDefinition"); + if (id) + def(id, type); + return true; + }; + } + const functionContext = ["FunctionDeclaration"]; + const gatherCompletions = { + FunctionDeclaration: /*@__PURE__*/defID("function"), + ClassDeclaration: /*@__PURE__*/defID("class"), + ClassExpression: () => true, + EnumDeclaration: /*@__PURE__*/defID("constant"), + TypeAliasDeclaration: /*@__PURE__*/defID("type"), + NamespaceDeclaration: /*@__PURE__*/defID("namespace"), + VariableDefinition(node, def) { if (!node.matchContext(functionContext)) + def(node, "variable"); }, + TypeDefinition(node, def) { def(node, "type"); }, + __proto__: null + }; + function getScope(doc, node) { + let cached = cache.get(node); + if (cached) return cached; let completions = [], top = true; function def(node, type) { @@ -26896,11 +28473,13 @@ completions.push({ label: name, type }); } node.cursor(IterMode.IncludeAnonymous).iterate(node => { - if (node.name) { + if (top) { + top = false; + } + else if (node.name) { let gather = gatherCompletions[node.name]; - if (gather && gather(node, def, top) || !top && ScopeNodes.has(node.name)) + if (gather && gather(node, def) || ScopeNodes.has(node.name)) return false; - top = false; } else if (node.to - node.from > 8192) { // Allow caching for bigger internal nodes @@ -26912,11 +28491,18 @@ cache.set(node, completions); return completions; } - const Identifier = /^[\w\xa1-\uffff][\w\d\xa1-\uffff]*$/; - const dontComplete = ["String", "FormatString", "Comment", "PropertyName"]; + const Identifier = /^[\w$\xa1-\uffff][\w$\d\xa1-\uffff]*$/; + const dontComplete = [ + "TemplateString", "String", "RegExp", + "LineComment", "BlockComment", + "VariableDefinition", "TypeDefinition", "Label", + "PropertyDefinition", "PropertyName", + "PrivatePropertyDefinition", "PrivatePropertyName", + ".", "?." + ]; /** Completion source that looks up locally defined names in - Python code. + JavaScript code. */ function localCompletionSource(context) { let inner = syntaxTree(context.state).resolveInner(context.pos, -1); @@ -26937,243 +28523,1179 @@ validFor: Identifier }; } - const globals = /*@__PURE__*/[ - "__annotations__", "__builtins__", "__debug__", "__doc__", "__import__", "__name__", - "__loader__", "__package__", "__spec__", - "False", "None", "True" - ].map(n => ({ label: n, type: "constant" })).concat(/*@__PURE__*/[ - "ArithmeticError", "AssertionError", "AttributeError", "BaseException", "BlockingIOError", - "BrokenPipeError", "BufferError", "BytesWarning", "ChildProcessError", "ConnectionAbortedError", - "ConnectionError", "ConnectionRefusedError", "ConnectionResetError", "DeprecationWarning", - "EOFError", "Ellipsis", "EncodingWarning", "EnvironmentError", "Exception", "FileExistsError", - "FileNotFoundError", "FloatingPointError", "FutureWarning", "GeneratorExit", "IOError", - "ImportError", "ImportWarning", "IndentationError", "IndexError", "InterruptedError", - "IsADirectoryError", "KeyError", "KeyboardInterrupt", "LookupError", "MemoryError", - "ModuleNotFoundError", "NameError", "NotADirectoryError", "NotImplemented", "NotImplementedError", - "OSError", "OverflowError", "PendingDeprecationWarning", "PermissionError", "ProcessLookupError", - "RecursionError", "ReferenceError", "ResourceWarning", "RuntimeError", "RuntimeWarning", - "StopAsyncIteration", "StopIteration", "SyntaxError", "SyntaxWarning", "SystemError", - "SystemExit", "TabError", "TimeoutError", "TypeError", "UnboundLocalError", "UnicodeDecodeError", - "UnicodeEncodeError", "UnicodeError", "UnicodeTranslateError", "UnicodeWarning", "UserWarning", - "ValueError", "Warning", "ZeroDivisionError" - ].map(n => ({ label: n, type: "type" }))).concat(/*@__PURE__*/[ - "bool", "bytearray", "bytes", "classmethod", "complex", "float", "frozenset", "int", "list", - "map", "memoryview", "object", "range", "set", "staticmethod", "str", "super", "tuple", "type" - ].map(n => ({ label: n, type: "class" }))).concat(/*@__PURE__*/[ - "abs", "aiter", "all", "anext", "any", "ascii", "bin", "breakpoint", "callable", "chr", - "compile", "delattr", "dict", "dir", "divmod", "enumerate", "eval", "exec", "exit", "filter", - "format", "getattr", "globals", "hasattr", "hash", "help", "hex", "id", "input", "isinstance", - "issubclass", "iter", "len", "license", "locals", "max", "min", "next", "oct", "open", - "ord", "pow", "print", "property", "quit", "repr", "reversed", "round", "setattr", "slice", - "sorted", "sum", "vars", "zip" - ].map(n => ({ label: n, type: "function" }))); - const snippets = [ - /*@__PURE__*/snippetCompletion("def ${name}(${params}):\n\t${}", { - label: "def", - detail: "function", - type: "keyword" - }), - /*@__PURE__*/snippetCompletion("for ${name} in ${collection}:\n\t${}", { - label: "for", - detail: "loop", - type: "keyword" - }), - /*@__PURE__*/snippetCompletion("while ${}:\n\t${}", { - label: "while", - detail: "loop", - type: "keyword" - }), - /*@__PURE__*/snippetCompletion("try:\n\t${}\nexcept ${error}:\n\t${}", { - label: "try", - detail: "/ except block", - type: "keyword" - }), - /*@__PURE__*/snippetCompletion("if ${}:\n\t\n", { - label: "if", - detail: "block", - type: "keyword" - }), - /*@__PURE__*/snippetCompletion("if ${}:\n\t${}\nelse:\n\t${}", { - label: "if", - detail: "/ else block", - type: "keyword" - }), - /*@__PURE__*/snippetCompletion("class ${name}:\n\tdef __init__(self, ${params}):\n\t\t\t${}", { - label: "class", - detail: "definition", - type: "keyword" - }), - /*@__PURE__*/snippetCompletion("import ${module}", { - label: "import", - detail: "statement", - type: "keyword" + + /** + A language provider based on the [Lezer JavaScript + parser](https://github.com/lezer-parser/javascript), extended with + highlighting and indentation information. + */ + const javascriptLanguage = /*@__PURE__*/LRLanguage.define({ + name: "javascript", + parser: /*@__PURE__*/parser$1.configure({ + props: [ + /*@__PURE__*/indentNodeProp.add({ + IfStatement: /*@__PURE__*/continuedIndent({ except: /^\s*({|else\b)/ }), + TryStatement: /*@__PURE__*/continuedIndent({ except: /^\s*({|catch\b|finally\b)/ }), + LabeledStatement: flatIndent, + SwitchBody: context => { + let after = context.textAfter, closed = /^\s*\}/.test(after), isCase = /^\s*(case|default)\b/.test(after); + return context.baseIndent + (closed ? 0 : isCase ? 1 : 2) * context.unit; + }, + Block: /*@__PURE__*/delimitedIndent({ closing: "}" }), + ArrowFunction: cx => cx.baseIndent + cx.unit, + "TemplateString BlockComment": () => null, + "Statement Property": /*@__PURE__*/continuedIndent({ except: /^{/ }), + JSXElement(context) { + let closed = /^\s*<\//.test(context.textAfter); + return context.lineIndent(context.node.from) + (closed ? 0 : context.unit); + }, + JSXEscape(context) { + let closed = /\s*\}/.test(context.textAfter); + return context.lineIndent(context.node.from) + (closed ? 0 : context.unit); + }, + "JSXOpenTag JSXSelfClosingTag"(context) { + return context.column(context.node.from) + context.unit; + } + }), + /*@__PURE__*/foldNodeProp.add({ + "Block ClassBody SwitchBody EnumBody ObjectExpression ArrayExpression ObjectType": foldInside, + BlockComment(tree) { return { from: tree.from + 2, to: tree.to - 2 }; } + }) + ] }), - /*@__PURE__*/snippetCompletion("from ${module} import ${names}", { - label: "from", - detail: "import", - type: "keyword" - }) - ]; + languageData: { + closeBrackets: { brackets: ["(", "[", "{", "'", '"', "`"] }, + commentTokens: { line: "//", block: { open: "/*", close: "*/" } }, + indentOnInput: /^\s*(?:case |default:|\{|\}|<\/)$/, + wordChars: "$" + } + }); + const jsxSublanguage = { + test: node => /^JSX/.test(node.name), + facet: /*@__PURE__*/defineLanguageFacet({ commentTokens: { block: { open: "{/*", close: "*/}" } } }) + }; /** - Autocompletion for built-in Python globals and keywords. + A language provider for TypeScript. */ - const globalCompletion = /*@__PURE__*/ifNotIn(dontComplete, /*@__PURE__*/completeFromList(/*@__PURE__*/globals.concat(snippets))); - - function innerBody(context) { - let { node, pos } = context; - let lineIndent = context.lineIndent(pos, -1); - let found = null; + const typescriptLanguage = /*@__PURE__*/javascriptLanguage.configure({ dialect: "ts" }, "typescript"); + /** + Language provider for JSX. + */ + const jsxLanguage = /*@__PURE__*/javascriptLanguage.configure({ + dialect: "jsx", + props: [/*@__PURE__*/sublanguageProp.add(n => n.isTop ? [jsxSublanguage] : undefined)] + }); + /** + Language provider for JSX + TypeScript. + */ + const tsxLanguage = /*@__PURE__*/javascriptLanguage.configure({ + dialect: "jsx ts", + props: [/*@__PURE__*/sublanguageProp.add(n => n.isTop ? [jsxSublanguage] : undefined)] + }, "typescript"); + let kwCompletion = (name) => ({ label: name, type: "keyword" }); + const keywords = /*@__PURE__*/"break case const continue default delete export extends false finally in instanceof let new return static super switch this throw true typeof var yield".split(" ").map(kwCompletion); + const typescriptKeywords = /*@__PURE__*/keywords.concat(/*@__PURE__*/["declare", "implements", "private", "protected", "public"].map(kwCompletion)); + /** + JavaScript support. Includes [snippet](https://codemirror.net/6/docs/ref/#lang-javascript.snippets) + and local variable completion. + */ + function javascript(config = {}) { + let lang = config.jsx ? (config.typescript ? tsxLanguage : jsxLanguage) + : config.typescript ? typescriptLanguage : javascriptLanguage; + let completions = config.typescript ? typescriptSnippets.concat(typescriptKeywords) : snippets.concat(keywords); + return new LanguageSupport(lang, [ + javascriptLanguage.data.of({ + autocomplete: ifNotIn(dontComplete, completeFromList(completions)) + }), + javascriptLanguage.data.of({ + autocomplete: localCompletionSource + }), + config.jsx ? autoCloseTags$1 : [], + ]); + } + function findOpenTag(node) { for (;;) { - let before = node.childBefore(pos); - if (!before) { - break; + if (node.name == "JSXOpenTag" || node.name == "JSXSelfClosingTag" || node.name == "JSXFragmentTag") + return node; + if (node.name == "JSXEscape" || !node.parent) + return null; + node = node.parent; + } + } + function elementName$1(doc, tree, max = doc.length) { + for (let ch = tree === null || tree === void 0 ? void 0 : tree.firstChild; ch; ch = ch.nextSibling) { + if (ch.name == "JSXIdentifier" || ch.name == "JSXBuiltin" || ch.name == "JSXNamespacedName" || + ch.name == "JSXMemberExpression") + return doc.sliceString(ch.from, Math.min(ch.to, max)); + } + return ""; + } + const android = typeof navigator == "object" && /*@__PURE__*//Android\b/.test(navigator.userAgent); + /** + Extension that will automatically insert JSX close tags when a `>` or + `/` is typed. + */ + const autoCloseTags$1 = /*@__PURE__*/EditorView.inputHandler.of((view, from, to, text, defaultInsert) => { + if ((android ? view.composing : view.compositionStarted) || view.state.readOnly || + from != to || (text != ">" && text != "/") || + !javascriptLanguage.isActiveAt(view.state, from, -1)) + return false; + let base = defaultInsert(), { state } = base; + let closeTags = state.changeByRange(range => { + var _a; + let { head } = range, around = syntaxTree(state).resolveInner(head - 1, -1), name; + if (around.name == "JSXStartTag") + around = around.parent; + if (state.doc.sliceString(head - 1, head) != text || around.name == "JSXAttributeValue" && around.to > head) ; + else if (text == ">" && around.name == "JSXFragmentTag") { + return { range, changes: { from: head, insert: `` } }; + } + else if (text == "/" && around.name == "JSXStartCloseTag") { + let empty = around.parent, base = empty.parent; + if (base && empty.from == head - 2 && + ((name = elementName$1(state.doc, base.firstChild, head)) || ((_a = base.firstChild) === null || _a === void 0 ? void 0 : _a.name) == "JSXFragmentTag")) { + let insert = `${name}>`; + return { range: EditorSelection.cursor(head + insert.length, -1), changes: { from: head, insert } }; + } + } + else if (text == ">") { + let openTag = findOpenTag(around); + if (openTag && openTag.name == "JSXOpenTag" && + !/^\/?>|^<\//.test(state.doc.sliceString(head, head + 2)) && + (name = elementName$1(state.doc, openTag, head))) + return { range, changes: { from: head, insert: `` } }; + } + return { range }; + }); + if (closeTags.changes.empty) + return false; + view.dispatch([ + base, + state.update(closeTags, { userEvent: "input.complete", scrollIntoView: true }) + ]); + return true; + }); + + const Targets = ["_blank", "_self", "_top", "_parent"]; + const Charsets = ["ascii", "utf-8", "utf-16", "latin1", "latin1"]; + const Methods = ["get", "post", "put", "delete"]; + const Encs = ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"]; + const Bool = ["true", "false"]; + const S = {}; // Empty tag spec + const Tags = { + a: { + attrs: { + href: null, ping: null, type: null, + media: null, + target: Targets, + hreflang: null } - else if (before.name == "Comment") { - pos = before.from; + }, + abbr: S, + address: S, + area: { + attrs: { + alt: null, coords: null, href: null, target: null, ping: null, + media: null, hreflang: null, type: null, + shape: ["default", "rect", "circle", "poly"] } - else if (before.name == "Body") { - if (context.baseIndentFor(before) + context.unit <= lineIndent) - found = before; - node = before; + }, + article: S, + aside: S, + audio: { + attrs: { + src: null, mediagroup: null, + crossorigin: ["anonymous", "use-credentials"], + preload: ["none", "metadata", "auto"], + autoplay: ["autoplay"], + loop: ["loop"], + controls: ["controls"] } - else if (before.type.is("Statement")) { - node = before; + }, + b: S, + base: { attrs: { href: null, target: Targets } }, + bdi: S, + bdo: S, + blockquote: { attrs: { cite: null } }, + body: S, + br: S, + button: { + attrs: { + form: null, formaction: null, name: null, value: null, + autofocus: ["autofocus"], + disabled: ["autofocus"], + formenctype: Encs, + formmethod: Methods, + formnovalidate: ["novalidate"], + formtarget: Targets, + type: ["submit", "reset", "button"] } - else { + }, + canvas: { attrs: { width: null, height: null } }, + caption: S, + center: S, + cite: S, + code: S, + col: { attrs: { span: null } }, + colgroup: { attrs: { span: null } }, + command: { + attrs: { + type: ["command", "checkbox", "radio"], + label: null, icon: null, radiogroup: null, command: null, title: null, + disabled: ["disabled"], + checked: ["checked"] + } + }, + data: { attrs: { value: null } }, + datagrid: { attrs: { disabled: ["disabled"], multiple: ["multiple"] } }, + datalist: { attrs: { data: null } }, + dd: S, + del: { attrs: { cite: null, datetime: null } }, + details: { attrs: { open: ["open"] } }, + dfn: S, + div: S, + dl: S, + dt: S, + em: S, + embed: { attrs: { src: null, type: null, width: null, height: null } }, + eventsource: { attrs: { src: null } }, + fieldset: { attrs: { disabled: ["disabled"], form: null, name: null } }, + figcaption: S, + figure: S, + footer: S, + form: { + attrs: { + action: null, name: null, + "accept-charset": Charsets, + autocomplete: ["on", "off"], + enctype: Encs, + method: Methods, + novalidate: ["novalidate"], + target: Targets + } + }, + h1: S, h2: S, h3: S, h4: S, h5: S, h6: S, + head: { + children: ["title", "base", "link", "style", "meta", "script", "noscript", "command"] + }, + header: S, + hgroup: S, + hr: S, + html: { + attrs: { manifest: null } + }, + i: S, + iframe: { + attrs: { + src: null, srcdoc: null, name: null, width: null, height: null, + sandbox: ["allow-top-navigation", "allow-same-origin", "allow-forms", "allow-scripts"], + seamless: ["seamless"] + } + }, + img: { + attrs: { + alt: null, src: null, ismap: null, usemap: null, width: null, height: null, + crossorigin: ["anonymous", "use-credentials"] + } + }, + input: { + attrs: { + alt: null, dirname: null, form: null, formaction: null, + height: null, list: null, max: null, maxlength: null, min: null, + name: null, pattern: null, placeholder: null, size: null, src: null, + step: null, value: null, width: null, + accept: ["audio/*", "video/*", "image/*"], + autocomplete: ["on", "off"], + autofocus: ["autofocus"], + checked: ["checked"], + disabled: ["disabled"], + formenctype: Encs, + formmethod: Methods, + formnovalidate: ["novalidate"], + formtarget: Targets, + multiple: ["multiple"], + readonly: ["readonly"], + required: ["required"], + type: ["hidden", "text", "search", "tel", "url", "email", "password", "datetime", "date", "month", + "week", "time", "datetime-local", "number", "range", "color", "checkbox", "radio", + "file", "submit", "image", "reset", "button"] + } + }, + ins: { attrs: { cite: null, datetime: null } }, + kbd: S, + keygen: { + attrs: { + challenge: null, form: null, name: null, + autofocus: ["autofocus"], + disabled: ["disabled"], + keytype: ["RSA"] + } + }, + label: { attrs: { for: null, form: null } }, + legend: S, + li: { attrs: { value: null } }, + link: { + attrs: { + href: null, type: null, + hreflang: null, + media: null, + sizes: ["all", "16x16", "16x16 32x32", "16x16 32x32 64x64"] + } + }, + map: { attrs: { name: null } }, + mark: S, + menu: { attrs: { label: null, type: ["list", "context", "toolbar"] } }, + meta: { + attrs: { + content: null, + charset: Charsets, + name: ["viewport", "application-name", "author", "description", "generator", "keywords"], + "http-equiv": ["content-language", "content-type", "default-style", "refresh"] + } + }, + meter: { attrs: { value: null, min: null, low: null, high: null, max: null, optimum: null } }, + nav: S, + noscript: S, + object: { + attrs: { + data: null, type: null, name: null, usemap: null, form: null, width: null, height: null, + typemustmatch: ["typemustmatch"] + } + }, + ol: { attrs: { reversed: ["reversed"], start: null, type: ["1", "a", "A", "i", "I"] }, + children: ["li", "script", "template", "ul", "ol"] }, + optgroup: { attrs: { disabled: ["disabled"], label: null } }, + option: { attrs: { disabled: ["disabled"], label: null, selected: ["selected"], value: null } }, + output: { attrs: { for: null, form: null, name: null } }, + p: S, + param: { attrs: { name: null, value: null } }, + pre: S, + progress: { attrs: { value: null, max: null } }, + q: { attrs: { cite: null } }, + rp: S, + rt: S, + ruby: S, + samp: S, + script: { + attrs: { + type: ["text/javascript"], + src: null, + async: ["async"], + defer: ["defer"], + charset: Charsets + } + }, + section: S, + select: { + attrs: { + form: null, name: null, size: null, + autofocus: ["autofocus"], + disabled: ["disabled"], + multiple: ["multiple"] + } + }, + slot: { attrs: { name: null } }, + small: S, + source: { attrs: { src: null, type: null, media: null } }, + span: S, + strong: S, + style: { + attrs: { + type: ["text/css"], + media: null, + scoped: null + } + }, + sub: S, + summary: S, + sup: S, + table: S, + tbody: S, + td: { attrs: { colspan: null, rowspan: null, headers: null } }, + template: S, + textarea: { + attrs: { + dirname: null, form: null, maxlength: null, name: null, placeholder: null, + rows: null, cols: null, + autofocus: ["autofocus"], + disabled: ["disabled"], + readonly: ["readonly"], + required: ["required"], + wrap: ["soft", "hard"] + } + }, + tfoot: S, + th: { attrs: { colspan: null, rowspan: null, headers: null, scope: ["row", "col", "rowgroup", "colgroup"] } }, + thead: S, + time: { attrs: { datetime: null } }, + title: S, + tr: S, + track: { + attrs: { + src: null, label: null, default: null, + kind: ["subtitles", "captions", "descriptions", "chapters", "metadata"], + srclang: null + } + }, + ul: { children: ["li", "script", "template", "ul", "ol"] }, + var: S, + video: { + attrs: { + src: null, poster: null, width: null, height: null, + crossorigin: ["anonymous", "use-credentials"], + preload: ["auto", "metadata", "none"], + autoplay: ["autoplay"], + mediagroup: ["movie"], + muted: ["muted"], + controls: ["controls"] + } + }, + wbr: S + }; + const GlobalAttrs = { + accesskey: null, + class: null, + contenteditable: Bool, + contextmenu: null, + dir: ["ltr", "rtl", "auto"], + draggable: ["true", "false", "auto"], + dropzone: ["copy", "move", "link", "string:", "file:"], + hidden: ["hidden"], + id: null, + inert: ["inert"], + itemid: null, + itemprop: null, + itemref: null, + itemscope: ["itemscope"], + itemtype: null, + lang: ["ar", "bn", "de", "en-GB", "en-US", "es", "fr", "hi", "id", "ja", "pa", "pt", "ru", "tr", "zh"], + spellcheck: Bool, + autocorrect: Bool, + autocapitalize: Bool, + style: null, + tabindex: null, + title: null, + translate: ["yes", "no"], + rel: ["stylesheet", "alternate", "author", "bookmark", "help", "license", "next", "nofollow", "noreferrer", "prefetch", "prev", "search", "tag"], + role: /*@__PURE__*/"alert application article banner button cell checkbox complementary contentinfo dialog document feed figure form grid gridcell heading img list listbox listitem main navigation region row rowgroup search switch tab table tabpanel textbox timer".split(" "), + "aria-activedescendant": null, + "aria-atomic": Bool, + "aria-autocomplete": ["inline", "list", "both", "none"], + "aria-busy": Bool, + "aria-checked": ["true", "false", "mixed", "undefined"], + "aria-controls": null, + "aria-describedby": null, + "aria-disabled": Bool, + "aria-dropeffect": null, + "aria-expanded": ["true", "false", "undefined"], + "aria-flowto": null, + "aria-grabbed": ["true", "false", "undefined"], + "aria-haspopup": Bool, + "aria-hidden": Bool, + "aria-invalid": ["true", "false", "grammar", "spelling"], + "aria-label": null, + "aria-labelledby": null, + "aria-level": null, + "aria-live": ["off", "polite", "assertive"], + "aria-multiline": Bool, + "aria-multiselectable": Bool, + "aria-owns": null, + "aria-posinset": null, + "aria-pressed": ["true", "false", "mixed", "undefined"], + "aria-readonly": Bool, + "aria-relevant": null, + "aria-required": Bool, + "aria-selected": ["true", "false", "undefined"], + "aria-setsize": null, + "aria-sort": ["ascending", "descending", "none", "other"], + "aria-valuemax": null, + "aria-valuemin": null, + "aria-valuenow": null, + "aria-valuetext": null + }; + const eventAttributes = /*@__PURE__*/("beforeunload copy cut dragstart dragover dragleave dragenter dragend " + + "drag paste focus blur change click load mousedown mouseenter mouseleave " + + "mouseup keydown keyup resize scroll unload").split(" ").map(n => "on" + n); + for (let a of eventAttributes) + GlobalAttrs[a] = null; + class Schema { + constructor(extraTags, extraAttrs) { + this.tags = Object.assign(Object.assign({}, Tags), extraTags); + this.globalAttrs = Object.assign(Object.assign({}, GlobalAttrs), extraAttrs); + this.allTags = Object.keys(this.tags); + this.globalAttrNames = Object.keys(this.globalAttrs); + } + } + Schema.default = /*@__PURE__*/new Schema; + function elementName(doc, tree, max = doc.length) { + if (!tree) + return ""; + let tag = tree.firstChild; + let name = tag && tag.getChild("TagName"); + return name ? doc.sliceString(name.from, Math.min(name.to, max)) : ""; + } + function findParentElement(tree, skip = false) { + for (; tree; tree = tree.parent) + if (tree.name == "Element") { + if (skip) + skip = false; + else + return tree; + } + return null; + } + function allowedChildren(doc, tree, schema) { + let parentInfo = schema.tags[elementName(doc, findParentElement(tree))]; + return (parentInfo === null || parentInfo === void 0 ? void 0 : parentInfo.children) || schema.allTags; + } + function openTags(doc, tree) { + let open = []; + for (let parent = findParentElement(tree); parent && !parent.type.isTop; parent = findParentElement(parent.parent)) { + let tagName = elementName(doc, parent); + if (tagName && parent.lastChild.name == "CloseTag") break; + if (tagName && open.indexOf(tagName) < 0 && (tree.name == "EndTag" || tree.from >= parent.firstChild.to)) + open.push(tagName); + } + return open; + } + const identifier = /^[:\-\.\w\u00b7-\uffff]*$/; + function completeTag(state, schema, tree, from, to) { + let end = /\s*>/.test(state.sliceDoc(to, to + 5)) ? "" : ">"; + let parent = findParentElement(tree, true); + return { from, to, + options: allowedChildren(state.doc, parent, schema).map(tagName => ({ label: tagName, type: "type" })).concat(openTags(state.doc, tree).map((tag, i) => ({ label: "/" + tag, apply: "/" + tag + end, + type: "type", boost: 99 - i }))), + validFor: /^\/?[:\-\.\w\u00b7-\uffff]*$/ }; + } + function completeCloseTag(state, tree, from, to) { + let end = /\s*>/.test(state.sliceDoc(to, to + 5)) ? "" : ">"; + return { from, to, + options: openTags(state.doc, tree).map((tag, i) => ({ label: tag, apply: tag + end, type: "type", boost: 99 - i })), + validFor: identifier }; + } + function completeStartTag(state, schema, tree, pos) { + let options = [], level = 0; + for (let tagName of allowedChildren(state.doc, tree, schema)) + options.push({ label: "<" + tagName, type: "type" }); + for (let open of openTags(state.doc, tree)) + options.push({ label: "", type: "type", boost: 99 - level++ }); + return { from: pos, to: pos, options, validFor: /^<\/?[:\-\.\w\u00b7-\uffff]*$/ }; + } + function completeAttrName(state, schema, tree, from, to) { + let elt = findParentElement(tree), info = elt ? schema.tags[elementName(state.doc, elt)] : null; + let localAttrs = info && info.attrs ? Object.keys(info.attrs) : []; + let names = info && info.globalAttrs === false ? localAttrs + : localAttrs.length ? localAttrs.concat(schema.globalAttrNames) : schema.globalAttrNames; + return { from, to, + options: names.map(attrName => ({ label: attrName, type: "property" })), + validFor: identifier }; + } + function completeAttrValue(state, schema, tree, from, to) { + var _a; + let nameNode = (_a = tree.parent) === null || _a === void 0 ? void 0 : _a.getChild("AttributeName"); + let options = [], token = undefined; + if (nameNode) { + let attrName = state.sliceDoc(nameNode.from, nameNode.to); + let attrs = schema.globalAttrs[attrName]; + if (!attrs) { + let elt = findParentElement(tree), info = elt ? schema.tags[elementName(state.doc, elt)] : null; + attrs = (info === null || info === void 0 ? void 0 : info.attrs) && info.attrs[attrName]; + } + if (attrs) { + let base = state.sliceDoc(from, to).toLowerCase(), quoteStart = '"', quoteEnd = '"'; + if (/^['"]/.test(base)) { + token = base[0] == '"' ? /^[^"]*$/ : /^[^']*$/; + quoteStart = ""; + quoteEnd = state.sliceDoc(to, to + 1) == base[0] ? "" : base[0]; + base = base.slice(1); + from++; + } + else { + token = /^[^\s<>='"]*$/; + } + for (let value of attrs) + options.push({ label: value, apply: quoteStart + value + quoteEnd, type: "constant" }); } } - return found; + return { from, to, options, validFor: token }; } - function indentBody(context, node) { - let base = context.baseIndentFor(node); - let line = context.lineAt(context.pos, -1), to = line.from + line.text.length; - // Don't consider blank, deindented lines at the end of the - // block part of the block - if (/^\s*($|#)/.test(line.text) && - context.node.to < to + 100 && - !/\S/.test(context.state.sliceDoc(to, context.node.to)) && - context.lineIndent(context.pos, -1) <= base) - return null; - // A normally deindenting keyword that appears at a higher - // indentation than the block should probably be handled by the next - // level - if (/^\s*(else:|elif |except |finally:)/.test(context.textAfter) && context.lineIndent(context.pos, -1) > base) + function htmlCompletionFor(schema, context) { + let { state, pos } = context, tree = syntaxTree(state).resolveInner(pos, -1), around = tree.resolve(pos); + for (let scan = pos, before; around == tree && (before = tree.childBefore(scan));) { + let last = before.lastChild; + if (!last || !last.type.isError || last.from < last.to) + break; + around = tree = before; + scan = last.from; + } + if (tree.name == "TagName") { + return tree.parent && /CloseTag$/.test(tree.parent.name) ? completeCloseTag(state, tree, tree.from, pos) + : completeTag(state, schema, tree, tree.from, pos); + } + else if (tree.name == "StartTag") { + return completeTag(state, schema, tree, pos, pos); + } + else if (tree.name == "StartCloseTag" || tree.name == "IncompleteCloseTag") { + return completeCloseTag(state, tree, pos, pos); + } + else if (tree.name == "OpenTag" || tree.name == "SelfClosingTag" || tree.name == "AttributeName") { + return completeAttrName(state, schema, tree, tree.name == "AttributeName" ? tree.from : pos, pos); + } + else if (tree.name == "Is" || tree.name == "AttributeValue" || tree.name == "UnquotedAttributeValue") { + return completeAttrValue(state, schema, tree, tree.name == "Is" ? pos : tree.from, pos); + } + else if (context.explicit && (around.name == "Element" || around.name == "Text" || around.name == "Document")) { + return completeStartTag(state, schema, tree, pos); + } + else { return null; - return base + context.unit; + } } /** - A language provider based on the [Lezer Python - parser](https://github.com/lezer-parser/python), extended with - highlighting and indentation information. + Create a completion source for HTML extended with additional tags + or attributes. */ - const pythonLanguage = /*@__PURE__*/LRLanguage.define({ - name: "python", - parser: /*@__PURE__*/parser.configure({ + function htmlCompletionSourceWith(config) { + let { extraTags, extraGlobalAttributes: extraAttrs } = config; + let schema = extraAttrs || extraTags ? new Schema(extraTags, extraAttrs) : Schema.default; + return (context) => htmlCompletionFor(schema, context); + } + + const jsonParser = /*@__PURE__*/javascriptLanguage.parser.configure({ top: "SingleExpression" }); + const defaultNesting = [ + { tag: "script", + attrs: attrs => attrs.type == "text/typescript" || attrs.lang == "ts", + parser: typescriptLanguage.parser }, + { tag: "script", + attrs: attrs => attrs.type == "text/babel" || attrs.type == "text/jsx", + parser: jsxLanguage.parser }, + { tag: "script", + attrs: attrs => attrs.type == "text/typescript-jsx", + parser: tsxLanguage.parser }, + { tag: "script", + attrs(attrs) { + return /^(importmap|speculationrules|application\/(.+\+)?json)$/i.test(attrs.type); + }, + parser: jsonParser }, + { tag: "script", + attrs(attrs) { + return !attrs.type || /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^module$|^$/i.test(attrs.type); + }, + parser: javascriptLanguage.parser }, + { tag: "style", + attrs(attrs) { + return (!attrs.lang || attrs.lang == "css") && (!attrs.type || /^(text\/)?(x-)?(stylesheet|css)$/i.test(attrs.type)); + }, + parser: cssLanguage.parser } + ]; + const defaultAttrs = /*@__PURE__*/[ + { name: "style", + parser: /*@__PURE__*/cssLanguage.parser.configure({ top: "Styles" }) } + ].concat(/*@__PURE__*/eventAttributes.map(name => ({ name, parser: javascriptLanguage.parser }))); + /** + A language provider based on the [Lezer HTML + parser](https://github.com/lezer-parser/html), extended with the + JavaScript and CSS parsers to parse the content of ` + + + \ No newline at end of file diff --git a/default/js/codemirror/src/main.js b/default/js/codemirror/src/main.js new file mode 100644 index 0000000..ecc653a --- /dev/null +++ b/default/js/codemirror/src/main.js @@ -0,0 +1,87 @@ +import {EditorView} from "@codemirror/view"; +import {Compartment, EditorState} from "@codemirror/state"; +import {basicSetup} from "codemirror"; +import {html} from "@codemirror/lang-html"; +import {javascript} from "@codemirror/lang-javascript"; +import {StreamLanguage} from "@codemirror/language" +import {properties} from "@codemirror/legacy-modes/mode/properties" +import {myTheme} from "./theme.js"; +import {json} from "@codemirror/lang-json"; + +class CodeEditor { + constructor() { + this._code = document.querySelector('#editor-content').innerHTML; + this._container = document.querySelector('#code-editor'); + this._language = new Compartment; + this.init(); + } + + getLanguage() { + return this._container.dataset.language; + } + + init() { + this._state = EditorState.create({ + doc: this._code, + extensions: [ + basicSetup, + myTheme, + this._language.of(this.findLanguage()), + this.loadLanguage() + ], + }); + + this._view = new EditorView({ + state: this._state, + parent: this._container + }); + } + + update() { + this._view.dispatch({ + effects: this._language.reconfigure(this.findLanguage()) + }) + } + + findLanguage() { + let language = null; + + switch (this.getLanguage()) { + case "html": + language = html(); + break; + case "javascript": + language = javascript(); + break; + case "json": + language = json(); + break; + case "properties": + language = StreamLanguage.define(properties); + break; + default: + language = html(); + break; + } + + if (language === null) { + return null + } + + return language; + } + + loadLanguage() { + return EditorState.transactionExtender.of(tr => { + if (!tr.docChanged) { + return null + } + + return { + effects: this._language.reconfigure(this.findLanguage()) + } + }); + } +} + +window.addEventListener('DOMContentLoaded', () => new CodeEditor); \ No newline at end of file diff --git a/default/js/codemirror/src/theme.js b/default/js/codemirror/src/theme.js new file mode 100644 index 0000000..ceef385 --- /dev/null +++ b/default/js/codemirror/src/theme.js @@ -0,0 +1,178 @@ +import {EditorView} from "@codemirror/view" +import {HighlightStyle, syntaxHighlighting} from '@codemirror/language' +import {tags as t} from '@lezer/highlight' + +const Colors = { + Text: 'var(--bs-success-text-emphasis)', + Key: 'var(--bs-code-color)', + Braces: 'var(--bs-tertiary-color)', + BracesActive: 'var(--bs-red)', + SameSelection: 'rgb(from var(--bs-red) r g b / 50%)', +}; + +const base00 = '#2E3235', + base01 = '#DDDDDD', + base02 = '#B9D2FF', + base03 = '#b0b0b0', + base04 = '#d0d0d0', + base05 = '#e0e0e0', + base06 = '#808080', + base07 = '#000000', + base08 = '#A54543', + base09 = '#fc6d24', + base0A = '#fda331', + base0B = '#8abeb7', + base0D = '#6fb3d2', + base0F = '#6987AF'; +const invalid = base09, + darkBackground = '#292d30', + highlightBackground = base02 + '30', + background = base00, + tooltipBackground = base01, + selection = '#202325', + cursor = base01; + +const Theme = EditorView.theme({ + '&': { + color: base01, + backgroundColor: background + }, + + '.cm-content': { + caretColor: cursor + }, + + '.cm-cursor, .cm-dropCursor': {borderLeftColor: cursor}, + '&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': + {backgroundColor: selection}, + + '.cm-activeLine': {backgroundColor: highlightBackground}, + '.cm-selectionMatch': { + backgroundColor: Colors.SameSelection + }, + + '&.cm-focused .cm-matchingBracket, &.cm-focused .cm-matchingBracket *': { + color: Colors.BracesActive, + backgroundColor: 'transparent', + fontWeight: 'bolder' + }, + + '.cm-gutters': { + borderRight: `1px solid #ffffff10`, + color: base06, + backgroundColor: darkBackground + }, + + '.cm-activeLineGutter': { + backgroundColor: highlightBackground + }, + + '.cm-foldPlaceholder': { + backgroundColor: 'transparent', + border: 'none', + color: base02 + } +}, { + dark: true +}); + +const Syntax = HighlightStyle.define([ + {tag: t.keyword, color: base0A}, + { + tag: [t.name, t.deleted, t.character, t.propertyName, t.macroName], + color: Colors.Key + }, + {tag: [t.variableName], color: base0D}, + {tag: [t.function(t.variableName)], color: base0A}, + {tag: [t.labelName], color: base09}, + { + tag: [t.color, t.constant(t.name), t.standard(t.name)], + color: base0A + }, + {tag: [t.definition(t.name), t.separator], color: Colors.Text}, + {tag: [t.brace], color: Colors.Braces}, + { + tag: [t.annotation], + color: invalid + }, + { + tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], + color: base0A + }, + { + tag: [t.typeName, t.className], + color: base0D + }, + { + tag: [t.operator, t.operatorKeyword], + color: Colors.Text + }, + { + tag: [t.tagName], + color: base0A + }, + { + tag: [t.squareBracket], + color: Colors.Braces + }, + { + tag: [t.angleBracket], + color: Colors.Braces + }, + { + tag: [t.attributeName], + color: base0D + }, + { + tag: [t.regexp], + color: base0A + }, + { + tag: [t.quote], + color: base01 + }, + {tag: [t.string], color: Colors.Text}, + { + tag: t.link, + color: base0F, + textDecoration: 'underline', + textUnderlinePosition: 'under' + }, + { + tag: [t.url, t.escape, t.special(t.string)], + color: base0B + }, + {tag: [t.meta], color: base08}, + {tag: [t.comment], color: base06, fontStyle: 'italic'}, + {tag: t.monospace, color: base01}, + {tag: t.strong, fontWeight: 'bold', color: base0A}, + {tag: t.emphasis, fontStyle: 'italic', color: base0D}, + {tag: t.strikethrough, textDecoration: 'line-through'}, + {tag: t.heading, fontWeight: 'bold', color: base01}, + {tag: t.special(t.heading1), fontWeight: 'bold', color: base01}, + {tag: t.heading1, fontWeight: 'bold', color: base01}, + { + tag: [t.heading2, t.heading3, t.heading4], + fontWeight: 'bold', + color: base01 + }, + { + tag: [t.heading5, t.heading6], + color: base01 + }, + {tag: [t.atom, t.bool, t.special(t.variableName)], color: base0B}, + { + tag: [t.processingInstruction, t.inserted], + color: base0B + }, + { + tag: [t.contentSeparator], + color: base0D + }, + {tag: t.invalid, color: base02, borderBottom: `1px dotted ${invalid}`} +]); + +export const myTheme = [ + Theme, + syntaxHighlighting(Syntax) +] \ No newline at end of file