mirror of
https://github.com/dreamstarsky/runbin.git
synced 2026-05-15 22:33:09 +00:00
4023 lines
121 KiB
JavaScript
4023 lines
121 KiB
JavaScript
import {
|
||
Decoration,
|
||
Direction,
|
||
EditorView,
|
||
GutterMarker,
|
||
StyleModule,
|
||
ViewPlugin,
|
||
WidgetType,
|
||
gutter,
|
||
logException
|
||
} from "./chunk-HHQTB6RG.js";
|
||
import {
|
||
EditorState,
|
||
Facet,
|
||
Prec,
|
||
RangeSet,
|
||
RangeSetBuilder,
|
||
StateEffect,
|
||
StateField,
|
||
combineConfig,
|
||
countColumn
|
||
} from "./chunk-JEVQZFNC.js";
|
||
|
||
// node_modules/@lezer/common/dist/index.js
|
||
var DefaultBufferLength = 1024;
|
||
var nextPropID = 0;
|
||
var Range = class {
|
||
constructor(from, to) {
|
||
this.from = from;
|
||
this.to = to;
|
||
}
|
||
};
|
||
var NodeProp = class {
|
||
/**
|
||
Create a new node prop type.
|
||
*/
|
||
constructor(config = {}) {
|
||
this.id = nextPropID++;
|
||
this.perNode = !!config.perNode;
|
||
this.deserialize = config.deserialize || (() => {
|
||
throw new Error("This node type doesn't define a deserialize function");
|
||
});
|
||
}
|
||
/**
|
||
This is meant to be used with
|
||
[`NodeSet.extend`](#common.NodeSet.extend) or
|
||
[`LRParser.configure`](#lr.ParserConfig.props) to compute
|
||
prop values for each node type in the set. Takes a [match
|
||
object](#common.NodeType^match) or function that returns undefined
|
||
if the node type doesn't get this prop, and the prop's value if
|
||
it does.
|
||
*/
|
||
add(match) {
|
||
if (this.perNode)
|
||
throw new RangeError("Can't add per-node props to node types");
|
||
if (typeof match != "function")
|
||
match = NodeType.match(match);
|
||
return (type) => {
|
||
let result = match(type);
|
||
return result === void 0 ? null : [this, result];
|
||
};
|
||
}
|
||
};
|
||
NodeProp.closedBy = new NodeProp({ deserialize: (str) => str.split(" ") });
|
||
NodeProp.openedBy = new NodeProp({ deserialize: (str) => str.split(" ") });
|
||
NodeProp.group = new NodeProp({ deserialize: (str) => str.split(" ") });
|
||
NodeProp.isolate = new NodeProp({ deserialize: (value) => {
|
||
if (value && value != "rtl" && value != "ltr" && value != "auto")
|
||
throw new RangeError("Invalid value for isolate: " + value);
|
||
return value || "auto";
|
||
} });
|
||
NodeProp.contextHash = new NodeProp({ perNode: true });
|
||
NodeProp.lookAhead = new NodeProp({ perNode: true });
|
||
NodeProp.mounted = new NodeProp({ perNode: true });
|
||
var MountedTree = class {
|
||
constructor(tree, overlay, parser) {
|
||
this.tree = tree;
|
||
this.overlay = overlay;
|
||
this.parser = parser;
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
static get(tree) {
|
||
return tree && tree.props && tree.props[NodeProp.mounted.id];
|
||
}
|
||
};
|
||
var noProps = /* @__PURE__ */ Object.create(null);
|
||
var NodeType = class _NodeType {
|
||
/**
|
||
@internal
|
||
*/
|
||
constructor(name2, props, id, flags = 0) {
|
||
this.name = name2;
|
||
this.props = props;
|
||
this.id = id;
|
||
this.flags = flags;
|
||
}
|
||
/**
|
||
Define a node type.
|
||
*/
|
||
static define(spec) {
|
||
let props = spec.props && spec.props.length ? /* @__PURE__ */ Object.create(null) : noProps;
|
||
let flags = (spec.top ? 1 : 0) | (spec.skipped ? 2 : 0) | (spec.error ? 4 : 0) | (spec.name == null ? 8 : 0);
|
||
let type = new _NodeType(spec.name || "", props, spec.id, flags);
|
||
if (spec.props)
|
||
for (let src of spec.props) {
|
||
if (!Array.isArray(src))
|
||
src = src(type);
|
||
if (src) {
|
||
if (src[0].perNode)
|
||
throw new RangeError("Can't store a per-node prop on a node type");
|
||
props[src[0].id] = src[1];
|
||
}
|
||
}
|
||
return type;
|
||
}
|
||
/**
|
||
Retrieves a node prop for this type. Will return `undefined` if
|
||
the prop isn't present on this node.
|
||
*/
|
||
prop(prop) {
|
||
return this.props[prop.id];
|
||
}
|
||
/**
|
||
True when this is the top node of a grammar.
|
||
*/
|
||
get isTop() {
|
||
return (this.flags & 1) > 0;
|
||
}
|
||
/**
|
||
True when this node is produced by a skip rule.
|
||
*/
|
||
get isSkipped() {
|
||
return (this.flags & 2) > 0;
|
||
}
|
||
/**
|
||
Indicates whether this is an error node.
|
||
*/
|
||
get isError() {
|
||
return (this.flags & 4) > 0;
|
||
}
|
||
/**
|
||
When true, this node type doesn't correspond to a user-declared
|
||
named node, for example because it is used to cache repetition.
|
||
*/
|
||
get isAnonymous() {
|
||
return (this.flags & 8) > 0;
|
||
}
|
||
/**
|
||
Returns true when this node's name or one of its
|
||
[groups](#common.NodeProp^group) matches the given string.
|
||
*/
|
||
is(name2) {
|
||
if (typeof name2 == "string") {
|
||
if (this.name == name2)
|
||
return true;
|
||
let group = this.prop(NodeProp.group);
|
||
return group ? group.indexOf(name2) > -1 : false;
|
||
}
|
||
return this.id == name2;
|
||
}
|
||
/**
|
||
Create a function from node types to arbitrary values by
|
||
specifying an object whose property names are node or
|
||
[group](#common.NodeProp^group) names. Often useful with
|
||
[`NodeProp.add`](#common.NodeProp.add). You can put multiple
|
||
names, separated by spaces, in a single property name to map
|
||
multiple node names to a single value.
|
||
*/
|
||
static match(map) {
|
||
let direct = /* @__PURE__ */ Object.create(null);
|
||
for (let prop in map)
|
||
for (let name2 of prop.split(" "))
|
||
direct[name2] = map[prop];
|
||
return (node) => {
|
||
for (let groups = node.prop(NodeProp.group), i = -1; i < (groups ? groups.length : 0); i++) {
|
||
let found = direct[i < 0 ? node.name : groups[i]];
|
||
if (found)
|
||
return found;
|
||
}
|
||
};
|
||
}
|
||
};
|
||
NodeType.none = new NodeType(
|
||
"",
|
||
/* @__PURE__ */ Object.create(null),
|
||
0,
|
||
8
|
||
/* NodeFlag.Anonymous */
|
||
);
|
||
var NodeSet = class _NodeSet {
|
||
/**
|
||
Create a set with the given types. The `id` property of each
|
||
type should correspond to its position within the array.
|
||
*/
|
||
constructor(types) {
|
||
this.types = types;
|
||
for (let i = 0; i < types.length; i++)
|
||
if (types[i].id != i)
|
||
throw new RangeError("Node type ids should correspond to array positions when creating a node set");
|
||
}
|
||
/**
|
||
Create a copy of this set with some node properties added. The
|
||
arguments to this method can be created with
|
||
[`NodeProp.add`](#common.NodeProp.add).
|
||
*/
|
||
extend(...props) {
|
||
let newTypes = [];
|
||
for (let type of this.types) {
|
||
let newProps = null;
|
||
for (let source of props) {
|
||
let add = source(type);
|
||
if (add) {
|
||
if (!newProps)
|
||
newProps = Object.assign({}, type.props);
|
||
newProps[add[0].id] = add[1];
|
||
}
|
||
}
|
||
newTypes.push(newProps ? new NodeType(type.name, newProps, type.id, type.flags) : type);
|
||
}
|
||
return new _NodeSet(newTypes);
|
||
}
|
||
};
|
||
var CachedNode = /* @__PURE__ */ new WeakMap();
|
||
var CachedInnerNode = /* @__PURE__ */ new WeakMap();
|
||
var IterMode;
|
||
(function(IterMode2) {
|
||
IterMode2[IterMode2["ExcludeBuffers"] = 1] = "ExcludeBuffers";
|
||
IterMode2[IterMode2["IncludeAnonymous"] = 2] = "IncludeAnonymous";
|
||
IterMode2[IterMode2["IgnoreMounts"] = 4] = "IgnoreMounts";
|
||
IterMode2[IterMode2["IgnoreOverlays"] = 8] = "IgnoreOverlays";
|
||
})(IterMode || (IterMode = {}));
|
||
var Tree = class _Tree {
|
||
/**
|
||
Construct a new tree. See also [`Tree.build`](#common.Tree^build).
|
||
*/
|
||
constructor(type, children, positions, length, props) {
|
||
this.type = type;
|
||
this.children = children;
|
||
this.positions = positions;
|
||
this.length = length;
|
||
this.props = null;
|
||
if (props && props.length) {
|
||
this.props = /* @__PURE__ */ Object.create(null);
|
||
for (let [prop, value] of props)
|
||
this.props[typeof prop == "number" ? prop : prop.id] = value;
|
||
}
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
toString() {
|
||
let mounted = MountedTree.get(this);
|
||
if (mounted && !mounted.overlay)
|
||
return mounted.tree.toString();
|
||
let children = "";
|
||
for (let ch of this.children) {
|
||
let str = ch.toString();
|
||
if (str) {
|
||
if (children)
|
||
children += ",";
|
||
children += str;
|
||
}
|
||
}
|
||
return !this.type.name ? children : (/\W/.test(this.type.name) && !this.type.isError ? JSON.stringify(this.type.name) : this.type.name) + (children.length ? "(" + children + ")" : "");
|
||
}
|
||
/**
|
||
Get a [tree cursor](#common.TreeCursor) positioned at the top of
|
||
the tree. Mode can be used to [control](#common.IterMode) which
|
||
nodes the cursor visits.
|
||
*/
|
||
cursor(mode = 0) {
|
||
return new TreeCursor(this.topNode, mode);
|
||
}
|
||
/**
|
||
Get a [tree cursor](#common.TreeCursor) pointing into this tree
|
||
at the given position and side (see
|
||
[`moveTo`](#common.TreeCursor.moveTo).
|
||
*/
|
||
cursorAt(pos, side = 0, mode = 0) {
|
||
let scope = CachedNode.get(this) || this.topNode;
|
||
let cursor = new TreeCursor(scope);
|
||
cursor.moveTo(pos, side);
|
||
CachedNode.set(this, cursor._tree);
|
||
return cursor;
|
||
}
|
||
/**
|
||
Get a [syntax node](#common.SyntaxNode) object for the top of the
|
||
tree.
|
||
*/
|
||
get topNode() {
|
||
return new TreeNode(this, 0, 0, null);
|
||
}
|
||
/**
|
||
Get the [syntax node](#common.SyntaxNode) at the given position.
|
||
If `side` is -1, this will move into nodes that end at the
|
||
position. If 1, it'll move into nodes that start at the
|
||
position. With 0, it'll only enter nodes that cover the position
|
||
from both sides.
|
||
|
||
Note that this will not enter
|
||
[overlays](#common.MountedTree.overlay), and you often want
|
||
[`resolveInner`](#common.Tree.resolveInner) instead.
|
||
*/
|
||
resolve(pos, side = 0) {
|
||
let node = resolveNode(CachedNode.get(this) || this.topNode, pos, side, false);
|
||
CachedNode.set(this, node);
|
||
return node;
|
||
}
|
||
/**
|
||
Like [`resolve`](#common.Tree.resolve), but will enter
|
||
[overlaid](#common.MountedTree.overlay) nodes, producing a syntax node
|
||
pointing into the innermost overlaid tree at the given position
|
||
(with parent links going through all parent structure, including
|
||
the host trees).
|
||
*/
|
||
resolveInner(pos, side = 0) {
|
||
let node = resolveNode(CachedInnerNode.get(this) || this.topNode, pos, side, true);
|
||
CachedInnerNode.set(this, node);
|
||
return node;
|
||
}
|
||
/**
|
||
In some situations, it can be useful to iterate through all
|
||
nodes around a position, including those in overlays that don't
|
||
directly cover the position. This method gives you an iterator
|
||
that will produce all nodes, from small to big, around the given
|
||
position.
|
||
*/
|
||
resolveStack(pos, side = 0) {
|
||
return stackIterator(this, pos, side);
|
||
}
|
||
/**
|
||
Iterate over the tree and its children, calling `enter` for any
|
||
node that touches the `from`/`to` region (if given) before
|
||
running over such a node's children, and `leave` (if given) when
|
||
leaving the node. When `enter` returns `false`, that node will
|
||
not have its children iterated over (or `leave` called).
|
||
*/
|
||
iterate(spec) {
|
||
let { enter, leave, from = 0, to = this.length } = spec;
|
||
let mode = spec.mode || 0, anon = (mode & IterMode.IncludeAnonymous) > 0;
|
||
for (let c = this.cursor(mode | IterMode.IncludeAnonymous); ; ) {
|
||
let entered = false;
|
||
if (c.from <= to && c.to >= from && (!anon && c.type.isAnonymous || enter(c) !== false)) {
|
||
if (c.firstChild())
|
||
continue;
|
||
entered = true;
|
||
}
|
||
for (; ; ) {
|
||
if (entered && leave && (anon || !c.type.isAnonymous))
|
||
leave(c);
|
||
if (c.nextSibling())
|
||
break;
|
||
if (!c.parent())
|
||
return;
|
||
entered = true;
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
Get the value of the given [node prop](#common.NodeProp) for this
|
||
node. Works with both per-node and per-type props.
|
||
*/
|
||
prop(prop) {
|
||
return !prop.perNode ? this.type.prop(prop) : this.props ? this.props[prop.id] : void 0;
|
||
}
|
||
/**
|
||
Returns the node's [per-node props](#common.NodeProp.perNode) in a
|
||
format that can be passed to the [`Tree`](#common.Tree)
|
||
constructor.
|
||
*/
|
||
get propValues() {
|
||
let result = [];
|
||
if (this.props)
|
||
for (let id in this.props)
|
||
result.push([+id, this.props[id]]);
|
||
return result;
|
||
}
|
||
/**
|
||
Balance the direct children of this tree, producing a copy of
|
||
which may have children grouped into subtrees with type
|
||
[`NodeType.none`](#common.NodeType^none).
|
||
*/
|
||
balance(config = {}) {
|
||
return this.children.length <= 8 ? this : balanceRange(NodeType.none, this.children, this.positions, 0, this.children.length, 0, this.length, (children, positions, length) => new _Tree(this.type, children, positions, length, this.propValues), config.makeTree || ((children, positions, length) => new _Tree(NodeType.none, children, positions, length)));
|
||
}
|
||
/**
|
||
Build a tree from a postfix-ordered buffer of node information,
|
||
or a cursor over such a buffer.
|
||
*/
|
||
static build(data) {
|
||
return buildTree(data);
|
||
}
|
||
};
|
||
Tree.empty = new Tree(NodeType.none, [], [], 0);
|
||
var FlatBufferCursor = class _FlatBufferCursor {
|
||
constructor(buffer, index) {
|
||
this.buffer = buffer;
|
||
this.index = index;
|
||
}
|
||
get id() {
|
||
return this.buffer[this.index - 4];
|
||
}
|
||
get start() {
|
||
return this.buffer[this.index - 3];
|
||
}
|
||
get end() {
|
||
return this.buffer[this.index - 2];
|
||
}
|
||
get size() {
|
||
return this.buffer[this.index - 1];
|
||
}
|
||
get pos() {
|
||
return this.index;
|
||
}
|
||
next() {
|
||
this.index -= 4;
|
||
}
|
||
fork() {
|
||
return new _FlatBufferCursor(this.buffer, this.index);
|
||
}
|
||
};
|
||
var TreeBuffer = class _TreeBuffer {
|
||
/**
|
||
Create a tree buffer.
|
||
*/
|
||
constructor(buffer, length, set) {
|
||
this.buffer = buffer;
|
||
this.length = length;
|
||
this.set = set;
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
get type() {
|
||
return NodeType.none;
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
toString() {
|
||
let result = [];
|
||
for (let index = 0; index < this.buffer.length; ) {
|
||
result.push(this.childString(index));
|
||
index = this.buffer[index + 3];
|
||
}
|
||
return result.join(",");
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
childString(index) {
|
||
let id = this.buffer[index], endIndex = this.buffer[index + 3];
|
||
let type = this.set.types[id], result = type.name;
|
||
if (/\W/.test(result) && !type.isError)
|
||
result = JSON.stringify(result);
|
||
index += 4;
|
||
if (endIndex == index)
|
||
return result;
|
||
let children = [];
|
||
while (index < endIndex) {
|
||
children.push(this.childString(index));
|
||
index = this.buffer[index + 3];
|
||
}
|
||
return result + "(" + children.join(",") + ")";
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
findChild(startIndex, endIndex, dir, pos, side) {
|
||
let { buffer } = this, pick = -1;
|
||
for (let i = startIndex; i != endIndex; i = buffer[i + 3]) {
|
||
if (checkSide(side, pos, buffer[i + 1], buffer[i + 2])) {
|
||
pick = i;
|
||
if (dir > 0)
|
||
break;
|
||
}
|
||
}
|
||
return pick;
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
slice(startI, endI, from) {
|
||
let b = this.buffer;
|
||
let copy = new Uint16Array(endI - startI), len = 0;
|
||
for (let i = startI, j = 0; i < endI; ) {
|
||
copy[j++] = b[i++];
|
||
copy[j++] = b[i++] - from;
|
||
let to = copy[j++] = b[i++] - from;
|
||
copy[j++] = b[i++] - startI;
|
||
len = Math.max(len, to);
|
||
}
|
||
return new _TreeBuffer(copy, len, this.set);
|
||
}
|
||
};
|
||
function checkSide(side, pos, from, to) {
|
||
switch (side) {
|
||
case -2:
|
||
return from < pos;
|
||
case -1:
|
||
return to >= pos && from < pos;
|
||
case 0:
|
||
return from < pos && to > pos;
|
||
case 1:
|
||
return from <= pos && to > pos;
|
||
case 2:
|
||
return to > pos;
|
||
case 4:
|
||
return true;
|
||
}
|
||
}
|
||
function resolveNode(node, pos, side, overlays) {
|
||
var _a2;
|
||
while (node.from == node.to || (side < 1 ? node.from >= pos : node.from > pos) || (side > -1 ? node.to <= pos : node.to < pos)) {
|
||
let parent = !overlays && node instanceof TreeNode && node.index < 0 ? null : node.parent;
|
||
if (!parent)
|
||
return node;
|
||
node = parent;
|
||
}
|
||
let mode = overlays ? 0 : IterMode.IgnoreOverlays;
|
||
if (overlays)
|
||
for (let scan = node, parent = scan.parent; parent; scan = parent, parent = scan.parent) {
|
||
if (scan instanceof TreeNode && scan.index < 0 && ((_a2 = parent.enter(pos, side, mode)) === null || _a2 === void 0 ? void 0 : _a2.from) != scan.from)
|
||
node = parent;
|
||
}
|
||
for (; ; ) {
|
||
let inner = node.enter(pos, side, mode);
|
||
if (!inner)
|
||
return node;
|
||
node = inner;
|
||
}
|
||
}
|
||
var BaseNode = class {
|
||
cursor(mode = 0) {
|
||
return new TreeCursor(this, mode);
|
||
}
|
||
getChild(type, before = null, after = null) {
|
||
let r = getChildren(this, type, before, after);
|
||
return r.length ? r[0] : null;
|
||
}
|
||
getChildren(type, before = null, after = null) {
|
||
return getChildren(this, type, before, after);
|
||
}
|
||
resolve(pos, side = 0) {
|
||
return resolveNode(this, pos, side, false);
|
||
}
|
||
resolveInner(pos, side = 0) {
|
||
return resolveNode(this, pos, side, true);
|
||
}
|
||
matchContext(context) {
|
||
return matchNodeContext(this.parent, context);
|
||
}
|
||
enterUnfinishedNodesBefore(pos) {
|
||
let scan = this.childBefore(pos), node = this;
|
||
while (scan) {
|
||
let last = scan.lastChild;
|
||
if (!last || last.to != scan.to)
|
||
break;
|
||
if (last.type.isError && last.from == last.to) {
|
||
node = scan;
|
||
scan = last.prevSibling;
|
||
} else {
|
||
scan = last;
|
||
}
|
||
}
|
||
return node;
|
||
}
|
||
get node() {
|
||
return this;
|
||
}
|
||
get next() {
|
||
return this.parent;
|
||
}
|
||
};
|
||
var TreeNode = class _TreeNode extends BaseNode {
|
||
constructor(_tree, from, index, _parent) {
|
||
super();
|
||
this._tree = _tree;
|
||
this.from = from;
|
||
this.index = index;
|
||
this._parent = _parent;
|
||
}
|
||
get type() {
|
||
return this._tree.type;
|
||
}
|
||
get name() {
|
||
return this._tree.type.name;
|
||
}
|
||
get to() {
|
||
return this.from + this._tree.length;
|
||
}
|
||
nextChild(i, dir, pos, side, mode = 0) {
|
||
for (let parent = this; ; ) {
|
||
for (let { children, positions } = parent._tree, e = dir > 0 ? children.length : -1; i != e; i += dir) {
|
||
let next = children[i], start = positions[i] + parent.from;
|
||
if (!checkSide(side, pos, start, start + next.length))
|
||
continue;
|
||
if (next instanceof TreeBuffer) {
|
||
if (mode & IterMode.ExcludeBuffers)
|
||
continue;
|
||
let index = next.findChild(0, next.buffer.length, dir, pos - start, side);
|
||
if (index > -1)
|
||
return new BufferNode(new BufferContext(parent, next, i, start), null, index);
|
||
} else if (mode & IterMode.IncludeAnonymous || (!next.type.isAnonymous || hasChild(next))) {
|
||
let mounted;
|
||
if (!(mode & IterMode.IgnoreMounts) && (mounted = MountedTree.get(next)) && !mounted.overlay)
|
||
return new _TreeNode(mounted.tree, start, i, parent);
|
||
let inner = new _TreeNode(next, start, i, parent);
|
||
return mode & IterMode.IncludeAnonymous || !inner.type.isAnonymous ? inner : inner.nextChild(dir < 0 ? next.children.length - 1 : 0, dir, pos, side);
|
||
}
|
||
}
|
||
if (mode & IterMode.IncludeAnonymous || !parent.type.isAnonymous)
|
||
return null;
|
||
if (parent.index >= 0)
|
||
i = parent.index + dir;
|
||
else
|
||
i = dir < 0 ? -1 : parent._parent._tree.children.length;
|
||
parent = parent._parent;
|
||
if (!parent)
|
||
return null;
|
||
}
|
||
}
|
||
get firstChild() {
|
||
return this.nextChild(
|
||
0,
|
||
1,
|
||
0,
|
||
4
|
||
/* Side.DontCare */
|
||
);
|
||
}
|
||
get lastChild() {
|
||
return this.nextChild(
|
||
this._tree.children.length - 1,
|
||
-1,
|
||
0,
|
||
4
|
||
/* Side.DontCare */
|
||
);
|
||
}
|
||
childAfter(pos) {
|
||
return this.nextChild(
|
||
0,
|
||
1,
|
||
pos,
|
||
2
|
||
/* Side.After */
|
||
);
|
||
}
|
||
childBefore(pos) {
|
||
return this.nextChild(
|
||
this._tree.children.length - 1,
|
||
-1,
|
||
pos,
|
||
-2
|
||
/* Side.Before */
|
||
);
|
||
}
|
||
enter(pos, side, mode = 0) {
|
||
let mounted;
|
||
if (!(mode & IterMode.IgnoreOverlays) && (mounted = MountedTree.get(this._tree)) && mounted.overlay) {
|
||
let rPos = pos - this.from;
|
||
for (let { from, to } of mounted.overlay) {
|
||
if ((side > 0 ? from <= rPos : from < rPos) && (side < 0 ? to >= rPos : to > rPos))
|
||
return new _TreeNode(mounted.tree, mounted.overlay[0].from + this.from, -1, this);
|
||
}
|
||
}
|
||
return this.nextChild(0, 1, pos, side, mode);
|
||
}
|
||
nextSignificantParent() {
|
||
let val = this;
|
||
while (val.type.isAnonymous && val._parent)
|
||
val = val._parent;
|
||
return val;
|
||
}
|
||
get parent() {
|
||
return this._parent ? this._parent.nextSignificantParent() : null;
|
||
}
|
||
get nextSibling() {
|
||
return this._parent && this.index >= 0 ? this._parent.nextChild(
|
||
this.index + 1,
|
||
1,
|
||
0,
|
||
4
|
||
/* Side.DontCare */
|
||
) : null;
|
||
}
|
||
get prevSibling() {
|
||
return this._parent && this.index >= 0 ? this._parent.nextChild(
|
||
this.index - 1,
|
||
-1,
|
||
0,
|
||
4
|
||
/* Side.DontCare */
|
||
) : null;
|
||
}
|
||
get tree() {
|
||
return this._tree;
|
||
}
|
||
toTree() {
|
||
return this._tree;
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
toString() {
|
||
return this._tree.toString();
|
||
}
|
||
};
|
||
function getChildren(node, type, before, after) {
|
||
let cur = node.cursor(), result = [];
|
||
if (!cur.firstChild())
|
||
return result;
|
||
if (before != null)
|
||
for (let found = false; !found; ) {
|
||
found = cur.type.is(before);
|
||
if (!cur.nextSibling())
|
||
return result;
|
||
}
|
||
for (; ; ) {
|
||
if (after != null && cur.type.is(after))
|
||
return result;
|
||
if (cur.type.is(type))
|
||
result.push(cur.node);
|
||
if (!cur.nextSibling())
|
||
return after == null ? result : [];
|
||
}
|
||
}
|
||
function matchNodeContext(node, context, i = context.length - 1) {
|
||
for (let p = node; i >= 0; p = p.parent) {
|
||
if (!p)
|
||
return false;
|
||
if (!p.type.isAnonymous) {
|
||
if (context[i] && context[i] != p.name)
|
||
return false;
|
||
i--;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
var BufferContext = class {
|
||
constructor(parent, buffer, index, start) {
|
||
this.parent = parent;
|
||
this.buffer = buffer;
|
||
this.index = index;
|
||
this.start = start;
|
||
}
|
||
};
|
||
var BufferNode = class _BufferNode extends BaseNode {
|
||
get name() {
|
||
return this.type.name;
|
||
}
|
||
get from() {
|
||
return this.context.start + this.context.buffer.buffer[this.index + 1];
|
||
}
|
||
get to() {
|
||
return this.context.start + this.context.buffer.buffer[this.index + 2];
|
||
}
|
||
constructor(context, _parent, index) {
|
||
super();
|
||
this.context = context;
|
||
this._parent = _parent;
|
||
this.index = index;
|
||
this.type = context.buffer.set.types[context.buffer.buffer[index]];
|
||
}
|
||
child(dir, pos, side) {
|
||
let { buffer } = this.context;
|
||
let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], dir, pos - this.context.start, side);
|
||
return index < 0 ? null : new _BufferNode(this.context, this, index);
|
||
}
|
||
get firstChild() {
|
||
return this.child(
|
||
1,
|
||
0,
|
||
4
|
||
/* Side.DontCare */
|
||
);
|
||
}
|
||
get lastChild() {
|
||
return this.child(
|
||
-1,
|
||
0,
|
||
4
|
||
/* Side.DontCare */
|
||
);
|
||
}
|
||
childAfter(pos) {
|
||
return this.child(
|
||
1,
|
||
pos,
|
||
2
|
||
/* Side.After */
|
||
);
|
||
}
|
||
childBefore(pos) {
|
||
return this.child(
|
||
-1,
|
||
pos,
|
||
-2
|
||
/* Side.Before */
|
||
);
|
||
}
|
||
enter(pos, side, mode = 0) {
|
||
if (mode & IterMode.ExcludeBuffers)
|
||
return null;
|
||
let { buffer } = this.context;
|
||
let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], side > 0 ? 1 : -1, pos - this.context.start, side);
|
||
return index < 0 ? null : new _BufferNode(this.context, this, index);
|
||
}
|
||
get parent() {
|
||
return this._parent || this.context.parent.nextSignificantParent();
|
||
}
|
||
externalSibling(dir) {
|
||
return this._parent ? null : this.context.parent.nextChild(
|
||
this.context.index + dir,
|
||
dir,
|
||
0,
|
||
4
|
||
/* Side.DontCare */
|
||
);
|
||
}
|
||
get nextSibling() {
|
||
let { buffer } = this.context;
|
||
let after = buffer.buffer[this.index + 3];
|
||
if (after < (this._parent ? buffer.buffer[this._parent.index + 3] : buffer.buffer.length))
|
||
return new _BufferNode(this.context, this._parent, after);
|
||
return this.externalSibling(1);
|
||
}
|
||
get prevSibling() {
|
||
let { buffer } = this.context;
|
||
let parentStart = this._parent ? this._parent.index + 4 : 0;
|
||
if (this.index == parentStart)
|
||
return this.externalSibling(-1);
|
||
return new _BufferNode(this.context, this._parent, buffer.findChild(
|
||
parentStart,
|
||
this.index,
|
||
-1,
|
||
0,
|
||
4
|
||
/* Side.DontCare */
|
||
));
|
||
}
|
||
get tree() {
|
||
return null;
|
||
}
|
||
toTree() {
|
||
let children = [], positions = [];
|
||
let { buffer } = this.context;
|
||
let startI = this.index + 4, endI = buffer.buffer[this.index + 3];
|
||
if (endI > startI) {
|
||
let from = buffer.buffer[this.index + 1];
|
||
children.push(buffer.slice(startI, endI, from));
|
||
positions.push(0);
|
||
}
|
||
return new Tree(this.type, children, positions, this.to - this.from);
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
toString() {
|
||
return this.context.buffer.childString(this.index);
|
||
}
|
||
};
|
||
function iterStack(heads) {
|
||
if (!heads.length)
|
||
return null;
|
||
let pick = 0, picked = heads[0];
|
||
for (let i = 1; i < heads.length; i++) {
|
||
let node = heads[i];
|
||
if (node.from > picked.from || node.to < picked.to) {
|
||
picked = node;
|
||
pick = i;
|
||
}
|
||
}
|
||
let next = picked instanceof TreeNode && picked.index < 0 ? null : picked.parent;
|
||
let newHeads = heads.slice();
|
||
if (next)
|
||
newHeads[pick] = next;
|
||
else
|
||
newHeads.splice(pick, 1);
|
||
return new StackIterator(newHeads, picked);
|
||
}
|
||
var StackIterator = class {
|
||
constructor(heads, node) {
|
||
this.heads = heads;
|
||
this.node = node;
|
||
}
|
||
get next() {
|
||
return iterStack(this.heads);
|
||
}
|
||
};
|
||
function stackIterator(tree, pos, side) {
|
||
let inner = tree.resolveInner(pos, side), layers = null;
|
||
for (let scan = inner instanceof TreeNode ? inner : inner.context.parent; scan; scan = scan.parent) {
|
||
if (scan.index < 0) {
|
||
let parent = scan.parent;
|
||
(layers || (layers = [inner])).push(parent.resolve(pos, side));
|
||
scan = parent;
|
||
} else {
|
||
let mount = MountedTree.get(scan.tree);
|
||
if (mount && mount.overlay && mount.overlay[0].from <= pos && mount.overlay[mount.overlay.length - 1].to >= pos) {
|
||
let root = new TreeNode(mount.tree, mount.overlay[0].from + scan.from, -1, scan);
|
||
(layers || (layers = [inner])).push(resolveNode(root, pos, side, false));
|
||
}
|
||
}
|
||
}
|
||
return layers ? iterStack(layers) : inner;
|
||
}
|
||
var TreeCursor = class {
|
||
/**
|
||
Shorthand for `.type.name`.
|
||
*/
|
||
get name() {
|
||
return this.type.name;
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
constructor(node, mode = 0) {
|
||
this.mode = mode;
|
||
this.buffer = null;
|
||
this.stack = [];
|
||
this.index = 0;
|
||
this.bufferNode = null;
|
||
if (node instanceof TreeNode) {
|
||
this.yieldNode(node);
|
||
} else {
|
||
this._tree = node.context.parent;
|
||
this.buffer = node.context;
|
||
for (let n = node._parent; n; n = n._parent)
|
||
this.stack.unshift(n.index);
|
||
this.bufferNode = node;
|
||
this.yieldBuf(node.index);
|
||
}
|
||
}
|
||
yieldNode(node) {
|
||
if (!node)
|
||
return false;
|
||
this._tree = node;
|
||
this.type = node.type;
|
||
this.from = node.from;
|
||
this.to = node.to;
|
||
return true;
|
||
}
|
||
yieldBuf(index, type) {
|
||
this.index = index;
|
||
let { start, buffer } = this.buffer;
|
||
this.type = type || buffer.set.types[buffer.buffer[index]];
|
||
this.from = start + buffer.buffer[index + 1];
|
||
this.to = start + buffer.buffer[index + 2];
|
||
return true;
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
yield(node) {
|
||
if (!node)
|
||
return false;
|
||
if (node instanceof TreeNode) {
|
||
this.buffer = null;
|
||
return this.yieldNode(node);
|
||
}
|
||
this.buffer = node.context;
|
||
return this.yieldBuf(node.index, node.type);
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
toString() {
|
||
return this.buffer ? this.buffer.buffer.childString(this.index) : this._tree.toString();
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
enterChild(dir, pos, side) {
|
||
if (!this.buffer)
|
||
return this.yield(this._tree.nextChild(dir < 0 ? this._tree._tree.children.length - 1 : 0, dir, pos, side, this.mode));
|
||
let { buffer } = this.buffer;
|
||
let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], dir, pos - this.buffer.start, side);
|
||
if (index < 0)
|
||
return false;
|
||
this.stack.push(this.index);
|
||
return this.yieldBuf(index);
|
||
}
|
||
/**
|
||
Move the cursor to this node's first child. When this returns
|
||
false, the node has no child, and the cursor has not been moved.
|
||
*/
|
||
firstChild() {
|
||
return this.enterChild(
|
||
1,
|
||
0,
|
||
4
|
||
/* Side.DontCare */
|
||
);
|
||
}
|
||
/**
|
||
Move the cursor to this node's last child.
|
||
*/
|
||
lastChild() {
|
||
return this.enterChild(
|
||
-1,
|
||
0,
|
||
4
|
||
/* Side.DontCare */
|
||
);
|
||
}
|
||
/**
|
||
Move the cursor to the first child that ends after `pos`.
|
||
*/
|
||
childAfter(pos) {
|
||
return this.enterChild(
|
||
1,
|
||
pos,
|
||
2
|
||
/* Side.After */
|
||
);
|
||
}
|
||
/**
|
||
Move to the last child that starts before `pos`.
|
||
*/
|
||
childBefore(pos) {
|
||
return this.enterChild(
|
||
-1,
|
||
pos,
|
||
-2
|
||
/* Side.Before */
|
||
);
|
||
}
|
||
/**
|
||
Move the cursor to the child around `pos`. If side is -1 the
|
||
child may end at that position, when 1 it may start there. This
|
||
will also enter [overlaid](#common.MountedTree.overlay)
|
||
[mounted](#common.NodeProp^mounted) trees unless `overlays` is
|
||
set to false.
|
||
*/
|
||
enter(pos, side, mode = this.mode) {
|
||
if (!this.buffer)
|
||
return this.yield(this._tree.enter(pos, side, mode));
|
||
return mode & IterMode.ExcludeBuffers ? false : this.enterChild(1, pos, side);
|
||
}
|
||
/**
|
||
Move to the node's parent node, if this isn't the top node.
|
||
*/
|
||
parent() {
|
||
if (!this.buffer)
|
||
return this.yieldNode(this.mode & IterMode.IncludeAnonymous ? this._tree._parent : this._tree.parent);
|
||
if (this.stack.length)
|
||
return this.yieldBuf(this.stack.pop());
|
||
let parent = this.mode & IterMode.IncludeAnonymous ? this.buffer.parent : this.buffer.parent.nextSignificantParent();
|
||
this.buffer = null;
|
||
return this.yieldNode(parent);
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
sibling(dir) {
|
||
if (!this.buffer)
|
||
return !this._tree._parent ? false : this.yield(this._tree.index < 0 ? null : this._tree._parent.nextChild(this._tree.index + dir, dir, 0, 4, this.mode));
|
||
let { buffer } = this.buffer, d = this.stack.length - 1;
|
||
if (dir < 0) {
|
||
let parentStart = d < 0 ? 0 : this.stack[d] + 4;
|
||
if (this.index != parentStart)
|
||
return this.yieldBuf(buffer.findChild(
|
||
parentStart,
|
||
this.index,
|
||
-1,
|
||
0,
|
||
4
|
||
/* Side.DontCare */
|
||
));
|
||
} else {
|
||
let after = buffer.buffer[this.index + 3];
|
||
if (after < (d < 0 ? buffer.buffer.length : buffer.buffer[this.stack[d] + 3]))
|
||
return this.yieldBuf(after);
|
||
}
|
||
return d < 0 ? this.yield(this.buffer.parent.nextChild(this.buffer.index + dir, dir, 0, 4, this.mode)) : false;
|
||
}
|
||
/**
|
||
Move to this node's next sibling, if any.
|
||
*/
|
||
nextSibling() {
|
||
return this.sibling(1);
|
||
}
|
||
/**
|
||
Move to this node's previous sibling, if any.
|
||
*/
|
||
prevSibling() {
|
||
return this.sibling(-1);
|
||
}
|
||
atLastNode(dir) {
|
||
let index, parent, { buffer } = this;
|
||
if (buffer) {
|
||
if (dir > 0) {
|
||
if (this.index < buffer.buffer.buffer.length)
|
||
return false;
|
||
} else {
|
||
for (let i = 0; i < this.index; i++)
|
||
if (buffer.buffer.buffer[i + 3] < this.index)
|
||
return false;
|
||
}
|
||
({ index, parent } = buffer);
|
||
} else {
|
||
({ index, _parent: parent } = this._tree);
|
||
}
|
||
for (; parent; { index, _parent: parent } = parent) {
|
||
if (index > -1)
|
||
for (let i = index + dir, e = dir < 0 ? -1 : parent._tree.children.length; i != e; i += dir) {
|
||
let child = parent._tree.children[i];
|
||
if (this.mode & IterMode.IncludeAnonymous || child instanceof TreeBuffer || !child.type.isAnonymous || hasChild(child))
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
move(dir, enter) {
|
||
if (enter && this.enterChild(
|
||
dir,
|
||
0,
|
||
4
|
||
/* Side.DontCare */
|
||
))
|
||
return true;
|
||
for (; ; ) {
|
||
if (this.sibling(dir))
|
||
return true;
|
||
if (this.atLastNode(dir) || !this.parent())
|
||
return false;
|
||
}
|
||
}
|
||
/**
|
||
Move to the next node in a
|
||
[pre-order](https://en.wikipedia.org/wiki/Tree_traversal#Pre-order,_NLR)
|
||
traversal, going from a node to its first child or, if the
|
||
current node is empty or `enter` is false, its next sibling or
|
||
the next sibling of the first parent node that has one.
|
||
*/
|
||
next(enter = true) {
|
||
return this.move(1, enter);
|
||
}
|
||
/**
|
||
Move to the next node in a last-to-first pre-order traversal. A
|
||
node is followed by its last child or, if it has none, its
|
||
previous sibling or the previous sibling of the first parent
|
||
node that has one.
|
||
*/
|
||
prev(enter = true) {
|
||
return this.move(-1, enter);
|
||
}
|
||
/**
|
||
Move the cursor to the innermost node that covers `pos`. If
|
||
`side` is -1, it will enter nodes that end at `pos`. If it is 1,
|
||
it will enter nodes that start at `pos`.
|
||
*/
|
||
moveTo(pos, side = 0) {
|
||
while (this.from == this.to || (side < 1 ? this.from >= pos : this.from > pos) || (side > -1 ? this.to <= pos : this.to < pos))
|
||
if (!this.parent())
|
||
break;
|
||
while (this.enterChild(1, pos, side)) {
|
||
}
|
||
return this;
|
||
}
|
||
/**
|
||
Get a [syntax node](#common.SyntaxNode) at the cursor's current
|
||
position.
|
||
*/
|
||
get node() {
|
||
if (!this.buffer)
|
||
return this._tree;
|
||
let cache = this.bufferNode, result = null, depth = 0;
|
||
if (cache && cache.context == this.buffer) {
|
||
scan: for (let index = this.index, d = this.stack.length; d >= 0; ) {
|
||
for (let c = cache; c; c = c._parent)
|
||
if (c.index == index) {
|
||
if (index == this.index)
|
||
return c;
|
||
result = c;
|
||
depth = d + 1;
|
||
break scan;
|
||
}
|
||
index = this.stack[--d];
|
||
}
|
||
}
|
||
for (let i = depth; i < this.stack.length; i++)
|
||
result = new BufferNode(this.buffer, result, this.stack[i]);
|
||
return this.bufferNode = new BufferNode(this.buffer, result, this.index);
|
||
}
|
||
/**
|
||
Get the [tree](#common.Tree) that represents the current node, if
|
||
any. Will return null when the node is in a [tree
|
||
buffer](#common.TreeBuffer).
|
||
*/
|
||
get tree() {
|
||
return this.buffer ? null : this._tree._tree;
|
||
}
|
||
/**
|
||
Iterate over the current node and all its descendants, calling
|
||
`enter` when entering a node and `leave`, if given, when leaving
|
||
one. When `enter` returns `false`, any children of that node are
|
||
skipped, and `leave` isn't called for it.
|
||
*/
|
||
iterate(enter, leave) {
|
||
for (let depth = 0; ; ) {
|
||
let mustLeave = false;
|
||
if (this.type.isAnonymous || enter(this) !== false) {
|
||
if (this.firstChild()) {
|
||
depth++;
|
||
continue;
|
||
}
|
||
if (!this.type.isAnonymous)
|
||
mustLeave = true;
|
||
}
|
||
for (; ; ) {
|
||
if (mustLeave && leave)
|
||
leave(this);
|
||
mustLeave = this.type.isAnonymous;
|
||
if (!depth)
|
||
return;
|
||
if (this.nextSibling())
|
||
break;
|
||
this.parent();
|
||
depth--;
|
||
mustLeave = true;
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
Test whether the current node matches a given context—a sequence
|
||
of direct parent node names. Empty strings in the context array
|
||
are treated as wildcards.
|
||
*/
|
||
matchContext(context) {
|
||
if (!this.buffer)
|
||
return matchNodeContext(this.node.parent, context);
|
||
let { buffer } = this.buffer, { types } = buffer.set;
|
||
for (let i = context.length - 1, d = this.stack.length - 1; i >= 0; d--) {
|
||
if (d < 0)
|
||
return matchNodeContext(this._tree, context, i);
|
||
let type = types[buffer.buffer[this.stack[d]]];
|
||
if (!type.isAnonymous) {
|
||
if (context[i] && context[i] != type.name)
|
||
return false;
|
||
i--;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
};
|
||
function hasChild(tree) {
|
||
return tree.children.some((ch) => ch instanceof TreeBuffer || !ch.type.isAnonymous || hasChild(ch));
|
||
}
|
||
function buildTree(data) {
|
||
var _a2;
|
||
let { buffer, nodeSet: nodeSet2, maxBufferLength = DefaultBufferLength, reused = [], minRepeatType = nodeSet2.types.length } = data;
|
||
let cursor = Array.isArray(buffer) ? new FlatBufferCursor(buffer, buffer.length) : buffer;
|
||
let types = nodeSet2.types;
|
||
let contextHash = 0, lookAhead = 0;
|
||
function takeNode(parentStart, minPos, children2, positions2, inRepeat, depth) {
|
||
let { id, start, end, size } = cursor;
|
||
let lookAheadAtStart = lookAhead, contextAtStart = contextHash;
|
||
while (size < 0) {
|
||
cursor.next();
|
||
if (size == -1) {
|
||
let node2 = reused[id];
|
||
children2.push(node2);
|
||
positions2.push(start - parentStart);
|
||
return;
|
||
} else if (size == -3) {
|
||
contextHash = id;
|
||
return;
|
||
} else if (size == -4) {
|
||
lookAhead = id;
|
||
return;
|
||
} else {
|
||
throw new RangeError(`Unrecognized record size: ${size}`);
|
||
}
|
||
}
|
||
let type = types[id], node, buffer2;
|
||
let startPos = start - parentStart;
|
||
if (end - start <= maxBufferLength && (buffer2 = findBufferSize(cursor.pos - minPos, inRepeat))) {
|
||
let data2 = new Uint16Array(buffer2.size - buffer2.skip);
|
||
let endPos = cursor.pos - buffer2.size, index = data2.length;
|
||
while (cursor.pos > endPos)
|
||
index = copyToBuffer(buffer2.start, data2, index);
|
||
node = new TreeBuffer(data2, end - buffer2.start, nodeSet2);
|
||
startPos = buffer2.start - parentStart;
|
||
} else {
|
||
let endPos = cursor.pos - size;
|
||
cursor.next();
|
||
let localChildren = [], localPositions = [];
|
||
let localInRepeat = id >= minRepeatType ? id : -1;
|
||
let lastGroup = 0, lastEnd = end;
|
||
while (cursor.pos > endPos) {
|
||
if (localInRepeat >= 0 && cursor.id == localInRepeat && cursor.size >= 0) {
|
||
if (cursor.end <= lastEnd - maxBufferLength) {
|
||
makeRepeatLeaf(localChildren, localPositions, start, lastGroup, cursor.end, lastEnd, localInRepeat, lookAheadAtStart, contextAtStart);
|
||
lastGroup = localChildren.length;
|
||
lastEnd = cursor.end;
|
||
}
|
||
cursor.next();
|
||
} else if (depth > 2500) {
|
||
takeFlatNode(start, endPos, localChildren, localPositions);
|
||
} else {
|
||
takeNode(start, endPos, localChildren, localPositions, localInRepeat, depth + 1);
|
||
}
|
||
}
|
||
if (localInRepeat >= 0 && lastGroup > 0 && lastGroup < localChildren.length)
|
||
makeRepeatLeaf(localChildren, localPositions, start, lastGroup, start, lastEnd, localInRepeat, lookAheadAtStart, contextAtStart);
|
||
localChildren.reverse();
|
||
localPositions.reverse();
|
||
if (localInRepeat > -1 && lastGroup > 0) {
|
||
let make = makeBalanced(type, contextAtStart);
|
||
node = balanceRange(type, localChildren, localPositions, 0, localChildren.length, 0, end - start, make, make);
|
||
} else {
|
||
node = makeTree(type, localChildren, localPositions, end - start, lookAheadAtStart - end, contextAtStart);
|
||
}
|
||
}
|
||
children2.push(node);
|
||
positions2.push(startPos);
|
||
}
|
||
function takeFlatNode(parentStart, minPos, children2, positions2) {
|
||
let nodes = [];
|
||
let nodeCount = 0, stopAt = -1;
|
||
while (cursor.pos > minPos) {
|
||
let { id, start, end, size } = cursor;
|
||
if (size > 4) {
|
||
cursor.next();
|
||
} else if (stopAt > -1 && start < stopAt) {
|
||
break;
|
||
} else {
|
||
if (stopAt < 0)
|
||
stopAt = end - maxBufferLength;
|
||
nodes.push(id, start, end);
|
||
nodeCount++;
|
||
cursor.next();
|
||
}
|
||
}
|
||
if (nodeCount) {
|
||
let buffer2 = new Uint16Array(nodeCount * 4);
|
||
let start = nodes[nodes.length - 2];
|
||
for (let i = nodes.length - 3, j = 0; i >= 0; i -= 3) {
|
||
buffer2[j++] = nodes[i];
|
||
buffer2[j++] = nodes[i + 1] - start;
|
||
buffer2[j++] = nodes[i + 2] - start;
|
||
buffer2[j++] = j;
|
||
}
|
||
children2.push(new TreeBuffer(buffer2, nodes[2] - start, nodeSet2));
|
||
positions2.push(start - parentStart);
|
||
}
|
||
}
|
||
function makeBalanced(type, contextHash2) {
|
||
return (children2, positions2, length2) => {
|
||
let lookAhead2 = 0, lastI = children2.length - 1, last, lookAheadProp;
|
||
if (lastI >= 0 && (last = children2[lastI]) instanceof Tree) {
|
||
if (!lastI && last.type == type && last.length == length2)
|
||
return last;
|
||
if (lookAheadProp = last.prop(NodeProp.lookAhead))
|
||
lookAhead2 = positions2[lastI] + last.length + lookAheadProp;
|
||
}
|
||
return makeTree(type, children2, positions2, length2, lookAhead2, contextHash2);
|
||
};
|
||
}
|
||
function makeRepeatLeaf(children2, positions2, base, i, from, to, type, lookAhead2, contextHash2) {
|
||
let localChildren = [], localPositions = [];
|
||
while (children2.length > i) {
|
||
localChildren.push(children2.pop());
|
||
localPositions.push(positions2.pop() + base - from);
|
||
}
|
||
children2.push(makeTree(nodeSet2.types[type], localChildren, localPositions, to - from, lookAhead2 - to, contextHash2));
|
||
positions2.push(from - base);
|
||
}
|
||
function makeTree(type, children2, positions2, length2, lookAhead2, contextHash2, props) {
|
||
if (contextHash2) {
|
||
let pair = [NodeProp.contextHash, contextHash2];
|
||
props = props ? [pair].concat(props) : [pair];
|
||
}
|
||
if (lookAhead2 > 25) {
|
||
let pair = [NodeProp.lookAhead, lookAhead2];
|
||
props = props ? [pair].concat(props) : [pair];
|
||
}
|
||
return new Tree(type, children2, positions2, length2, props);
|
||
}
|
||
function findBufferSize(maxSize, inRepeat) {
|
||
let fork = cursor.fork();
|
||
let size = 0, start = 0, skip = 0, minStart = fork.end - maxBufferLength;
|
||
let result = { size: 0, start: 0, skip: 0 };
|
||
scan: for (let minPos = fork.pos - maxSize; fork.pos > minPos; ) {
|
||
let nodeSize2 = fork.size;
|
||
if (fork.id == inRepeat && nodeSize2 >= 0) {
|
||
result.size = size;
|
||
result.start = start;
|
||
result.skip = skip;
|
||
skip += 4;
|
||
size += 4;
|
||
fork.next();
|
||
continue;
|
||
}
|
||
let startPos = fork.pos - nodeSize2;
|
||
if (nodeSize2 < 0 || startPos < minPos || fork.start < minStart)
|
||
break;
|
||
let localSkipped = fork.id >= minRepeatType ? 4 : 0;
|
||
let nodeStart = fork.start;
|
||
fork.next();
|
||
while (fork.pos > startPos) {
|
||
if (fork.size < 0) {
|
||
if (fork.size == -3)
|
||
localSkipped += 4;
|
||
else
|
||
break scan;
|
||
} else if (fork.id >= minRepeatType) {
|
||
localSkipped += 4;
|
||
}
|
||
fork.next();
|
||
}
|
||
start = nodeStart;
|
||
size += nodeSize2;
|
||
skip += localSkipped;
|
||
}
|
||
if (inRepeat < 0 || size == maxSize) {
|
||
result.size = size;
|
||
result.start = start;
|
||
result.skip = skip;
|
||
}
|
||
return result.size > 4 ? result : void 0;
|
||
}
|
||
function copyToBuffer(bufferStart, buffer2, index) {
|
||
let { id, start, end, size } = cursor;
|
||
cursor.next();
|
||
if (size >= 0 && id < minRepeatType) {
|
||
let startIndex = index;
|
||
if (size > 4) {
|
||
let endPos = cursor.pos - (size - 4);
|
||
while (cursor.pos > endPos)
|
||
index = copyToBuffer(bufferStart, buffer2, index);
|
||
}
|
||
buffer2[--index] = startIndex;
|
||
buffer2[--index] = end - bufferStart;
|
||
buffer2[--index] = start - bufferStart;
|
||
buffer2[--index] = id;
|
||
} else if (size == -3) {
|
||
contextHash = id;
|
||
} else if (size == -4) {
|
||
lookAhead = id;
|
||
}
|
||
return index;
|
||
}
|
||
let children = [], positions = [];
|
||
while (cursor.pos > 0)
|
||
takeNode(data.start || 0, data.bufferStart || 0, children, positions, -1, 0);
|
||
let length = (_a2 = data.length) !== null && _a2 !== void 0 ? _a2 : children.length ? positions[0] + children[0].length : 0;
|
||
return new Tree(types[data.topID], children.reverse(), positions.reverse(), length);
|
||
}
|
||
var nodeSizeCache = /* @__PURE__ */ new WeakMap();
|
||
function nodeSize(balanceType, node) {
|
||
if (!balanceType.isAnonymous || node instanceof TreeBuffer || node.type != balanceType)
|
||
return 1;
|
||
let size = nodeSizeCache.get(node);
|
||
if (size == null) {
|
||
size = 1;
|
||
for (let child of node.children) {
|
||
if (child.type != balanceType || !(child instanceof Tree)) {
|
||
size = 1;
|
||
break;
|
||
}
|
||
size += nodeSize(balanceType, child);
|
||
}
|
||
nodeSizeCache.set(node, size);
|
||
}
|
||
return size;
|
||
}
|
||
function balanceRange(balanceType, children, positions, from, to, start, length, mkTop, mkTree) {
|
||
let total = 0;
|
||
for (let i = from; i < to; i++)
|
||
total += nodeSize(balanceType, children[i]);
|
||
let maxChild = Math.ceil(
|
||
total * 1.5 / 8
|
||
/* Balance.BranchFactor */
|
||
);
|
||
let localChildren = [], localPositions = [];
|
||
function divide(children2, positions2, from2, to2, offset) {
|
||
for (let i = from2; i < to2; ) {
|
||
let groupFrom = i, groupStart = positions2[i], groupSize = nodeSize(balanceType, children2[i]);
|
||
i++;
|
||
for (; i < to2; i++) {
|
||
let nextSize = nodeSize(balanceType, children2[i]);
|
||
if (groupSize + nextSize >= maxChild)
|
||
break;
|
||
groupSize += nextSize;
|
||
}
|
||
if (i == groupFrom + 1) {
|
||
if (groupSize > maxChild) {
|
||
let only = children2[groupFrom];
|
||
divide(only.children, only.positions, 0, only.children.length, positions2[groupFrom] + offset);
|
||
continue;
|
||
}
|
||
localChildren.push(children2[groupFrom]);
|
||
} else {
|
||
let length2 = positions2[i - 1] + children2[i - 1].length - groupStart;
|
||
localChildren.push(balanceRange(balanceType, children2, positions2, groupFrom, i, groupStart, length2, null, mkTree));
|
||
}
|
||
localPositions.push(groupStart + offset - start);
|
||
}
|
||
}
|
||
divide(children, positions, from, to, 0);
|
||
return (mkTop || mkTree)(localChildren, localPositions, length);
|
||
}
|
||
var TreeFragment = class _TreeFragment {
|
||
/**
|
||
Construct a tree fragment. You'll usually want to use
|
||
[`addTree`](#common.TreeFragment^addTree) and
|
||
[`applyChanges`](#common.TreeFragment^applyChanges) instead of
|
||
calling this directly.
|
||
*/
|
||
constructor(from, to, tree, offset, openStart = false, openEnd = false) {
|
||
this.from = from;
|
||
this.to = to;
|
||
this.tree = tree;
|
||
this.offset = offset;
|
||
this.open = (openStart ? 1 : 0) | (openEnd ? 2 : 0);
|
||
}
|
||
/**
|
||
Whether the start of the fragment represents the start of a
|
||
parse, or the end of a change. (In the second case, it may not
|
||
be safe to reuse some nodes at the start, depending on the
|
||
parsing algorithm.)
|
||
*/
|
||
get openStart() {
|
||
return (this.open & 1) > 0;
|
||
}
|
||
/**
|
||
Whether the end of the fragment represents the end of a
|
||
full-document parse, or the start of a change.
|
||
*/
|
||
get openEnd() {
|
||
return (this.open & 2) > 0;
|
||
}
|
||
/**
|
||
Create a set of fragments from a freshly parsed tree, or update
|
||
an existing set of fragments by replacing the ones that overlap
|
||
with a tree with content from the new tree. When `partial` is
|
||
true, the parse is treated as incomplete, and the resulting
|
||
fragment has [`openEnd`](#common.TreeFragment.openEnd) set to
|
||
true.
|
||
*/
|
||
static addTree(tree, fragments = [], partial = false) {
|
||
let result = [new _TreeFragment(0, tree.length, tree, 0, false, partial)];
|
||
for (let f of fragments)
|
||
if (f.to > tree.length)
|
||
result.push(f);
|
||
return result;
|
||
}
|
||
/**
|
||
Apply a set of edits to an array of fragments, removing or
|
||
splitting fragments as necessary to remove edited ranges, and
|
||
adjusting offsets for fragments that moved.
|
||
*/
|
||
static applyChanges(fragments, changes, minGap = 128) {
|
||
if (!changes.length)
|
||
return fragments;
|
||
let result = [];
|
||
let fI = 1, nextF = fragments.length ? fragments[0] : null;
|
||
for (let cI = 0, pos = 0, off = 0; ; cI++) {
|
||
let nextC = cI < changes.length ? changes[cI] : null;
|
||
let nextPos = nextC ? nextC.fromA : 1e9;
|
||
if (nextPos - pos >= minGap)
|
||
while (nextF && nextF.from < nextPos) {
|
||
let cut = nextF;
|
||
if (pos >= cut.from || nextPos <= cut.to || off) {
|
||
let fFrom = Math.max(cut.from, pos) - off, fTo = Math.min(cut.to, nextPos) - off;
|
||
cut = fFrom >= fTo ? null : new _TreeFragment(fFrom, fTo, cut.tree, cut.offset + off, cI > 0, !!nextC);
|
||
}
|
||
if (cut)
|
||
result.push(cut);
|
||
if (nextF.to > nextPos)
|
||
break;
|
||
nextF = fI < fragments.length ? fragments[fI++] : null;
|
||
}
|
||
if (!nextC)
|
||
break;
|
||
pos = nextC.toA;
|
||
off = nextC.toA - nextC.toB;
|
||
}
|
||
return result;
|
||
}
|
||
};
|
||
var Parser = class {
|
||
/**
|
||
Start a parse, returning a [partial parse](#common.PartialParse)
|
||
object. [`fragments`](#common.TreeFragment) can be passed in to
|
||
make the parse incremental.
|
||
|
||
By default, the entire input is parsed. You can pass `ranges`,
|
||
which should be a sorted array of non-empty, non-overlapping
|
||
ranges, to parse only those ranges. The tree returned in that
|
||
case will start at `ranges[0].from`.
|
||
*/
|
||
startParse(input, fragments, ranges) {
|
||
if (typeof input == "string")
|
||
input = new StringInput(input);
|
||
ranges = !ranges ? [new Range(0, input.length)] : ranges.length ? ranges.map((r) => new Range(r.from, r.to)) : [new Range(0, 0)];
|
||
return this.createParse(input, fragments || [], ranges);
|
||
}
|
||
/**
|
||
Run a full parse, returning the resulting tree.
|
||
*/
|
||
parse(input, fragments, ranges) {
|
||
let parse = this.startParse(input, fragments, ranges);
|
||
for (; ; ) {
|
||
let done = parse.advance();
|
||
if (done)
|
||
return done;
|
||
}
|
||
}
|
||
};
|
||
var StringInput = class {
|
||
constructor(string2) {
|
||
this.string = string2;
|
||
}
|
||
get length() {
|
||
return this.string.length;
|
||
}
|
||
chunk(from) {
|
||
return this.string.slice(from);
|
||
}
|
||
get lineChunks() {
|
||
return false;
|
||
}
|
||
read(from, to) {
|
||
return this.string.slice(from, to);
|
||
}
|
||
};
|
||
var stoppedInner = new NodeProp({ perNode: true });
|
||
|
||
// node_modules/@lezer/highlight/dist/index.js
|
||
var nextTagID = 0;
|
||
var Tag = class _Tag {
|
||
/**
|
||
@internal
|
||
*/
|
||
constructor(name2, set, base, modified) {
|
||
this.name = name2;
|
||
this.set = set;
|
||
this.base = base;
|
||
this.modified = modified;
|
||
this.id = nextTagID++;
|
||
}
|
||
toString() {
|
||
let { name: name2 } = this;
|
||
for (let mod of this.modified)
|
||
if (mod.name)
|
||
name2 = `${mod.name}(${name2})`;
|
||
return name2;
|
||
}
|
||
static define(nameOrParent, parent) {
|
||
let name2 = typeof nameOrParent == "string" ? nameOrParent : "?";
|
||
if (nameOrParent instanceof _Tag)
|
||
parent = nameOrParent;
|
||
if (parent === null || parent === void 0 ? void 0 : parent.base)
|
||
throw new Error("Can not derive from a modified tag");
|
||
let tag = new _Tag(name2, [], null, []);
|
||
tag.set.push(tag);
|
||
if (parent)
|
||
for (let t2 of parent.set)
|
||
tag.set.push(t2);
|
||
return tag;
|
||
}
|
||
/**
|
||
Define a tag _modifier_, which is a function that, given a tag,
|
||
will return a tag that is a subtag of the original. Applying the
|
||
same modifier to a twice tag will return the same value (`m1(t1)
|
||
== m1(t1)`) and applying multiple modifiers will, regardless or
|
||
order, produce the same tag (`m1(m2(t1)) == m2(m1(t1))`).
|
||
|
||
When multiple modifiers are applied to a given base tag, each
|
||
smaller set of modifiers is registered as a parent, so that for
|
||
example `m1(m2(m3(t1)))` is a subtype of `m1(m2(t1))`,
|
||
`m1(m3(t1)`, and so on.
|
||
*/
|
||
static defineModifier(name2) {
|
||
let mod = new Modifier(name2);
|
||
return (tag) => {
|
||
if (tag.modified.indexOf(mod) > -1)
|
||
return tag;
|
||
return Modifier.get(tag.base || tag, tag.modified.concat(mod).sort((a, b) => a.id - b.id));
|
||
};
|
||
}
|
||
};
|
||
var nextModifierID = 0;
|
||
var Modifier = class _Modifier {
|
||
constructor(name2) {
|
||
this.name = name2;
|
||
this.instances = [];
|
||
this.id = nextModifierID++;
|
||
}
|
||
static get(base, mods) {
|
||
if (!mods.length)
|
||
return base;
|
||
let exists = mods[0].instances.find((t2) => t2.base == base && sameArray(mods, t2.modified));
|
||
if (exists)
|
||
return exists;
|
||
let set = [], tag = new Tag(base.name, set, base, mods);
|
||
for (let m of mods)
|
||
m.instances.push(tag);
|
||
let configs = powerSet(mods);
|
||
for (let parent of base.set)
|
||
if (!parent.modified.length)
|
||
for (let config of configs)
|
||
set.push(_Modifier.get(parent, config));
|
||
return tag;
|
||
}
|
||
};
|
||
function sameArray(a, b) {
|
||
return a.length == b.length && a.every((x, i) => x == b[i]);
|
||
}
|
||
function powerSet(array) {
|
||
let sets = [[]];
|
||
for (let i = 0; i < array.length; i++) {
|
||
for (let j = 0, e = sets.length; j < e; j++) {
|
||
sets.push(sets[j].concat(array[i]));
|
||
}
|
||
}
|
||
return sets.sort((a, b) => b.length - a.length);
|
||
}
|
||
function styleTags(spec) {
|
||
let byName = /* @__PURE__ */ Object.create(null);
|
||
for (let prop in spec) {
|
||
let tags2 = spec[prop];
|
||
if (!Array.isArray(tags2))
|
||
tags2 = [tags2];
|
||
for (let part of prop.split(" "))
|
||
if (part) {
|
||
let pieces = [], mode = 2, rest = part;
|
||
for (let pos = 0; ; ) {
|
||
if (rest == "..." && pos > 0 && pos + 3 == part.length) {
|
||
mode = 1;
|
||
break;
|
||
}
|
||
let m = /^"(?:[^"\\]|\\.)*?"|[^\/!]+/.exec(rest);
|
||
if (!m)
|
||
throw new RangeError("Invalid path: " + part);
|
||
pieces.push(m[0] == "*" ? "" : m[0][0] == '"' ? JSON.parse(m[0]) : m[0]);
|
||
pos += m[0].length;
|
||
if (pos == part.length)
|
||
break;
|
||
let next = part[pos++];
|
||
if (pos == part.length && next == "!") {
|
||
mode = 0;
|
||
break;
|
||
}
|
||
if (next != "/")
|
||
throw new RangeError("Invalid path: " + part);
|
||
rest = part.slice(pos);
|
||
}
|
||
let last = pieces.length - 1, inner = pieces[last];
|
||
if (!inner)
|
||
throw new RangeError("Invalid path: " + part);
|
||
let rule = new Rule(tags2, mode, last > 0 ? pieces.slice(0, last) : null);
|
||
byName[inner] = rule.sort(byName[inner]);
|
||
}
|
||
}
|
||
return ruleNodeProp.add(byName);
|
||
}
|
||
var ruleNodeProp = new NodeProp();
|
||
var Rule = class {
|
||
constructor(tags2, mode, context, next) {
|
||
this.tags = tags2;
|
||
this.mode = mode;
|
||
this.context = context;
|
||
this.next = next;
|
||
}
|
||
get opaque() {
|
||
return this.mode == 0;
|
||
}
|
||
get inherit() {
|
||
return this.mode == 1;
|
||
}
|
||
sort(other) {
|
||
if (!other || other.depth < this.depth) {
|
||
this.next = other;
|
||
return this;
|
||
}
|
||
other.next = this.sort(other.next);
|
||
return other;
|
||
}
|
||
get depth() {
|
||
return this.context ? this.context.length : 0;
|
||
}
|
||
};
|
||
Rule.empty = new Rule([], 2, null);
|
||
function tagHighlighter(tags2, options) {
|
||
let map = /* @__PURE__ */ Object.create(null);
|
||
for (let style of tags2) {
|
||
if (!Array.isArray(style.tag))
|
||
map[style.tag.id] = style.class;
|
||
else
|
||
for (let tag of style.tag)
|
||
map[tag.id] = style.class;
|
||
}
|
||
let { scope, all = null } = options || {};
|
||
return {
|
||
style: (tags3) => {
|
||
let cls = all;
|
||
for (let tag of tags3) {
|
||
for (let sub of tag.set) {
|
||
let tagClass = map[sub.id];
|
||
if (tagClass) {
|
||
cls = cls ? cls + " " + tagClass : tagClass;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
return cls;
|
||
},
|
||
scope
|
||
};
|
||
}
|
||
function highlightTags(highlighters, tags2) {
|
||
let result = null;
|
||
for (let highlighter of highlighters) {
|
||
let value = highlighter.style(tags2);
|
||
if (value)
|
||
result = result ? result + " " + value : value;
|
||
}
|
||
return result;
|
||
}
|
||
function highlightTree(tree, highlighter, putStyle, from = 0, to = tree.length) {
|
||
let builder = new HighlightBuilder(from, Array.isArray(highlighter) ? highlighter : [highlighter], putStyle);
|
||
builder.highlightRange(tree.cursor(), from, to, "", builder.highlighters);
|
||
builder.flush(to);
|
||
}
|
||
var HighlightBuilder = class {
|
||
constructor(at, highlighters, span) {
|
||
this.at = at;
|
||
this.highlighters = highlighters;
|
||
this.span = span;
|
||
this.class = "";
|
||
}
|
||
startSpan(at, cls) {
|
||
if (cls != this.class) {
|
||
this.flush(at);
|
||
if (at > this.at)
|
||
this.at = at;
|
||
this.class = cls;
|
||
}
|
||
}
|
||
flush(to) {
|
||
if (to > this.at && this.class)
|
||
this.span(this.at, to, this.class);
|
||
}
|
||
highlightRange(cursor, from, to, inheritedClass, highlighters) {
|
||
let { type, from: start, to: end } = cursor;
|
||
if (start >= to || end <= from)
|
||
return;
|
||
if (type.isTop)
|
||
highlighters = this.highlighters.filter((h) => !h.scope || h.scope(type));
|
||
let cls = inheritedClass;
|
||
let rule = getStyleTags(cursor) || Rule.empty;
|
||
let tagCls = highlightTags(highlighters, rule.tags);
|
||
if (tagCls) {
|
||
if (cls)
|
||
cls += " ";
|
||
cls += tagCls;
|
||
if (rule.mode == 1)
|
||
inheritedClass += (inheritedClass ? " " : "") + tagCls;
|
||
}
|
||
this.startSpan(Math.max(from, start), cls);
|
||
if (rule.opaque)
|
||
return;
|
||
let mounted = cursor.tree && cursor.tree.prop(NodeProp.mounted);
|
||
if (mounted && mounted.overlay) {
|
||
let inner = cursor.node.enter(mounted.overlay[0].from + start, 1);
|
||
let innerHighlighters = this.highlighters.filter((h) => !h.scope || h.scope(mounted.tree.type));
|
||
let hasChild2 = cursor.firstChild();
|
||
for (let i = 0, pos = start; ; i++) {
|
||
let next = i < mounted.overlay.length ? mounted.overlay[i] : null;
|
||
let nextPos = next ? next.from + start : end;
|
||
let rangeFrom = Math.max(from, pos), rangeTo = Math.min(to, nextPos);
|
||
if (rangeFrom < rangeTo && hasChild2) {
|
||
while (cursor.from < rangeTo) {
|
||
this.highlightRange(cursor, rangeFrom, rangeTo, inheritedClass, highlighters);
|
||
this.startSpan(Math.min(rangeTo, cursor.to), cls);
|
||
if (cursor.to >= nextPos || !cursor.nextSibling())
|
||
break;
|
||
}
|
||
}
|
||
if (!next || nextPos > to)
|
||
break;
|
||
pos = next.to + start;
|
||
if (pos > from) {
|
||
this.highlightRange(inner.cursor(), Math.max(from, next.from + start), Math.min(to, pos), "", innerHighlighters);
|
||
this.startSpan(Math.min(to, pos), cls);
|
||
}
|
||
}
|
||
if (hasChild2)
|
||
cursor.parent();
|
||
} else if (cursor.firstChild()) {
|
||
if (mounted)
|
||
inheritedClass = "";
|
||
do {
|
||
if (cursor.to <= from)
|
||
continue;
|
||
if (cursor.from >= to)
|
||
break;
|
||
this.highlightRange(cursor, from, to, inheritedClass, highlighters);
|
||
this.startSpan(Math.min(to, cursor.to), cls);
|
||
} while (cursor.nextSibling());
|
||
cursor.parent();
|
||
}
|
||
}
|
||
};
|
||
function getStyleTags(node) {
|
||
let rule = node.type.prop(ruleNodeProp);
|
||
while (rule && rule.context && !node.matchContext(rule.context))
|
||
rule = rule.next;
|
||
return rule || null;
|
||
}
|
||
var t = Tag.define;
|
||
var comment = t();
|
||
var name = t();
|
||
var typeName = t(name);
|
||
var propertyName = t(name);
|
||
var literal = t();
|
||
var string = t(literal);
|
||
var number = t(literal);
|
||
var content = t();
|
||
var heading = t(content);
|
||
var keyword = t();
|
||
var operator = t();
|
||
var punctuation = t();
|
||
var bracket = t(punctuation);
|
||
var meta = t();
|
||
var tags = {
|
||
/**
|
||
A comment.
|
||
*/
|
||
comment,
|
||
/**
|
||
A line [comment](#highlight.tags.comment).
|
||
*/
|
||
lineComment: t(comment),
|
||
/**
|
||
A block [comment](#highlight.tags.comment).
|
||
*/
|
||
blockComment: t(comment),
|
||
/**
|
||
A documentation [comment](#highlight.tags.comment).
|
||
*/
|
||
docComment: t(comment),
|
||
/**
|
||
Any kind of identifier.
|
||
*/
|
||
name,
|
||
/**
|
||
The [name](#highlight.tags.name) of a variable.
|
||
*/
|
||
variableName: t(name),
|
||
/**
|
||
A type [name](#highlight.tags.name).
|
||
*/
|
||
typeName,
|
||
/**
|
||
A tag name (subtag of [`typeName`](#highlight.tags.typeName)).
|
||
*/
|
||
tagName: t(typeName),
|
||
/**
|
||
A property or field [name](#highlight.tags.name).
|
||
*/
|
||
propertyName,
|
||
/**
|
||
An attribute name (subtag of [`propertyName`](#highlight.tags.propertyName)).
|
||
*/
|
||
attributeName: t(propertyName),
|
||
/**
|
||
The [name](#highlight.tags.name) of a class.
|
||
*/
|
||
className: t(name),
|
||
/**
|
||
A label [name](#highlight.tags.name).
|
||
*/
|
||
labelName: t(name),
|
||
/**
|
||
A namespace [name](#highlight.tags.name).
|
||
*/
|
||
namespace: t(name),
|
||
/**
|
||
The [name](#highlight.tags.name) of a macro.
|
||
*/
|
||
macroName: t(name),
|
||
/**
|
||
A literal value.
|
||
*/
|
||
literal,
|
||
/**
|
||
A string [literal](#highlight.tags.literal).
|
||
*/
|
||
string,
|
||
/**
|
||
A documentation [string](#highlight.tags.string).
|
||
*/
|
||
docString: t(string),
|
||
/**
|
||
A character literal (subtag of [string](#highlight.tags.string)).
|
||
*/
|
||
character: t(string),
|
||
/**
|
||
An attribute value (subtag of [string](#highlight.tags.string)).
|
||
*/
|
||
attributeValue: t(string),
|
||
/**
|
||
A number [literal](#highlight.tags.literal).
|
||
*/
|
||
number,
|
||
/**
|
||
An integer [number](#highlight.tags.number) literal.
|
||
*/
|
||
integer: t(number),
|
||
/**
|
||
A floating-point [number](#highlight.tags.number) literal.
|
||
*/
|
||
float: t(number),
|
||
/**
|
||
A boolean [literal](#highlight.tags.literal).
|
||
*/
|
||
bool: t(literal),
|
||
/**
|
||
Regular expression [literal](#highlight.tags.literal).
|
||
*/
|
||
regexp: t(literal),
|
||
/**
|
||
An escape [literal](#highlight.tags.literal), for example a
|
||
backslash escape in a string.
|
||
*/
|
||
escape: t(literal),
|
||
/**
|
||
A color [literal](#highlight.tags.literal).
|
||
*/
|
||
color: t(literal),
|
||
/**
|
||
A URL [literal](#highlight.tags.literal).
|
||
*/
|
||
url: t(literal),
|
||
/**
|
||
A language keyword.
|
||
*/
|
||
keyword,
|
||
/**
|
||
The [keyword](#highlight.tags.keyword) for the self or this
|
||
object.
|
||
*/
|
||
self: t(keyword),
|
||
/**
|
||
The [keyword](#highlight.tags.keyword) for null.
|
||
*/
|
||
null: t(keyword),
|
||
/**
|
||
A [keyword](#highlight.tags.keyword) denoting some atomic value.
|
||
*/
|
||
atom: t(keyword),
|
||
/**
|
||
A [keyword](#highlight.tags.keyword) that represents a unit.
|
||
*/
|
||
unit: t(keyword),
|
||
/**
|
||
A modifier [keyword](#highlight.tags.keyword).
|
||
*/
|
||
modifier: t(keyword),
|
||
/**
|
||
A [keyword](#highlight.tags.keyword) that acts as an operator.
|
||
*/
|
||
operatorKeyword: t(keyword),
|
||
/**
|
||
A control-flow related [keyword](#highlight.tags.keyword).
|
||
*/
|
||
controlKeyword: t(keyword),
|
||
/**
|
||
A [keyword](#highlight.tags.keyword) that defines something.
|
||
*/
|
||
definitionKeyword: t(keyword),
|
||
/**
|
||
A [keyword](#highlight.tags.keyword) related to defining or
|
||
interfacing with modules.
|
||
*/
|
||
moduleKeyword: t(keyword),
|
||
/**
|
||
An operator.
|
||
*/
|
||
operator,
|
||
/**
|
||
An [operator](#highlight.tags.operator) that dereferences something.
|
||
*/
|
||
derefOperator: t(operator),
|
||
/**
|
||
Arithmetic-related [operator](#highlight.tags.operator).
|
||
*/
|
||
arithmeticOperator: t(operator),
|
||
/**
|
||
Logical [operator](#highlight.tags.operator).
|
||
*/
|
||
logicOperator: t(operator),
|
||
/**
|
||
Bit [operator](#highlight.tags.operator).
|
||
*/
|
||
bitwiseOperator: t(operator),
|
||
/**
|
||
Comparison [operator](#highlight.tags.operator).
|
||
*/
|
||
compareOperator: t(operator),
|
||
/**
|
||
[Operator](#highlight.tags.operator) that updates its operand.
|
||
*/
|
||
updateOperator: t(operator),
|
||
/**
|
||
[Operator](#highlight.tags.operator) that defines something.
|
||
*/
|
||
definitionOperator: t(operator),
|
||
/**
|
||
Type-related [operator](#highlight.tags.operator).
|
||
*/
|
||
typeOperator: t(operator),
|
||
/**
|
||
Control-flow [operator](#highlight.tags.operator).
|
||
*/
|
||
controlOperator: t(operator),
|
||
/**
|
||
Program or markup punctuation.
|
||
*/
|
||
punctuation,
|
||
/**
|
||
[Punctuation](#highlight.tags.punctuation) that separates
|
||
things.
|
||
*/
|
||
separator: t(punctuation),
|
||
/**
|
||
Bracket-style [punctuation](#highlight.tags.punctuation).
|
||
*/
|
||
bracket,
|
||
/**
|
||
Angle [brackets](#highlight.tags.bracket) (usually `<` and `>`
|
||
tokens).
|
||
*/
|
||
angleBracket: t(bracket),
|
||
/**
|
||
Square [brackets](#highlight.tags.bracket) (usually `[` and `]`
|
||
tokens).
|
||
*/
|
||
squareBracket: t(bracket),
|
||
/**
|
||
Parentheses (usually `(` and `)` tokens). Subtag of
|
||
[bracket](#highlight.tags.bracket).
|
||
*/
|
||
paren: t(bracket),
|
||
/**
|
||
Braces (usually `{` and `}` tokens). Subtag of
|
||
[bracket](#highlight.tags.bracket).
|
||
*/
|
||
brace: t(bracket),
|
||
/**
|
||
Content, for example plain text in XML or markup documents.
|
||
*/
|
||
content,
|
||
/**
|
||
[Content](#highlight.tags.content) that represents a heading.
|
||
*/
|
||
heading,
|
||
/**
|
||
A level 1 [heading](#highlight.tags.heading).
|
||
*/
|
||
heading1: t(heading),
|
||
/**
|
||
A level 2 [heading](#highlight.tags.heading).
|
||
*/
|
||
heading2: t(heading),
|
||
/**
|
||
A level 3 [heading](#highlight.tags.heading).
|
||
*/
|
||
heading3: t(heading),
|
||
/**
|
||
A level 4 [heading](#highlight.tags.heading).
|
||
*/
|
||
heading4: t(heading),
|
||
/**
|
||
A level 5 [heading](#highlight.tags.heading).
|
||
*/
|
||
heading5: t(heading),
|
||
/**
|
||
A level 6 [heading](#highlight.tags.heading).
|
||
*/
|
||
heading6: t(heading),
|
||
/**
|
||
A prose [content](#highlight.tags.content) separator (such as a horizontal rule).
|
||
*/
|
||
contentSeparator: t(content),
|
||
/**
|
||
[Content](#highlight.tags.content) that represents a list.
|
||
*/
|
||
list: t(content),
|
||
/**
|
||
[Content](#highlight.tags.content) that represents a quote.
|
||
*/
|
||
quote: t(content),
|
||
/**
|
||
[Content](#highlight.tags.content) that is emphasized.
|
||
*/
|
||
emphasis: t(content),
|
||
/**
|
||
[Content](#highlight.tags.content) that is styled strong.
|
||
*/
|
||
strong: t(content),
|
||
/**
|
||
[Content](#highlight.tags.content) that is part of a link.
|
||
*/
|
||
link: t(content),
|
||
/**
|
||
[Content](#highlight.tags.content) that is styled as code or
|
||
monospace.
|
||
*/
|
||
monospace: t(content),
|
||
/**
|
||
[Content](#highlight.tags.content) that has a strike-through
|
||
style.
|
||
*/
|
||
strikethrough: t(content),
|
||
/**
|
||
Inserted text in a change-tracking format.
|
||
*/
|
||
inserted: t(),
|
||
/**
|
||
Deleted text.
|
||
*/
|
||
deleted: t(),
|
||
/**
|
||
Changed text.
|
||
*/
|
||
changed: t(),
|
||
/**
|
||
An invalid or unsyntactic element.
|
||
*/
|
||
invalid: t(),
|
||
/**
|
||
Metadata or meta-instruction.
|
||
*/
|
||
meta,
|
||
/**
|
||
[Metadata](#highlight.tags.meta) that applies to the entire
|
||
document.
|
||
*/
|
||
documentMeta: t(meta),
|
||
/**
|
||
[Metadata](#highlight.tags.meta) that annotates or adds
|
||
attributes to a given syntactic element.
|
||
*/
|
||
annotation: t(meta),
|
||
/**
|
||
Processing instruction or preprocessor directive. Subtag of
|
||
[meta](#highlight.tags.meta).
|
||
*/
|
||
processingInstruction: t(meta),
|
||
/**
|
||
[Modifier](#highlight.Tag^defineModifier) that indicates that a
|
||
given element is being defined. Expected to be used with the
|
||
various [name](#highlight.tags.name) tags.
|
||
*/
|
||
definition: Tag.defineModifier("definition"),
|
||
/**
|
||
[Modifier](#highlight.Tag^defineModifier) that indicates that
|
||
something is constant. Mostly expected to be used with
|
||
[variable names](#highlight.tags.variableName).
|
||
*/
|
||
constant: Tag.defineModifier("constant"),
|
||
/**
|
||
[Modifier](#highlight.Tag^defineModifier) used to indicate that
|
||
a [variable](#highlight.tags.variableName) or [property
|
||
name](#highlight.tags.propertyName) is being called or defined
|
||
as a function.
|
||
*/
|
||
function: Tag.defineModifier("function"),
|
||
/**
|
||
[Modifier](#highlight.Tag^defineModifier) that can be applied to
|
||
[names](#highlight.tags.name) to indicate that they belong to
|
||
the language's standard environment.
|
||
*/
|
||
standard: Tag.defineModifier("standard"),
|
||
/**
|
||
[Modifier](#highlight.Tag^defineModifier) that indicates a given
|
||
[names](#highlight.tags.name) is local to some scope.
|
||
*/
|
||
local: Tag.defineModifier("local"),
|
||
/**
|
||
A generic variant [modifier](#highlight.Tag^defineModifier) that
|
||
can be used to tag language-specific alternative variants of
|
||
some common tag. It is recommended for themes to define special
|
||
forms of at least the [string](#highlight.tags.string) and
|
||
[variable name](#highlight.tags.variableName) tags, since those
|
||
come up a lot.
|
||
*/
|
||
special: Tag.defineModifier("special")
|
||
};
|
||
for (let name2 in tags) {
|
||
let val = tags[name2];
|
||
if (val instanceof Tag)
|
||
val.name = name2;
|
||
}
|
||
var classHighlighter = tagHighlighter([
|
||
{ tag: tags.link, class: "tok-link" },
|
||
{ tag: tags.heading, class: "tok-heading" },
|
||
{ tag: tags.emphasis, class: "tok-emphasis" },
|
||
{ tag: tags.strong, class: "tok-strong" },
|
||
{ tag: tags.keyword, class: "tok-keyword" },
|
||
{ tag: tags.atom, class: "tok-atom" },
|
||
{ tag: tags.bool, class: "tok-bool" },
|
||
{ tag: tags.url, class: "tok-url" },
|
||
{ tag: tags.labelName, class: "tok-labelName" },
|
||
{ tag: tags.inserted, class: "tok-inserted" },
|
||
{ tag: tags.deleted, class: "tok-deleted" },
|
||
{ tag: tags.literal, class: "tok-literal" },
|
||
{ tag: tags.string, class: "tok-string" },
|
||
{ tag: tags.number, class: "tok-number" },
|
||
{ tag: [tags.regexp, tags.escape, tags.special(tags.string)], class: "tok-string2" },
|
||
{ tag: tags.variableName, class: "tok-variableName" },
|
||
{ tag: tags.local(tags.variableName), class: "tok-variableName tok-local" },
|
||
{ tag: tags.definition(tags.variableName), class: "tok-variableName tok-definition" },
|
||
{ tag: tags.special(tags.variableName), class: "tok-variableName2" },
|
||
{ tag: tags.definition(tags.propertyName), class: "tok-propertyName tok-definition" },
|
||
{ tag: tags.typeName, class: "tok-typeName" },
|
||
{ tag: tags.namespace, class: "tok-namespace" },
|
||
{ tag: tags.className, class: "tok-className" },
|
||
{ tag: tags.macroName, class: "tok-macroName" },
|
||
{ tag: tags.propertyName, class: "tok-propertyName" },
|
||
{ tag: tags.operator, class: "tok-operator" },
|
||
{ tag: tags.comment, class: "tok-comment" },
|
||
{ tag: tags.meta, class: "tok-meta" },
|
||
{ tag: tags.invalid, class: "tok-invalid" },
|
||
{ tag: tags.punctuation, class: "tok-punctuation" }
|
||
]);
|
||
|
||
// node_modules/@codemirror/language/dist/index.js
|
||
var _a;
|
||
var languageDataProp = new NodeProp();
|
||
function defineLanguageFacet(baseData) {
|
||
return Facet.define({
|
||
combine: baseData ? (values) => values.concat(baseData) : void 0
|
||
});
|
||
}
|
||
var sublanguageProp = new NodeProp();
|
||
var Language = class {
|
||
/**
|
||
Construct a language object. If you need to invoke this
|
||
directly, first define a data facet with
|
||
[`defineLanguageFacet`](https://codemirror.net/6/docs/ref/#language.defineLanguageFacet), and then
|
||
configure your parser to [attach](https://codemirror.net/6/docs/ref/#language.languageDataProp) it
|
||
to the language's outer syntax node.
|
||
*/
|
||
constructor(data, parser, extraExtensions = [], name2 = "") {
|
||
this.data = data;
|
||
this.name = name2;
|
||
if (!EditorState.prototype.hasOwnProperty("tree"))
|
||
Object.defineProperty(EditorState.prototype, "tree", { get() {
|
||
return syntaxTree(this);
|
||
} });
|
||
this.parser = parser;
|
||
this.extension = [
|
||
language.of(this),
|
||
EditorState.languageData.of((state, pos, side) => {
|
||
let top = topNodeAt(state, pos, side), data2 = top.type.prop(languageDataProp);
|
||
if (!data2)
|
||
return [];
|
||
let base = state.facet(data2), sub = top.type.prop(sublanguageProp);
|
||
if (sub) {
|
||
let innerNode = top.resolve(pos - top.from, side);
|
||
for (let sublang of sub)
|
||
if (sublang.test(innerNode, state)) {
|
||
let data3 = state.facet(sublang.facet);
|
||
return sublang.type == "replace" ? data3 : data3.concat(base);
|
||
}
|
||
}
|
||
return base;
|
||
})
|
||
].concat(extraExtensions);
|
||
}
|
||
/**
|
||
Query whether this language is active at the given position.
|
||
*/
|
||
isActiveAt(state, pos, side = -1) {
|
||
return topNodeAt(state, pos, side).type.prop(languageDataProp) == this.data;
|
||
}
|
||
/**
|
||
Find the document regions that were parsed using this language.
|
||
The returned regions will _include_ any nested languages rooted
|
||
in this language, when those exist.
|
||
*/
|
||
findRegions(state) {
|
||
let lang = state.facet(language);
|
||
if ((lang === null || lang === void 0 ? void 0 : lang.data) == this.data)
|
||
return [{ from: 0, to: state.doc.length }];
|
||
if (!lang || !lang.allowsNesting)
|
||
return [];
|
||
let result = [];
|
||
let explore = (tree, from) => {
|
||
if (tree.prop(languageDataProp) == this.data) {
|
||
result.push({ from, to: from + tree.length });
|
||
return;
|
||
}
|
||
let mount = tree.prop(NodeProp.mounted);
|
||
if (mount) {
|
||
if (mount.tree.prop(languageDataProp) == this.data) {
|
||
if (mount.overlay)
|
||
for (let r of mount.overlay)
|
||
result.push({ from: r.from + from, to: r.to + from });
|
||
else
|
||
result.push({ from, to: from + tree.length });
|
||
return;
|
||
} else if (mount.overlay) {
|
||
let size = result.length;
|
||
explore(mount.tree, mount.overlay[0].from + from);
|
||
if (result.length > size)
|
||
return;
|
||
}
|
||
}
|
||
for (let i = 0; i < tree.children.length; i++) {
|
||
let ch = tree.children[i];
|
||
if (ch instanceof Tree)
|
||
explore(ch, tree.positions[i] + from);
|
||
}
|
||
};
|
||
explore(syntaxTree(state), 0);
|
||
return result;
|
||
}
|
||
/**
|
||
Indicates whether this language allows nested languages. The
|
||
default implementation returns true.
|
||
*/
|
||
get allowsNesting() {
|
||
return true;
|
||
}
|
||
};
|
||
Language.setState = StateEffect.define();
|
||
function topNodeAt(state, pos, side) {
|
||
let topLang = state.facet(language), tree = syntaxTree(state).topNode;
|
||
if (!topLang || topLang.allowsNesting) {
|
||
for (let node = tree; node; node = node.enter(pos, side, IterMode.ExcludeBuffers))
|
||
if (node.type.isTop)
|
||
tree = node;
|
||
}
|
||
return tree;
|
||
}
|
||
var LRLanguage = class _LRLanguage extends Language {
|
||
constructor(data, parser, name2) {
|
||
super(data, parser, [], name2);
|
||
this.parser = parser;
|
||
}
|
||
/**
|
||
Define a language from a parser.
|
||
*/
|
||
static define(spec) {
|
||
let data = defineLanguageFacet(spec.languageData);
|
||
return new _LRLanguage(data, spec.parser.configure({
|
||
props: [languageDataProp.add((type) => type.isTop ? data : void 0)]
|
||
}), spec.name);
|
||
}
|
||
/**
|
||
Create a new instance of this language with a reconfigured
|
||
version of its parser and optionally a new name.
|
||
*/
|
||
configure(options, name2) {
|
||
return new _LRLanguage(this.data, this.parser.configure(options), name2 || this.name);
|
||
}
|
||
get allowsNesting() {
|
||
return this.parser.hasWrappers();
|
||
}
|
||
};
|
||
function syntaxTree(state) {
|
||
let field = state.field(Language.state, false);
|
||
return field ? field.tree : Tree.empty;
|
||
}
|
||
var DocInput = class {
|
||
/**
|
||
Create an input object for the given document.
|
||
*/
|
||
constructor(doc) {
|
||
this.doc = doc;
|
||
this.cursorPos = 0;
|
||
this.string = "";
|
||
this.cursor = doc.iter();
|
||
}
|
||
get length() {
|
||
return this.doc.length;
|
||
}
|
||
syncTo(pos) {
|
||
this.string = this.cursor.next(pos - this.cursorPos).value;
|
||
this.cursorPos = pos + this.string.length;
|
||
return this.cursorPos - this.string.length;
|
||
}
|
||
chunk(pos) {
|
||
this.syncTo(pos);
|
||
return this.string;
|
||
}
|
||
get lineChunks() {
|
||
return true;
|
||
}
|
||
read(from, to) {
|
||
let stringStart = this.cursorPos - this.string.length;
|
||
if (from < stringStart || to >= this.cursorPos)
|
||
return this.doc.sliceString(from, to);
|
||
else
|
||
return this.string.slice(from - stringStart, to - stringStart);
|
||
}
|
||
};
|
||
var currentContext = null;
|
||
var ParseContext = class _ParseContext {
|
||
constructor(parser, state, fragments = [], tree, treeLen, viewport, skipped, scheduleOn) {
|
||
this.parser = parser;
|
||
this.state = state;
|
||
this.fragments = fragments;
|
||
this.tree = tree;
|
||
this.treeLen = treeLen;
|
||
this.viewport = viewport;
|
||
this.skipped = skipped;
|
||
this.scheduleOn = scheduleOn;
|
||
this.parse = null;
|
||
this.tempSkipped = [];
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
static create(parser, state, viewport) {
|
||
return new _ParseContext(parser, state, [], Tree.empty, 0, viewport, [], null);
|
||
}
|
||
startParse() {
|
||
return this.parser.startParse(new DocInput(this.state.doc), this.fragments);
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
work(until, upto) {
|
||
if (upto != null && upto >= this.state.doc.length)
|
||
upto = void 0;
|
||
if (this.tree != Tree.empty && this.isDone(upto !== null && upto !== void 0 ? upto : this.state.doc.length)) {
|
||
this.takeTree();
|
||
return true;
|
||
}
|
||
return this.withContext(() => {
|
||
var _a2;
|
||
if (typeof until == "number") {
|
||
let endTime = Date.now() + until;
|
||
until = () => Date.now() > endTime;
|
||
}
|
||
if (!this.parse)
|
||
this.parse = this.startParse();
|
||
if (upto != null && (this.parse.stoppedAt == null || this.parse.stoppedAt > upto) && upto < this.state.doc.length)
|
||
this.parse.stopAt(upto);
|
||
for (; ; ) {
|
||
let done = this.parse.advance();
|
||
if (done) {
|
||
this.fragments = this.withoutTempSkipped(TreeFragment.addTree(done, this.fragments, this.parse.stoppedAt != null));
|
||
this.treeLen = (_a2 = this.parse.stoppedAt) !== null && _a2 !== void 0 ? _a2 : this.state.doc.length;
|
||
this.tree = done;
|
||
this.parse = null;
|
||
if (this.treeLen < (upto !== null && upto !== void 0 ? upto : this.state.doc.length))
|
||
this.parse = this.startParse();
|
||
else
|
||
return true;
|
||
}
|
||
if (until())
|
||
return false;
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
takeTree() {
|
||
let pos, tree;
|
||
if (this.parse && (pos = this.parse.parsedPos) >= this.treeLen) {
|
||
if (this.parse.stoppedAt == null || this.parse.stoppedAt > pos)
|
||
this.parse.stopAt(pos);
|
||
this.withContext(() => {
|
||
while (!(tree = this.parse.advance())) {
|
||
}
|
||
});
|
||
this.treeLen = pos;
|
||
this.tree = tree;
|
||
this.fragments = this.withoutTempSkipped(TreeFragment.addTree(this.tree, this.fragments, true));
|
||
this.parse = null;
|
||
}
|
||
}
|
||
withContext(f) {
|
||
let prev = currentContext;
|
||
currentContext = this;
|
||
try {
|
||
return f();
|
||
} finally {
|
||
currentContext = prev;
|
||
}
|
||
}
|
||
withoutTempSkipped(fragments) {
|
||
for (let r; r = this.tempSkipped.pop(); )
|
||
fragments = cutFragments(fragments, r.from, r.to);
|
||
return fragments;
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
changes(changes, newState) {
|
||
let { fragments, tree, treeLen, viewport, skipped } = this;
|
||
this.takeTree();
|
||
if (!changes.empty) {
|
||
let ranges = [];
|
||
changes.iterChangedRanges((fromA, toA, fromB, toB) => ranges.push({ fromA, toA, fromB, toB }));
|
||
fragments = TreeFragment.applyChanges(fragments, ranges);
|
||
tree = Tree.empty;
|
||
treeLen = 0;
|
||
viewport = { from: changes.mapPos(viewport.from, -1), to: changes.mapPos(viewport.to, 1) };
|
||
if (this.skipped.length) {
|
||
skipped = [];
|
||
for (let r of this.skipped) {
|
||
let from = changes.mapPos(r.from, 1), to = changes.mapPos(r.to, -1);
|
||
if (from < to)
|
||
skipped.push({ from, to });
|
||
}
|
||
}
|
||
}
|
||
return new _ParseContext(this.parser, newState, fragments, tree, treeLen, viewport, skipped, this.scheduleOn);
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
updateViewport(viewport) {
|
||
if (this.viewport.from == viewport.from && this.viewport.to == viewport.to)
|
||
return false;
|
||
this.viewport = viewport;
|
||
let startLen = this.skipped.length;
|
||
for (let i = 0; i < this.skipped.length; i++) {
|
||
let { from, to } = this.skipped[i];
|
||
if (from < viewport.to && to > viewport.from) {
|
||
this.fragments = cutFragments(this.fragments, from, to);
|
||
this.skipped.splice(i--, 1);
|
||
}
|
||
}
|
||
if (this.skipped.length >= startLen)
|
||
return false;
|
||
this.reset();
|
||
return true;
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
reset() {
|
||
if (this.parse) {
|
||
this.takeTree();
|
||
this.parse = null;
|
||
}
|
||
}
|
||
/**
|
||
Notify the parse scheduler that the given region was skipped
|
||
because it wasn't in view, and the parse should be restarted
|
||
when it comes into view.
|
||
*/
|
||
skipUntilInView(from, to) {
|
||
this.skipped.push({ from, to });
|
||
}
|
||
/**
|
||
Returns a parser intended to be used as placeholder when
|
||
asynchronously loading a nested parser. It'll skip its input and
|
||
mark it as not-really-parsed, so that the next update will parse
|
||
it again.
|
||
|
||
When `until` is given, a reparse will be scheduled when that
|
||
promise resolves.
|
||
*/
|
||
static getSkippingParser(until) {
|
||
return new class extends Parser {
|
||
createParse(input, fragments, ranges) {
|
||
let from = ranges[0].from, to = ranges[ranges.length - 1].to;
|
||
let parser = {
|
||
parsedPos: from,
|
||
advance() {
|
||
let cx = currentContext;
|
||
if (cx) {
|
||
for (let r of ranges)
|
||
cx.tempSkipped.push(r);
|
||
if (until)
|
||
cx.scheduleOn = cx.scheduleOn ? Promise.all([cx.scheduleOn, until]) : until;
|
||
}
|
||
this.parsedPos = to;
|
||
return new Tree(NodeType.none, [], [], to - from);
|
||
},
|
||
stoppedAt: null,
|
||
stopAt() {
|
||
}
|
||
};
|
||
return parser;
|
||
}
|
||
}();
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
isDone(upto) {
|
||
upto = Math.min(upto, this.state.doc.length);
|
||
let frags = this.fragments;
|
||
return this.treeLen >= upto && frags.length && frags[0].from == 0 && frags[0].to >= upto;
|
||
}
|
||
/**
|
||
Get the context for the current parse, or `null` if no editor
|
||
parse is in progress.
|
||
*/
|
||
static get() {
|
||
return currentContext;
|
||
}
|
||
};
|
||
function cutFragments(fragments, from, to) {
|
||
return TreeFragment.applyChanges(fragments, [{ fromA: from, toA: to, fromB: from, toB: to }]);
|
||
}
|
||
var LanguageState = class _LanguageState {
|
||
constructor(context) {
|
||
this.context = context;
|
||
this.tree = context.tree;
|
||
}
|
||
apply(tr) {
|
||
if (!tr.docChanged && this.tree == this.context.tree)
|
||
return this;
|
||
let newCx = this.context.changes(tr.changes, tr.state);
|
||
let upto = this.context.treeLen == tr.startState.doc.length ? void 0 : Math.max(tr.changes.mapPos(this.context.treeLen), newCx.viewport.to);
|
||
if (!newCx.work(20, upto))
|
||
newCx.takeTree();
|
||
return new _LanguageState(newCx);
|
||
}
|
||
static init(state) {
|
||
let vpTo = Math.min(3e3, state.doc.length);
|
||
let parseState = ParseContext.create(state.facet(language).parser, state, { from: 0, to: vpTo });
|
||
if (!parseState.work(20, vpTo))
|
||
parseState.takeTree();
|
||
return new _LanguageState(parseState);
|
||
}
|
||
};
|
||
Language.state = StateField.define({
|
||
create: LanguageState.init,
|
||
update(value, tr) {
|
||
for (let e of tr.effects)
|
||
if (e.is(Language.setState))
|
||
return e.value;
|
||
if (tr.startState.facet(language) != tr.state.facet(language))
|
||
return LanguageState.init(tr.state);
|
||
return value.apply(tr);
|
||
}
|
||
});
|
||
var requestIdle = (callback) => {
|
||
let timeout = setTimeout(
|
||
() => callback(),
|
||
500
|
||
/* Work.MaxPause */
|
||
);
|
||
return () => clearTimeout(timeout);
|
||
};
|
||
if (typeof requestIdleCallback != "undefined")
|
||
requestIdle = (callback) => {
|
||
let idle = -1, timeout = setTimeout(
|
||
() => {
|
||
idle = requestIdleCallback(callback, {
|
||
timeout: 500 - 100
|
||
/* Work.MinPause */
|
||
});
|
||
},
|
||
100
|
||
/* Work.MinPause */
|
||
);
|
||
return () => idle < 0 ? clearTimeout(timeout) : cancelIdleCallback(idle);
|
||
};
|
||
var isInputPending = typeof navigator != "undefined" && ((_a = navigator.scheduling) === null || _a === void 0 ? void 0 : _a.isInputPending) ? () => navigator.scheduling.isInputPending() : null;
|
||
var parseWorker = ViewPlugin.fromClass(class ParseWorker {
|
||
constructor(view) {
|
||
this.view = view;
|
||
this.working = null;
|
||
this.workScheduled = 0;
|
||
this.chunkEnd = -1;
|
||
this.chunkBudget = -1;
|
||
this.work = this.work.bind(this);
|
||
this.scheduleWork();
|
||
}
|
||
update(update) {
|
||
let cx = this.view.state.field(Language.state).context;
|
||
if (cx.updateViewport(update.view.viewport) || this.view.viewport.to > cx.treeLen)
|
||
this.scheduleWork();
|
||
if (update.docChanged || update.selectionSet) {
|
||
if (this.view.hasFocus)
|
||
this.chunkBudget += 50;
|
||
this.scheduleWork();
|
||
}
|
||
this.checkAsyncSchedule(cx);
|
||
}
|
||
scheduleWork() {
|
||
if (this.working)
|
||
return;
|
||
let { state } = this.view, field = state.field(Language.state);
|
||
if (field.tree != field.context.tree || !field.context.isDone(state.doc.length))
|
||
this.working = requestIdle(this.work);
|
||
}
|
||
work(deadline) {
|
||
this.working = null;
|
||
let now = Date.now();
|
||
if (this.chunkEnd < now && (this.chunkEnd < 0 || this.view.hasFocus)) {
|
||
this.chunkEnd = now + 3e4;
|
||
this.chunkBudget = 3e3;
|
||
}
|
||
if (this.chunkBudget <= 0)
|
||
return;
|
||
let { state, viewport: { to: vpTo } } = this.view, field = state.field(Language.state);
|
||
if (field.tree == field.context.tree && field.context.isDone(
|
||
vpTo + 1e5
|
||
/* Work.MaxParseAhead */
|
||
))
|
||
return;
|
||
let endTime = Date.now() + Math.min(this.chunkBudget, 100, deadline && !isInputPending ? Math.max(25, deadline.timeRemaining() - 5) : 1e9);
|
||
let viewportFirst = field.context.treeLen < vpTo && state.doc.length > vpTo + 1e3;
|
||
let done = field.context.work(() => {
|
||
return isInputPending && isInputPending() || Date.now() > endTime;
|
||
}, vpTo + (viewportFirst ? 0 : 1e5));
|
||
this.chunkBudget -= Date.now() - now;
|
||
if (done || this.chunkBudget <= 0) {
|
||
field.context.takeTree();
|
||
this.view.dispatch({ effects: Language.setState.of(new LanguageState(field.context)) });
|
||
}
|
||
if (this.chunkBudget > 0 && !(done && !viewportFirst))
|
||
this.scheduleWork();
|
||
this.checkAsyncSchedule(field.context);
|
||
}
|
||
checkAsyncSchedule(cx) {
|
||
if (cx.scheduleOn) {
|
||
this.workScheduled++;
|
||
cx.scheduleOn.then(() => this.scheduleWork()).catch((err) => logException(this.view.state, err)).then(() => this.workScheduled--);
|
||
cx.scheduleOn = null;
|
||
}
|
||
}
|
||
destroy() {
|
||
if (this.working)
|
||
this.working();
|
||
}
|
||
isWorking() {
|
||
return !!(this.working || this.workScheduled > 0);
|
||
}
|
||
}, {
|
||
eventHandlers: { focus() {
|
||
this.scheduleWork();
|
||
} }
|
||
});
|
||
var language = Facet.define({
|
||
combine(languages) {
|
||
return languages.length ? languages[0] : null;
|
||
},
|
||
enables: (language2) => [
|
||
Language.state,
|
||
parseWorker,
|
||
EditorView.contentAttributes.compute([language2], (state) => {
|
||
let lang = state.facet(language2);
|
||
return lang && lang.name ? { "data-language": lang.name } : {};
|
||
})
|
||
]
|
||
});
|
||
var LanguageSupport = class {
|
||
/**
|
||
Create a language support object.
|
||
*/
|
||
constructor(language2, support = []) {
|
||
this.language = language2;
|
||
this.support = support;
|
||
this.extension = [language2, support];
|
||
}
|
||
};
|
||
var indentService = Facet.define();
|
||
var indentUnit = Facet.define({
|
||
combine: (values) => {
|
||
if (!values.length)
|
||
return " ";
|
||
let unit = values[0];
|
||
if (!unit || /\S/.test(unit) || Array.from(unit).some((e) => e != unit[0]))
|
||
throw new Error("Invalid indent unit: " + JSON.stringify(values[0]));
|
||
return unit;
|
||
}
|
||
});
|
||
function getIndentUnit(state) {
|
||
let unit = state.facet(indentUnit);
|
||
return unit.charCodeAt(0) == 9 ? state.tabSize * unit.length : unit.length;
|
||
}
|
||
function indentString(state, cols) {
|
||
let result = "", ts = state.tabSize, ch = state.facet(indentUnit)[0];
|
||
if (ch == " ") {
|
||
while (cols >= ts) {
|
||
result += " ";
|
||
cols -= ts;
|
||
}
|
||
ch = " ";
|
||
}
|
||
for (let i = 0; i < cols; i++)
|
||
result += ch;
|
||
return result;
|
||
}
|
||
function getIndentation(context, pos) {
|
||
if (context instanceof EditorState)
|
||
context = new IndentContext(context);
|
||
for (let service of context.state.facet(indentService)) {
|
||
let result = service(context, pos);
|
||
if (result !== void 0)
|
||
return result;
|
||
}
|
||
let tree = syntaxTree(context.state);
|
||
return tree.length >= pos ? syntaxIndentation(context, tree, pos) : null;
|
||
}
|
||
var IndentContext = class {
|
||
/**
|
||
Create an indent context.
|
||
*/
|
||
constructor(state, options = {}) {
|
||
this.state = state;
|
||
this.options = options;
|
||
this.unit = getIndentUnit(state);
|
||
}
|
||
/**
|
||
Get a description of the line at the given position, taking
|
||
[simulated line
|
||
breaks](https://codemirror.net/6/docs/ref/#language.IndentContext.constructor^options.simulateBreak)
|
||
into account. If there is such a break at `pos`, the `bias`
|
||
argument determines whether the part of the line line before or
|
||
after the break is used.
|
||
*/
|
||
lineAt(pos, bias = 1) {
|
||
let line = this.state.doc.lineAt(pos);
|
||
let { simulateBreak, simulateDoubleBreak } = this.options;
|
||
if (simulateBreak != null && simulateBreak >= line.from && simulateBreak <= line.to) {
|
||
if (simulateDoubleBreak && simulateBreak == pos)
|
||
return { text: "", from: pos };
|
||
else if (bias < 0 ? simulateBreak < pos : simulateBreak <= pos)
|
||
return { text: line.text.slice(simulateBreak - line.from), from: simulateBreak };
|
||
else
|
||
return { text: line.text.slice(0, simulateBreak - line.from), from: line.from };
|
||
}
|
||
return line;
|
||
}
|
||
/**
|
||
Get the text directly after `pos`, either the entire line
|
||
or the next 100 characters, whichever is shorter.
|
||
*/
|
||
textAfterPos(pos, bias = 1) {
|
||
if (this.options.simulateDoubleBreak && pos == this.options.simulateBreak)
|
||
return "";
|
||
let { text, from } = this.lineAt(pos, bias);
|
||
return text.slice(pos - from, Math.min(text.length, pos + 100 - from));
|
||
}
|
||
/**
|
||
Find the column for the given position.
|
||
*/
|
||
column(pos, bias = 1) {
|
||
let { text, from } = this.lineAt(pos, bias);
|
||
let result = this.countColumn(text, pos - from);
|
||
let override = this.options.overrideIndentation ? this.options.overrideIndentation(from) : -1;
|
||
if (override > -1)
|
||
result += override - this.countColumn(text, text.search(/\S|$/));
|
||
return result;
|
||
}
|
||
/**
|
||
Find the column position (taking tabs into account) of the given
|
||
position in the given string.
|
||
*/
|
||
countColumn(line, pos = line.length) {
|
||
return countColumn(line, this.state.tabSize, pos);
|
||
}
|
||
/**
|
||
Find the indentation column of the line at the given point.
|
||
*/
|
||
lineIndent(pos, bias = 1) {
|
||
let { text, from } = this.lineAt(pos, bias);
|
||
let override = this.options.overrideIndentation;
|
||
if (override) {
|
||
let overriden = override(from);
|
||
if (overriden > -1)
|
||
return overriden;
|
||
}
|
||
return this.countColumn(text, text.search(/\S|$/));
|
||
}
|
||
/**
|
||
Returns the [simulated line
|
||
break](https://codemirror.net/6/docs/ref/#language.IndentContext.constructor^options.simulateBreak)
|
||
for this context, if any.
|
||
*/
|
||
get simulatedBreak() {
|
||
return this.options.simulateBreak || null;
|
||
}
|
||
};
|
||
var indentNodeProp = new NodeProp();
|
||
function syntaxIndentation(cx, ast, pos) {
|
||
let stack = ast.resolveStack(pos);
|
||
let inner = ast.resolveInner(pos, -1).resolve(pos, 0).enterUnfinishedNodesBefore(pos);
|
||
if (inner != stack.node) {
|
||
let add = [];
|
||
for (let cur = inner; cur && !(cur.from == stack.node.from && cur.type == stack.node.type); cur = cur.parent)
|
||
add.push(cur);
|
||
for (let i = add.length - 1; i >= 0; i--)
|
||
stack = { node: add[i], next: stack };
|
||
}
|
||
return indentFor(stack, cx, pos);
|
||
}
|
||
function indentFor(stack, cx, pos) {
|
||
for (let cur = stack; cur; cur = cur.next) {
|
||
let strategy = indentStrategy(cur.node);
|
||
if (strategy)
|
||
return strategy(TreeIndentContext.create(cx, pos, cur));
|
||
}
|
||
return 0;
|
||
}
|
||
function ignoreClosed(cx) {
|
||
return cx.pos == cx.options.simulateBreak && cx.options.simulateDoubleBreak;
|
||
}
|
||
function indentStrategy(tree) {
|
||
let strategy = tree.type.prop(indentNodeProp);
|
||
if (strategy)
|
||
return strategy;
|
||
let first = tree.firstChild, close;
|
||
if (first && (close = first.type.prop(NodeProp.closedBy))) {
|
||
let last = tree.lastChild, closed = last && close.indexOf(last.name) > -1;
|
||
return (cx) => delimitedStrategy(cx, true, 1, void 0, closed && !ignoreClosed(cx) ? last.from : void 0);
|
||
}
|
||
return tree.parent == null ? topIndent : null;
|
||
}
|
||
function topIndent() {
|
||
return 0;
|
||
}
|
||
var TreeIndentContext = class _TreeIndentContext extends IndentContext {
|
||
constructor(base, pos, context) {
|
||
super(base.state, base.options);
|
||
this.base = base;
|
||
this.pos = pos;
|
||
this.context = context;
|
||
}
|
||
/**
|
||
The syntax tree node to which the indentation strategy
|
||
applies.
|
||
*/
|
||
get node() {
|
||
return this.context.node;
|
||
}
|
||
/**
|
||
@internal
|
||
*/
|
||
static create(base, pos, context) {
|
||
return new _TreeIndentContext(base, pos, context);
|
||
}
|
||
/**
|
||
Get the text directly after `this.pos`, either the entire line
|
||
or the next 100 characters, whichever is shorter.
|
||
*/
|
||
get textAfter() {
|
||
return this.textAfterPos(this.pos);
|
||
}
|
||
/**
|
||
Get the indentation at the reference line for `this.node`, which
|
||
is the line on which it starts, unless there is a node that is
|
||
_not_ a parent of this node covering the start of that line. If
|
||
so, the line at the start of that node is tried, again skipping
|
||
on if it is covered by another such node.
|
||
*/
|
||
get baseIndent() {
|
||
return this.baseIndentFor(this.node);
|
||
}
|
||
/**
|
||
Get the indentation for the reference line of the given node
|
||
(see [`baseIndent`](https://codemirror.net/6/docs/ref/#language.TreeIndentContext.baseIndent)).
|
||
*/
|
||
baseIndentFor(node) {
|
||
let line = this.state.doc.lineAt(node.from);
|
||
for (; ; ) {
|
||
let atBreak = node.resolve(line.from);
|
||
while (atBreak.parent && atBreak.parent.from == atBreak.from)
|
||
atBreak = atBreak.parent;
|
||
if (isParent(atBreak, node))
|
||
break;
|
||
line = this.state.doc.lineAt(atBreak.from);
|
||
}
|
||
return this.lineIndent(line.from);
|
||
}
|
||
/**
|
||
Continue looking for indentations in the node's parent nodes,
|
||
and return the result of that.
|
||
*/
|
||
continue() {
|
||
return indentFor(this.context.next, this.base, this.pos);
|
||
}
|
||
};
|
||
function isParent(parent, of) {
|
||
for (let cur = of; cur; cur = cur.parent)
|
||
if (parent == cur)
|
||
return true;
|
||
return false;
|
||
}
|
||
function bracketedAligned(context) {
|
||
let tree = context.node;
|
||
let openToken = tree.childAfter(tree.from), last = tree.lastChild;
|
||
if (!openToken)
|
||
return null;
|
||
let sim = context.options.simulateBreak;
|
||
let openLine = context.state.doc.lineAt(openToken.from);
|
||
let lineEnd = sim == null || sim <= openLine.from ? openLine.to : Math.min(openLine.to, sim);
|
||
for (let pos = openToken.to; ; ) {
|
||
let next = tree.childAfter(pos);
|
||
if (!next || next == last)
|
||
return null;
|
||
if (!next.type.isSkipped) {
|
||
if (next.from >= lineEnd)
|
||
return null;
|
||
let space = /^ */.exec(openLine.text.slice(openToken.to - openLine.from))[0].length;
|
||
return { from: openToken.from, to: openToken.to + space };
|
||
}
|
||
pos = next.to;
|
||
}
|
||
}
|
||
function delimitedIndent({ closing, align = true, units = 1 }) {
|
||
return (context) => delimitedStrategy(context, align, units, closing);
|
||
}
|
||
function delimitedStrategy(context, align, units, closing, closedAt) {
|
||
let after = context.textAfter, space = after.match(/^\s*/)[0].length;
|
||
let closed = closing && after.slice(space, space + closing.length) == closing || closedAt == context.pos + space;
|
||
let aligned = align ? bracketedAligned(context) : null;
|
||
if (aligned)
|
||
return closed ? context.column(aligned.from) : context.column(aligned.to);
|
||
return context.baseIndent + (closed ? 0 : context.unit * units);
|
||
}
|
||
var flatIndent = (context) => context.baseIndent;
|
||
function continuedIndent({ except, units = 1 } = {}) {
|
||
return (context) => {
|
||
let matchExcept = except && except.test(context.textAfter);
|
||
return context.baseIndent + (matchExcept ? 0 : units * context.unit);
|
||
};
|
||
}
|
||
var DontIndentBeyond = 200;
|
||
function indentOnInput() {
|
||
return EditorState.transactionFilter.of((tr) => {
|
||
if (!tr.docChanged || !tr.isUserEvent("input.type") && !tr.isUserEvent("input.complete"))
|
||
return tr;
|
||
let rules = tr.startState.languageDataAt("indentOnInput", tr.startState.selection.main.head);
|
||
if (!rules.length)
|
||
return tr;
|
||
let doc = tr.newDoc, { head } = tr.newSelection.main, line = doc.lineAt(head);
|
||
if (head > line.from + DontIndentBeyond)
|
||
return tr;
|
||
let lineStart = doc.sliceString(line.from, head);
|
||
if (!rules.some((r) => r.test(lineStart)))
|
||
return tr;
|
||
let { state } = tr, last = -1, changes = [];
|
||
for (let { head: head2 } of state.selection.ranges) {
|
||
let line2 = state.doc.lineAt(head2);
|
||
if (line2.from == last)
|
||
continue;
|
||
last = line2.from;
|
||
let indent = getIndentation(state, line2.from);
|
||
if (indent == null)
|
||
continue;
|
||
let cur = /^\s*/.exec(line2.text)[0];
|
||
let norm = indentString(state, indent);
|
||
if (cur != norm)
|
||
changes.push({ from: line2.from, to: line2.from + cur.length, insert: norm });
|
||
}
|
||
return changes.length ? [tr, { changes, sequential: true }] : tr;
|
||
});
|
||
}
|
||
var foldService = Facet.define();
|
||
var foldNodeProp = new NodeProp();
|
||
function foldInside(node) {
|
||
let first = node.firstChild, last = node.lastChild;
|
||
return first && first.to < last.from ? { from: first.to, to: last.type.isError ? node.to : last.from } : null;
|
||
}
|
||
function syntaxFolding(state, start, end) {
|
||
let tree = syntaxTree(state);
|
||
if (tree.length < end)
|
||
return null;
|
||
let stack = tree.resolveStack(end, 1);
|
||
let found = null;
|
||
for (let iter = stack; iter; iter = iter.next) {
|
||
let cur = iter.node;
|
||
if (cur.to <= end || cur.from > end)
|
||
continue;
|
||
if (found && cur.from < start)
|
||
break;
|
||
let prop = cur.type.prop(foldNodeProp);
|
||
if (prop && (cur.to < tree.length - 50 || tree.length == state.doc.length || !isUnfinished(cur))) {
|
||
let value = prop(cur, state);
|
||
if (value && value.from <= end && value.from >= start && value.to > end)
|
||
found = value;
|
||
}
|
||
}
|
||
return found;
|
||
}
|
||
function isUnfinished(node) {
|
||
let ch = node.lastChild;
|
||
return ch && ch.to == node.to && ch.type.isError;
|
||
}
|
||
function foldable(state, lineStart, lineEnd) {
|
||
for (let service of state.facet(foldService)) {
|
||
let result = service(state, lineStart, lineEnd);
|
||
if (result)
|
||
return result;
|
||
}
|
||
return syntaxFolding(state, lineStart, lineEnd);
|
||
}
|
||
function mapRange(range, mapping) {
|
||
let from = mapping.mapPos(range.from, 1), to = mapping.mapPos(range.to, -1);
|
||
return from >= to ? void 0 : { from, to };
|
||
}
|
||
var foldEffect = StateEffect.define({ map: mapRange });
|
||
var unfoldEffect = StateEffect.define({ map: mapRange });
|
||
function selectedLines(view) {
|
||
let lines = [];
|
||
for (let { head } of view.state.selection.ranges) {
|
||
if (lines.some((l) => l.from <= head && l.to >= head))
|
||
continue;
|
||
lines.push(view.lineBlockAt(head));
|
||
}
|
||
return lines;
|
||
}
|
||
var foldState = StateField.define({
|
||
create() {
|
||
return Decoration.none;
|
||
},
|
||
update(folded, tr) {
|
||
folded = folded.map(tr.changes);
|
||
for (let e of tr.effects) {
|
||
if (e.is(foldEffect) && !foldExists(folded, e.value.from, e.value.to)) {
|
||
let { preparePlaceholder } = tr.state.facet(foldConfig);
|
||
let widget = !preparePlaceholder ? foldWidget : Decoration.replace({ widget: new PreparedFoldWidget(preparePlaceholder(tr.state, e.value)) });
|
||
folded = folded.update({ add: [widget.range(e.value.from, e.value.to)] });
|
||
} else if (e.is(unfoldEffect)) {
|
||
folded = folded.update({
|
||
filter: (from, to) => e.value.from != from || e.value.to != to,
|
||
filterFrom: e.value.from,
|
||
filterTo: e.value.to
|
||
});
|
||
}
|
||
}
|
||
if (tr.selection) {
|
||
let onSelection = false, { head } = tr.selection.main;
|
||
folded.between(head, head, (a, b) => {
|
||
if (a < head && b > head)
|
||
onSelection = true;
|
||
});
|
||
if (onSelection)
|
||
folded = folded.update({
|
||
filterFrom: head,
|
||
filterTo: head,
|
||
filter: (a, b) => b <= head || a >= head
|
||
});
|
||
}
|
||
return folded;
|
||
},
|
||
provide: (f) => EditorView.decorations.from(f),
|
||
toJSON(folded, state) {
|
||
let ranges = [];
|
||
folded.between(0, state.doc.length, (from, to) => {
|
||
ranges.push(from, to);
|
||
});
|
||
return ranges;
|
||
},
|
||
fromJSON(value) {
|
||
if (!Array.isArray(value) || value.length % 2)
|
||
throw new RangeError("Invalid JSON for fold state");
|
||
let ranges = [];
|
||
for (let i = 0; i < value.length; ) {
|
||
let from = value[i++], to = value[i++];
|
||
if (typeof from != "number" || typeof to != "number")
|
||
throw new RangeError("Invalid JSON for fold state");
|
||
ranges.push(foldWidget.range(from, to));
|
||
}
|
||
return Decoration.set(ranges, true);
|
||
}
|
||
});
|
||
function findFold(state, from, to) {
|
||
var _a2;
|
||
let found = null;
|
||
(_a2 = state.field(foldState, false)) === null || _a2 === void 0 ? void 0 : _a2.between(from, to, (from2, to2) => {
|
||
if (!found || found.from > from2)
|
||
found = { from: from2, to: to2 };
|
||
});
|
||
return found;
|
||
}
|
||
function foldExists(folded, from, to) {
|
||
let found = false;
|
||
folded.between(from, from, (a, b) => {
|
||
if (a == from && b == to)
|
||
found = true;
|
||
});
|
||
return found;
|
||
}
|
||
function maybeEnable(state, other) {
|
||
return state.field(foldState, false) ? other : other.concat(StateEffect.appendConfig.of(codeFolding()));
|
||
}
|
||
var foldCode = (view) => {
|
||
for (let line of selectedLines(view)) {
|
||
let range = foldable(view.state, line.from, line.to);
|
||
if (range) {
|
||
view.dispatch({ effects: maybeEnable(view.state, [foldEffect.of(range), announceFold(view, range)]) });
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
};
|
||
var unfoldCode = (view) => {
|
||
if (!view.state.field(foldState, false))
|
||
return false;
|
||
let effects = [];
|
||
for (let line of selectedLines(view)) {
|
||
let folded = findFold(view.state, line.from, line.to);
|
||
if (folded)
|
||
effects.push(unfoldEffect.of(folded), announceFold(view, folded, false));
|
||
}
|
||
if (effects.length)
|
||
view.dispatch({ effects });
|
||
return effects.length > 0;
|
||
};
|
||
function announceFold(view, range, fold = true) {
|
||
let lineFrom = view.state.doc.lineAt(range.from).number, lineTo = view.state.doc.lineAt(range.to).number;
|
||
return EditorView.announce.of(`${view.state.phrase(fold ? "Folded lines" : "Unfolded lines")} ${lineFrom} ${view.state.phrase("to")} ${lineTo}.`);
|
||
}
|
||
var foldAll = (view) => {
|
||
let { state } = view, effects = [];
|
||
for (let pos = 0; pos < state.doc.length; ) {
|
||
let line = view.lineBlockAt(pos), range = foldable(state, line.from, line.to);
|
||
if (range)
|
||
effects.push(foldEffect.of(range));
|
||
pos = (range ? view.lineBlockAt(range.to) : line).to + 1;
|
||
}
|
||
if (effects.length)
|
||
view.dispatch({ effects: maybeEnable(view.state, effects) });
|
||
return !!effects.length;
|
||
};
|
||
var unfoldAll = (view) => {
|
||
let field = view.state.field(foldState, false);
|
||
if (!field || !field.size)
|
||
return false;
|
||
let effects = [];
|
||
field.between(0, view.state.doc.length, (from, to) => {
|
||
effects.push(unfoldEffect.of({ from, to }));
|
||
});
|
||
view.dispatch({ effects });
|
||
return true;
|
||
};
|
||
var foldKeymap = [
|
||
{ key: "Ctrl-Shift-[", mac: "Cmd-Alt-[", run: foldCode },
|
||
{ key: "Ctrl-Shift-]", mac: "Cmd-Alt-]", run: unfoldCode },
|
||
{ key: "Ctrl-Alt-[", run: foldAll },
|
||
{ key: "Ctrl-Alt-]", run: unfoldAll }
|
||
];
|
||
var defaultConfig = {
|
||
placeholderDOM: null,
|
||
preparePlaceholder: null,
|
||
placeholderText: "…"
|
||
};
|
||
var foldConfig = Facet.define({
|
||
combine(values) {
|
||
return combineConfig(values, defaultConfig);
|
||
}
|
||
});
|
||
function codeFolding(config) {
|
||
let result = [foldState, baseTheme$1];
|
||
if (config)
|
||
result.push(foldConfig.of(config));
|
||
return result;
|
||
}
|
||
function widgetToDOM(view, prepared) {
|
||
let { state } = view, conf = state.facet(foldConfig);
|
||
let onclick = (event) => {
|
||
let line = view.lineBlockAt(view.posAtDOM(event.target));
|
||
let folded = findFold(view.state, line.from, line.to);
|
||
if (folded)
|
||
view.dispatch({ effects: unfoldEffect.of(folded) });
|
||
event.preventDefault();
|
||
};
|
||
if (conf.placeholderDOM)
|
||
return conf.placeholderDOM(view, onclick, prepared);
|
||
let element = document.createElement("span");
|
||
element.textContent = conf.placeholderText;
|
||
element.setAttribute("aria-label", state.phrase("folded code"));
|
||
element.title = state.phrase("unfold");
|
||
element.className = "cm-foldPlaceholder";
|
||
element.onclick = onclick;
|
||
return element;
|
||
}
|
||
var foldWidget = Decoration.replace({ widget: new class extends WidgetType {
|
||
toDOM(view) {
|
||
return widgetToDOM(view, null);
|
||
}
|
||
}() });
|
||
var PreparedFoldWidget = class extends WidgetType {
|
||
constructor(value) {
|
||
super();
|
||
this.value = value;
|
||
}
|
||
eq(other) {
|
||
return this.value == other.value;
|
||
}
|
||
toDOM(view) {
|
||
return widgetToDOM(view, this.value);
|
||
}
|
||
};
|
||
var foldGutterDefaults = {
|
||
openText: "⌄",
|
||
closedText: "›",
|
||
markerDOM: null,
|
||
domEventHandlers: {},
|
||
foldingChanged: () => false
|
||
};
|
||
var FoldMarker = class extends GutterMarker {
|
||
constructor(config, open) {
|
||
super();
|
||
this.config = config;
|
||
this.open = open;
|
||
}
|
||
eq(other) {
|
||
return this.config == other.config && this.open == other.open;
|
||
}
|
||
toDOM(view) {
|
||
if (this.config.markerDOM)
|
||
return this.config.markerDOM(this.open);
|
||
let span = document.createElement("span");
|
||
span.textContent = this.open ? this.config.openText : this.config.closedText;
|
||
span.title = view.state.phrase(this.open ? "Fold line" : "Unfold line");
|
||
return span;
|
||
}
|
||
};
|
||
function foldGutter(config = {}) {
|
||
let fullConfig = Object.assign(Object.assign({}, foldGutterDefaults), config);
|
||
let canFold = new FoldMarker(fullConfig, true), canUnfold = new FoldMarker(fullConfig, false);
|
||
let markers = ViewPlugin.fromClass(class {
|
||
constructor(view) {
|
||
this.from = view.viewport.from;
|
||
this.markers = this.buildMarkers(view);
|
||
}
|
||
update(update) {
|
||
if (update.docChanged || update.viewportChanged || update.startState.facet(language) != update.state.facet(language) || update.startState.field(foldState, false) != update.state.field(foldState, false) || syntaxTree(update.startState) != syntaxTree(update.state) || fullConfig.foldingChanged(update))
|
||
this.markers = this.buildMarkers(update.view);
|
||
}
|
||
buildMarkers(view) {
|
||
let builder = new RangeSetBuilder();
|
||
for (let line of view.viewportLineBlocks) {
|
||
let mark = findFold(view.state, line.from, line.to) ? canUnfold : foldable(view.state, line.from, line.to) ? canFold : null;
|
||
if (mark)
|
||
builder.add(line.from, line.from, mark);
|
||
}
|
||
return builder.finish();
|
||
}
|
||
});
|
||
let { domEventHandlers } = fullConfig;
|
||
return [
|
||
markers,
|
||
gutter({
|
||
class: "cm-foldGutter",
|
||
markers(view) {
|
||
var _a2;
|
||
return ((_a2 = view.plugin(markers)) === null || _a2 === void 0 ? void 0 : _a2.markers) || RangeSet.empty;
|
||
},
|
||
initialSpacer() {
|
||
return new FoldMarker(fullConfig, false);
|
||
},
|
||
domEventHandlers: Object.assign(Object.assign({}, domEventHandlers), { click: (view, line, event) => {
|
||
if (domEventHandlers.click && domEventHandlers.click(view, line, event))
|
||
return true;
|
||
let folded = findFold(view.state, line.from, line.to);
|
||
if (folded) {
|
||
view.dispatch({ effects: unfoldEffect.of(folded) });
|
||
return true;
|
||
}
|
||
let range = foldable(view.state, line.from, line.to);
|
||
if (range) {
|
||
view.dispatch({ effects: foldEffect.of(range) });
|
||
return true;
|
||
}
|
||
return false;
|
||
} })
|
||
}),
|
||
codeFolding()
|
||
];
|
||
}
|
||
var baseTheme$1 = EditorView.baseTheme({
|
||
".cm-foldPlaceholder": {
|
||
backgroundColor: "#eee",
|
||
border: "1px solid #ddd",
|
||
color: "#888",
|
||
borderRadius: ".2em",
|
||
margin: "0 1px",
|
||
padding: "0 1px",
|
||
cursor: "pointer"
|
||
},
|
||
".cm-foldGutter span": {
|
||
padding: "0 1px",
|
||
cursor: "pointer"
|
||
}
|
||
});
|
||
var HighlightStyle = class _HighlightStyle {
|
||
constructor(specs, options) {
|
||
this.specs = specs;
|
||
let modSpec;
|
||
function def(spec) {
|
||
let cls = StyleModule.newName();
|
||
(modSpec || (modSpec = /* @__PURE__ */ Object.create(null)))["." + cls] = spec;
|
||
return cls;
|
||
}
|
||
const all = typeof options.all == "string" ? options.all : options.all ? def(options.all) : void 0;
|
||
const scopeOpt = options.scope;
|
||
this.scope = scopeOpt instanceof Language ? (type) => type.prop(languageDataProp) == scopeOpt.data : scopeOpt ? (type) => type == scopeOpt : void 0;
|
||
this.style = tagHighlighter(specs.map((style) => ({
|
||
tag: style.tag,
|
||
class: style.class || def(Object.assign({}, style, { tag: null }))
|
||
})), {
|
||
all
|
||
}).style;
|
||
this.module = modSpec ? new StyleModule(modSpec) : null;
|
||
this.themeType = options.themeType;
|
||
}
|
||
/**
|
||
Create a highlighter style that associates the given styles to
|
||
the given tags. The specs must be objects that hold a style tag
|
||
or array of tags in their `tag` property, and either a single
|
||
`class` property providing a static CSS class (for highlighter
|
||
that rely on external styling), or a
|
||
[`style-mod`](https://github.com/marijnh/style-mod#documentation)-style
|
||
set of CSS properties (which define the styling for those tags).
|
||
|
||
The CSS rules created for a highlighter will be emitted in the
|
||
order of the spec's properties. That means that for elements that
|
||
have multiple tags associated with them, styles defined further
|
||
down in the list will have a higher CSS precedence than styles
|
||
defined earlier.
|
||
*/
|
||
static define(specs, options) {
|
||
return new _HighlightStyle(specs, options || {});
|
||
}
|
||
};
|
||
var highlighterFacet = Facet.define();
|
||
var fallbackHighlighter = Facet.define({
|
||
combine(values) {
|
||
return values.length ? [values[0]] : null;
|
||
}
|
||
});
|
||
function getHighlighters(state) {
|
||
let main = state.facet(highlighterFacet);
|
||
return main.length ? main : state.facet(fallbackHighlighter);
|
||
}
|
||
function syntaxHighlighting(highlighter, options) {
|
||
let ext = [treeHighlighter], themeType;
|
||
if (highlighter instanceof HighlightStyle) {
|
||
if (highlighter.module)
|
||
ext.push(EditorView.styleModule.of(highlighter.module));
|
||
themeType = highlighter.themeType;
|
||
}
|
||
if (options === null || options === void 0 ? void 0 : options.fallback)
|
||
ext.push(fallbackHighlighter.of(highlighter));
|
||
else if (themeType)
|
||
ext.push(highlighterFacet.computeN([EditorView.darkTheme], (state) => {
|
||
return state.facet(EditorView.darkTheme) == (themeType == "dark") ? [highlighter] : [];
|
||
}));
|
||
else
|
||
ext.push(highlighterFacet.of(highlighter));
|
||
return ext;
|
||
}
|
||
var TreeHighlighter = class {
|
||
constructor(view) {
|
||
this.markCache = /* @__PURE__ */ Object.create(null);
|
||
this.tree = syntaxTree(view.state);
|
||
this.decorations = this.buildDeco(view, getHighlighters(view.state));
|
||
this.decoratedTo = view.viewport.to;
|
||
}
|
||
update(update) {
|
||
let tree = syntaxTree(update.state), highlighters = getHighlighters(update.state);
|
||
let styleChange = highlighters != getHighlighters(update.startState);
|
||
let { viewport } = update.view, decoratedToMapped = update.changes.mapPos(this.decoratedTo, 1);
|
||
if (tree.length < viewport.to && !styleChange && tree.type == this.tree.type && decoratedToMapped >= viewport.to) {
|
||
this.decorations = this.decorations.map(update.changes);
|
||
this.decoratedTo = decoratedToMapped;
|
||
} else if (tree != this.tree || update.viewportChanged || styleChange) {
|
||
this.tree = tree;
|
||
this.decorations = this.buildDeco(update.view, highlighters);
|
||
this.decoratedTo = viewport.to;
|
||
}
|
||
}
|
||
buildDeco(view, highlighters) {
|
||
if (!highlighters || !this.tree.length)
|
||
return Decoration.none;
|
||
let builder = new RangeSetBuilder();
|
||
for (let { from, to } of view.visibleRanges) {
|
||
highlightTree(this.tree, highlighters, (from2, to2, style) => {
|
||
builder.add(from2, to2, this.markCache[style] || (this.markCache[style] = Decoration.mark({ class: style })));
|
||
}, from, to);
|
||
}
|
||
return builder.finish();
|
||
}
|
||
};
|
||
var treeHighlighter = Prec.high(ViewPlugin.fromClass(TreeHighlighter, {
|
||
decorations: (v) => v.decorations
|
||
}));
|
||
var defaultHighlightStyle = HighlightStyle.define([
|
||
{
|
||
tag: tags.meta,
|
||
color: "#404740"
|
||
},
|
||
{
|
||
tag: tags.link,
|
||
textDecoration: "underline"
|
||
},
|
||
{
|
||
tag: tags.heading,
|
||
textDecoration: "underline",
|
||
fontWeight: "bold"
|
||
},
|
||
{
|
||
tag: tags.emphasis,
|
||
fontStyle: "italic"
|
||
},
|
||
{
|
||
tag: tags.strong,
|
||
fontWeight: "bold"
|
||
},
|
||
{
|
||
tag: tags.strikethrough,
|
||
textDecoration: "line-through"
|
||
},
|
||
{
|
||
tag: tags.keyword,
|
||
color: "#708"
|
||
},
|
||
{
|
||
tag: [tags.atom, tags.bool, tags.url, tags.contentSeparator, tags.labelName],
|
||
color: "#219"
|
||
},
|
||
{
|
||
tag: [tags.literal, tags.inserted],
|
||
color: "#164"
|
||
},
|
||
{
|
||
tag: [tags.string, tags.deleted],
|
||
color: "#a11"
|
||
},
|
||
{
|
||
tag: [tags.regexp, tags.escape, tags.special(tags.string)],
|
||
color: "#e40"
|
||
},
|
||
{
|
||
tag: tags.definition(tags.variableName),
|
||
color: "#00f"
|
||
},
|
||
{
|
||
tag: tags.local(tags.variableName),
|
||
color: "#30a"
|
||
},
|
||
{
|
||
tag: [tags.typeName, tags.namespace],
|
||
color: "#085"
|
||
},
|
||
{
|
||
tag: tags.className,
|
||
color: "#167"
|
||
},
|
||
{
|
||
tag: [tags.special(tags.variableName), tags.macroName],
|
||
color: "#256"
|
||
},
|
||
{
|
||
tag: tags.definition(tags.propertyName),
|
||
color: "#00c"
|
||
},
|
||
{
|
||
tag: tags.comment,
|
||
color: "#940"
|
||
},
|
||
{
|
||
tag: tags.invalid,
|
||
color: "#f00"
|
||
}
|
||
]);
|
||
var baseTheme = EditorView.baseTheme({
|
||
"&.cm-focused .cm-matchingBracket": { backgroundColor: "#328c8252" },
|
||
"&.cm-focused .cm-nonmatchingBracket": { backgroundColor: "#bb555544" }
|
||
});
|
||
var DefaultScanDist = 1e4;
|
||
var DefaultBrackets = "()[]{}";
|
||
var bracketMatchingConfig = Facet.define({
|
||
combine(configs) {
|
||
return combineConfig(configs, {
|
||
afterCursor: true,
|
||
brackets: DefaultBrackets,
|
||
maxScanDistance: DefaultScanDist,
|
||
renderMatch: defaultRenderMatch
|
||
});
|
||
}
|
||
});
|
||
var matchingMark = Decoration.mark({ class: "cm-matchingBracket" });
|
||
var nonmatchingMark = Decoration.mark({ class: "cm-nonmatchingBracket" });
|
||
function defaultRenderMatch(match) {
|
||
let decorations = [];
|
||
let mark = match.matched ? matchingMark : nonmatchingMark;
|
||
decorations.push(mark.range(match.start.from, match.start.to));
|
||
if (match.end)
|
||
decorations.push(mark.range(match.end.from, match.end.to));
|
||
return decorations;
|
||
}
|
||
var bracketMatchingState = StateField.define({
|
||
create() {
|
||
return Decoration.none;
|
||
},
|
||
update(deco, tr) {
|
||
if (!tr.docChanged && !tr.selection)
|
||
return deco;
|
||
let decorations = [];
|
||
let config = tr.state.facet(bracketMatchingConfig);
|
||
for (let range of tr.state.selection.ranges) {
|
||
if (!range.empty)
|
||
continue;
|
||
let match = matchBrackets(tr.state, range.head, -1, config) || range.head > 0 && matchBrackets(tr.state, range.head - 1, 1, config) || config.afterCursor && (matchBrackets(tr.state, range.head, 1, config) || range.head < tr.state.doc.length && matchBrackets(tr.state, range.head + 1, -1, config));
|
||
if (match)
|
||
decorations = decorations.concat(config.renderMatch(match, tr.state));
|
||
}
|
||
return Decoration.set(decorations, true);
|
||
},
|
||
provide: (f) => EditorView.decorations.from(f)
|
||
});
|
||
var bracketMatchingUnique = [
|
||
bracketMatchingState,
|
||
baseTheme
|
||
];
|
||
function bracketMatching(config = {}) {
|
||
return [bracketMatchingConfig.of(config), bracketMatchingUnique];
|
||
}
|
||
var bracketMatchingHandle = new NodeProp();
|
||
function matchingNodes(node, dir, brackets) {
|
||
let byProp = node.prop(dir < 0 ? NodeProp.openedBy : NodeProp.closedBy);
|
||
if (byProp)
|
||
return byProp;
|
||
if (node.name.length == 1) {
|
||
let index = brackets.indexOf(node.name);
|
||
if (index > -1 && index % 2 == (dir < 0 ? 1 : 0))
|
||
return [brackets[index + dir]];
|
||
}
|
||
return null;
|
||
}
|
||
function findHandle(node) {
|
||
let hasHandle = node.type.prop(bracketMatchingHandle);
|
||
return hasHandle ? hasHandle(node.node) : node;
|
||
}
|
||
function matchBrackets(state, pos, dir, config = {}) {
|
||
let maxScanDistance = config.maxScanDistance || DefaultScanDist, brackets = config.brackets || DefaultBrackets;
|
||
let tree = syntaxTree(state), node = tree.resolveInner(pos, dir);
|
||
for (let cur = node; cur; cur = cur.parent) {
|
||
let matches = matchingNodes(cur.type, dir, brackets);
|
||
if (matches && cur.from < cur.to) {
|
||
let handle = findHandle(cur);
|
||
if (handle && (dir > 0 ? pos >= handle.from && pos < handle.to : pos > handle.from && pos <= handle.to))
|
||
return matchMarkedBrackets(state, pos, dir, cur, handle, matches, brackets);
|
||
}
|
||
}
|
||
return matchPlainBrackets(state, pos, dir, tree, node.type, maxScanDistance, brackets);
|
||
}
|
||
function matchMarkedBrackets(_state, _pos, dir, token, handle, matching, brackets) {
|
||
let parent = token.parent, firstToken = { from: handle.from, to: handle.to };
|
||
let depth = 0, cursor = parent === null || parent === void 0 ? void 0 : parent.cursor();
|
||
if (cursor && (dir < 0 ? cursor.childBefore(token.from) : cursor.childAfter(token.to)))
|
||
do {
|
||
if (dir < 0 ? cursor.to <= token.from : cursor.from >= token.to) {
|
||
if (depth == 0 && matching.indexOf(cursor.type.name) > -1 && cursor.from < cursor.to) {
|
||
let endHandle = findHandle(cursor);
|
||
return { start: firstToken, end: endHandle ? { from: endHandle.from, to: endHandle.to } : void 0, matched: true };
|
||
} else if (matchingNodes(cursor.type, dir, brackets)) {
|
||
depth++;
|
||
} else if (matchingNodes(cursor.type, -dir, brackets)) {
|
||
if (depth == 0) {
|
||
let endHandle = findHandle(cursor);
|
||
return {
|
||
start: firstToken,
|
||
end: endHandle && endHandle.from < endHandle.to ? { from: endHandle.from, to: endHandle.to } : void 0,
|
||
matched: false
|
||
};
|
||
}
|
||
depth--;
|
||
}
|
||
}
|
||
} while (dir < 0 ? cursor.prevSibling() : cursor.nextSibling());
|
||
return { start: firstToken, matched: false };
|
||
}
|
||
function matchPlainBrackets(state, pos, dir, tree, tokenType, maxScanDistance, brackets) {
|
||
let startCh = dir < 0 ? state.sliceDoc(pos - 1, pos) : state.sliceDoc(pos, pos + 1);
|
||
let bracket2 = brackets.indexOf(startCh);
|
||
if (bracket2 < 0 || bracket2 % 2 == 0 != dir > 0)
|
||
return null;
|
||
let startToken = { from: dir < 0 ? pos - 1 : pos, to: dir > 0 ? pos + 1 : pos };
|
||
let iter = state.doc.iterRange(pos, dir > 0 ? state.doc.length : 0), depth = 0;
|
||
for (let distance = 0; !iter.next().done && distance <= maxScanDistance; ) {
|
||
let text = iter.value;
|
||
if (dir < 0)
|
||
distance += text.length;
|
||
let basePos = pos + distance * dir;
|
||
for (let pos2 = dir > 0 ? 0 : text.length - 1, end = dir > 0 ? text.length : -1; pos2 != end; pos2 += dir) {
|
||
let found = brackets.indexOf(text[pos2]);
|
||
if (found < 0 || tree.resolveInner(basePos + pos2, 1).type != tokenType)
|
||
continue;
|
||
if (found % 2 == 0 == dir > 0) {
|
||
depth++;
|
||
} else if (depth == 1) {
|
||
return { start: startToken, end: { from: basePos + pos2, to: basePos + pos2 + 1 }, matched: found >> 1 == bracket2 >> 1 };
|
||
} else {
|
||
depth--;
|
||
}
|
||
}
|
||
if (dir > 0)
|
||
distance += text.length;
|
||
}
|
||
return iter.done ? { start: startToken, matched: false } : null;
|
||
}
|
||
var noTokens = /* @__PURE__ */ Object.create(null);
|
||
var typeArray = [NodeType.none];
|
||
var nodeSet = new NodeSet(typeArray);
|
||
var warned = [];
|
||
var byTag = /* @__PURE__ */ Object.create(null);
|
||
var defaultTable = /* @__PURE__ */ Object.create(null);
|
||
for (let [legacyName, name2] 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] = createTokenType(noTokens, name2);
|
||
var TokenTable = class {
|
||
constructor(extra) {
|
||
this.extra = extra;
|
||
this.table = Object.assign(/* @__PURE__ */ Object.create(null), defaultTable);
|
||
}
|
||
resolve(tag) {
|
||
return !tag ? 0 : this.table[tag] || (this.table[tag] = createTokenType(this.extra, tag));
|
||
}
|
||
};
|
||
var defaultTokenTable = 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 = [];
|
||
for (let name3 of tagStr.split(" ")) {
|
||
let found = [];
|
||
for (let part of name3.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];
|
||
}
|
||
}
|
||
for (let tag of found)
|
||
tags$1.push(tag);
|
||
}
|
||
if (!tags$1.length)
|
||
return 0;
|
||
let name2 = tagStr.replace(/ /g, "_"), key = name2 + " " + tags$1.map((t2) => t2.id);
|
||
let known = byTag[key];
|
||
if (known)
|
||
return known.id;
|
||
let type = byTag[key] = NodeType.define({
|
||
id: typeArray.length,
|
||
name: name2,
|
||
props: [styleTags({ [name2]: tags$1 })]
|
||
});
|
||
typeArray.push(type);
|
||
return type.id;
|
||
}
|
||
function buildForLine(line) {
|
||
return line.length <= 4096 && /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac\ufb50-\ufdff]/.test(line);
|
||
}
|
||
function textHasRTL(text) {
|
||
for (let i = text.iter(); !i.next().done; )
|
||
if (buildForLine(i.value))
|
||
return true;
|
||
return false;
|
||
}
|
||
function changeAddsRTL(change) {
|
||
let added = false;
|
||
change.iterChanges((fA, tA, fB, tB, ins) => {
|
||
if (!added && textHasRTL(ins))
|
||
added = true;
|
||
});
|
||
return added;
|
||
}
|
||
var alwaysIsolate = Facet.define({ combine: (values) => values.some((x) => x) });
|
||
var isolateMarks = ViewPlugin.fromClass(class {
|
||
constructor(view) {
|
||
this.always = view.state.facet(alwaysIsolate) || view.textDirection != Direction.LTR || view.state.facet(EditorView.perLineTextDirection);
|
||
this.hasRTL = !this.always && textHasRTL(view.state.doc);
|
||
this.tree = syntaxTree(view.state);
|
||
this.decorations = this.always || this.hasRTL ? buildDeco(view, this.tree, this.always) : Decoration.none;
|
||
}
|
||
update(update) {
|
||
let always = update.state.facet(alwaysIsolate) || update.view.textDirection != Direction.LTR || update.state.facet(EditorView.perLineTextDirection);
|
||
if (!always && !this.hasRTL && changeAddsRTL(update.changes))
|
||
this.hasRTL = true;
|
||
if (!always && !this.hasRTL)
|
||
return;
|
||
let tree = syntaxTree(update.state);
|
||
if (always != this.always || tree != this.tree || update.docChanged || update.viewportChanged) {
|
||
this.tree = tree;
|
||
this.always = always;
|
||
this.decorations = buildDeco(update.view, tree, always);
|
||
}
|
||
}
|
||
}, {
|
||
provide: (plugin) => {
|
||
function access(view) {
|
||
var _a2, _b;
|
||
return (_b = (_a2 = view.plugin(plugin)) === null || _a2 === void 0 ? void 0 : _a2.decorations) !== null && _b !== void 0 ? _b : Decoration.none;
|
||
}
|
||
return [
|
||
EditorView.outerDecorations.of(access),
|
||
Prec.lowest(EditorView.bidiIsolatedRanges.of(access))
|
||
];
|
||
}
|
||
});
|
||
function buildDeco(view, tree, always) {
|
||
let deco = new RangeSetBuilder();
|
||
let ranges = view.visibleRanges;
|
||
if (!always)
|
||
ranges = clipRTLLines(ranges, view.state.doc);
|
||
for (let { from, to } of ranges) {
|
||
tree.iterate({
|
||
enter: (node) => {
|
||
let iso = node.type.prop(NodeProp.isolate);
|
||
if (iso)
|
||
deco.add(node.from, node.to, marks[iso]);
|
||
},
|
||
from,
|
||
to
|
||
});
|
||
}
|
||
return deco.finish();
|
||
}
|
||
function clipRTLLines(ranges, doc) {
|
||
let cur = doc.iter(), pos = 0, result = [], last = null;
|
||
for (let { from, to } of ranges) {
|
||
if (last && last.to > from) {
|
||
from = last.to;
|
||
if (from >= to)
|
||
continue;
|
||
}
|
||
if (pos + cur.value.length < from) {
|
||
cur.next(from - (pos + cur.value.length));
|
||
pos = from;
|
||
}
|
||
for (; ; ) {
|
||
let start = pos, end = pos + cur.value.length;
|
||
if (!cur.lineBreak && buildForLine(cur.value)) {
|
||
if (last && last.to > start - 10)
|
||
last.to = Math.min(to, end);
|
||
else
|
||
result.push(last = { from: start, to: Math.min(to, end) });
|
||
}
|
||
if (end >= to)
|
||
break;
|
||
pos = end;
|
||
cur.next();
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
var marks = {
|
||
rtl: Decoration.mark({ class: "cm-iso", inclusive: true, attributes: { dir: "rtl" }, bidiIsolate: Direction.RTL }),
|
||
ltr: Decoration.mark({ class: "cm-iso", inclusive: true, attributes: { dir: "ltr" }, bidiIsolate: Direction.LTR }),
|
||
auto: Decoration.mark({ class: "cm-iso", inclusive: true, attributes: { dir: "auto" }, bidiIsolate: null })
|
||
};
|
||
|
||
export {
|
||
DefaultBufferLength,
|
||
NodeProp,
|
||
NodeType,
|
||
NodeSet,
|
||
IterMode,
|
||
Tree,
|
||
Parser,
|
||
styleTags,
|
||
tags,
|
||
LRLanguage,
|
||
syntaxTree,
|
||
LanguageSupport,
|
||
indentUnit,
|
||
getIndentUnit,
|
||
indentString,
|
||
getIndentation,
|
||
IndentContext,
|
||
indentNodeProp,
|
||
delimitedIndent,
|
||
flatIndent,
|
||
continuedIndent,
|
||
indentOnInput,
|
||
foldNodeProp,
|
||
foldInside,
|
||
foldKeymap,
|
||
foldGutter,
|
||
HighlightStyle,
|
||
syntaxHighlighting,
|
||
defaultHighlightStyle,
|
||
bracketMatching,
|
||
matchBrackets
|
||
};
|
||
//# sourceMappingURL=chunk-ELUT3ZLT.js.map
|