Files
topos/node_modules/.vite/deps/chunk-D63OSQ34.js

2212 lines
69 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
Decoration,
EditorView,
GutterMarker,
StyleModule,
ViewPlugin,
WidgetType,
gutter,
logException
} from "./chunk-LORPBXGU.js";
import {
EditorState,
Facet,
Prec,
RangeSet,
RangeSetBuilder,
StateEffect,
StateField,
combineConfig,
countColumn
} from "./chunk-MKFMOIK6.js";
import {
IterMode,
NodeProp,
NodeSet,
NodeType,
Parser,
Tree,
TreeFragment,
highlightTree,
styleTags,
tagHighlighter,
tags
} from "./chunk-BSVZPYOD.js";
// 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 = [], name = "") {
this.data = data;
this.name = name;
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, name) {
super(data, parser, [], name);
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, name) {
return new _LRLanguage(this.data, this.parser.configure(options), name || this.name);
}
get allowsNesting() {
return this.parser.hasWrappers();
}
};
function syntaxTree(state) {
let field = state.field(Language.state, false);
return field ? field.tree : Tree.empty;
}
function ensureSyntaxTree(state, upto, timeout = 50) {
var _a2;
let parse = (_a2 = state.field(Language.state, false)) === null || _a2 === void 0 ? void 0 : _a2.context;
if (!parse)
return null;
let oldVieport = parse.viewport;
parse.updateViewport({ from: 0, to: upto });
let result = parse.isDone(upto) || parse.work(timeout, upto) ? parse.tree : null;
parse.updateViewport(oldVieport);
return result;
}
function syntaxTreeAvailable(state, upto = state.doc.length) {
var _a2;
return ((_a2 = state.field(Language.state, false)) === null || _a2 === void 0 ? void 0 : _a2.context.isDone(upto)) || false;
}
function forceParsing(view, upto = view.viewport.to, timeout = 100) {
let success = ensureSyntaxTree(view.state, upto, timeout);
if (success != syntaxTree(view.state))
view.dispatch({});
return !!success;
}
function syntaxParserRunning(view) {
var _a2;
return ((_a2 = view.plugin(parseWorker)) === null || _a2 === void 0 ? void 0 : _a2.isWorking()) || false;
}
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
/* MaxPause */
);
return () => clearTimeout(timeout);
};
if (typeof requestIdleCallback != "undefined")
requestIdle = (callback) => {
let idle = -1, timeout = setTimeout(
() => {
idle = requestIdleCallback(callback, {
timeout: 500 - 100
/* MinPause */
});
},
100
/* 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) {
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
/* 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 LanguageDescription = class _LanguageDescription {
constructor(name, alias, extensions, filename, loadFunc, support = void 0) {
this.name = name;
this.alias = alias;
this.extensions = extensions;
this.filename = filename;
this.loadFunc = loadFunc;
this.support = support;
this.loading = null;
}
/**
Start loading the the language. Will return a promise that
resolves to a [`LanguageSupport`](https://codemirror.net/6/docs/ref/#language.LanguageSupport)
object when the language successfully loads.
*/
load() {
return this.loading || (this.loading = this.loadFunc().then((support) => this.support = support, (err) => {
this.loading = null;
throw err;
}));
}
/**
Create a language description.
*/
static of(spec) {
let { load, support } = spec;
if (!load) {
if (!support)
throw new RangeError("Must pass either 'load' or 'support' to LanguageDescription.of");
load = () => Promise.resolve(support);
}
return new _LanguageDescription(spec.name, (spec.alias || []).concat(spec.name).map((s) => s.toLowerCase()), spec.extensions || [], spec.filename, load, support);
}
/**
Look for a language in the given array of descriptions that
matches the filename. Will first match
[`filename`](https://codemirror.net/6/docs/ref/#language.LanguageDescription.filename) patterns,
and then [extensions](https://codemirror.net/6/docs/ref/#language.LanguageDescription.extensions),
and return the first language that matches.
*/
static matchFilename(descs, filename) {
for (let d of descs)
if (d.filename && d.filename.test(filename))
return d;
let ext = /\.([^.]+)$/.exec(filename);
if (ext) {
for (let d of descs)
if (d.extensions.indexOf(ext[1]) > -1)
return d;
}
return null;
}
/**
Look for a language whose name or alias matches the the given
name (case-insensitively). If `fuzzy` is true, and no direct
matchs is found, this'll also search for a language whose name
or alias occurs in the string (for names shorter than three
characters, only when surrounded by non-word characters).
*/
static matchLanguageName(descs, name, fuzzy = true) {
name = name.toLowerCase();
for (let d of descs)
if (d.alias.some((a) => a == name))
return d;
if (fuzzy)
for (let d of descs)
for (let a of d.alias) {
let found = name.indexOf(a);
if (found > -1 && (a.length > 2 || !/\w/.test(name[found - 1]) && !/\w/.test(name[found + a.length])))
return d;
}
return null;
}
};
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 ? syntaxIndentation(context, tree, pos) : null;
}
function indentRange(state, from, to) {
let updated = /* @__PURE__ */ Object.create(null);
let context = new IndentContext(state, { overrideIndentation: (start) => {
var _a2;
return (_a2 = updated[start]) !== null && _a2 !== void 0 ? _a2 : -1;
} });
let changes = [];
for (let pos = from; pos <= to; ) {
let line = state.doc.lineAt(pos);
pos = line.to + 1;
let indent = getIndentation(context, line.from);
if (indent == null)
continue;
if (!/\S/.test(line.text))
indent = 0;
let cur = /^\s*/.exec(line.text)[0];
let norm = indentString(state, indent);
if (cur != norm) {
updated[line.from] = indent;
changes.push({ from: line.from, to: line.from + cur.length, insert: norm });
}
}
return state.changes(changes);
}
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) {
return indentFrom(ast.resolveInner(pos).enterUnfinishedNodesBefore(pos), pos, cx);
}
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 indentFrom(node, pos, base) {
for (; node; node = node.parent) {
let strategy = indentStrategy(node);
if (strategy)
return strategy(TreeIndentContext.create(base, pos, node));
}
return null;
}
function topIndent() {
return 0;
}
var TreeIndentContext = class _TreeIndentContext extends IndentContext {
constructor(base, pos, node) {
super(base.state, base.options);
this.base = base;
this.pos = pos;
this.node = node;
}
/**
@internal
*/
static create(base, pos, node) {
return new _TreeIndentContext(base, pos, node);
}
/**
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() {
let parent = this.node.parent;
return parent ? indentFrom(parent, this.pos, this.base) : 0;
}
};
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)
return next.from < lineEnd ? openToken : null;
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 inner = tree.resolveInner(end, 1);
let found = null;
for (let cur = inner; cur; cur = cur.parent) {
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))
folded = folded.update({ add: [foldWidget.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 foldedRanges(state) {
return state.field(foldState, false) || RangeSet.empty;
}
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;
};
function foldableContainer(view, lineBlock) {
for (let line = lineBlock; ; ) {
let foldableRegion = foldable(view.state, line.from, line.to);
if (foldableRegion && foldableRegion.to > lineBlock.from)
return foldableRegion;
if (!line.from)
return null;
line = view.lineBlockAt(line.from - 1);
}
}
var toggleFold = (view) => {
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));
} else {
let foldRange = foldableContainer(view, line);
if (foldRange)
effects.push(foldEffect.of(foldRange), announceFold(view, foldRange));
}
}
if (effects.length > 0)
view.dispatch({ effects: maybeEnable(view.state, effects) });
return !!effects.length;
};
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,
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;
}
var foldWidget = Decoration.replace({ widget: new class extends WidgetType {
toDOM(view) {
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);
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 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;
}
function highlightingFor(state, tags2, scope) {
let highlighters = getHighlighters(state);
let result = null;
if (highlighters)
for (let highlighter of highlighters) {
if (!highlighter.scope || scope && highlighter.scope(scope)) {
let cls = highlighter.style(tags2);
if (cls)
result = result ? result + " " + cls : cls;
}
}
return result;
}
var TreeHighlighter = class {
constructor(view) {
this.markCache = /* @__PURE__ */ Object.create(null);
this.tree = syntaxTree(view.state);
this.decorations = this.buildDeco(view, getHighlighters(view.state));
}
update(update) {
let tree = syntaxTree(update.state), highlighters = getHighlighters(update.state);
let styleChange = highlighters != getHighlighters(update.startState);
if (tree.length < update.view.viewport.to && !styleChange && tree.type == this.tree.type) {
this.decorations = this.decorations.map(update.changes);
} else if (tree != this.tree || update.viewportChanged || styleChange) {
this.tree = tree;
this.decorations = this.buildDeco(update.view, highlighters);
}
}
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 bracket = brackets.indexOf(startCh);
if (bracket < 0 || bracket % 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 == bracket >> 1 };
} else {
depth--;
}
}
if (dir > 0)
distance += text.length;
}
return iter.done ? { start: startToken, matched: false } : null;
}
function countCol(string, end, tabSize, startIndex = 0, startValue = 0) {
if (end == null) {
end = string.search(/[^\s\u00a0]/);
if (end == -1)
end = string.length;
}
let n = startValue;
for (let i = startIndex; i < end; i++) {
if (string.charCodeAt(i) == 9)
n += tabSize - n % tabSize;
else
n++;
}
return n;
}
var StringStream = class {
/**
Create a stream.
*/
constructor(string, tabSize, indentUnit2, overrideIndent) {
this.string = string;
this.tabSize = tabSize;
this.indentUnit = indentUnit2;
this.overrideIndent = overrideIndent;
this.pos = 0;
this.start = 0;
this.lastColumnPos = 0;
this.lastColumnValue = 0;
}
/**
True if we are at the end of the line.
*/
eol() {
return this.pos >= this.string.length;
}
/**
True if we are at the start of the line.
*/
sol() {
return this.pos == 0;
}
/**
Get the next code unit after the current position, or undefined
if we're at the end of the line.
*/
peek() {
return this.string.charAt(this.pos) || void 0;
}
/**
Read the next code unit and advance `this.pos`.
*/
next() {
if (this.pos < this.string.length)
return this.string.charAt(this.pos++);
}
/**
Match the next character against the given string, regular
expression, or predicate. Consume and return it if it matches.
*/
eat(match) {
let ch = this.string.charAt(this.pos);
let ok;
if (typeof match == "string")
ok = ch == match;
else
ok = ch && (match instanceof RegExp ? match.test(ch) : match(ch));
if (ok) {
++this.pos;
return ch;
}
}
/**
Continue matching characters that match the given string,
regular expression, or predicate function. Return true if any
characters were consumed.
*/
eatWhile(match) {
let start = this.pos;
while (this.eat(match)) {
}
return this.pos > start;
}
/**
Consume whitespace ahead of `this.pos`. Return true if any was
found.
*/
eatSpace() {
let start = this.pos;
while (/[\s\u00a0]/.test(this.string.charAt(this.pos)))
++this.pos;
return this.pos > start;
}
/**
Move to the end of the line.
*/
skipToEnd() {
this.pos = this.string.length;
}
/**
Move to directly before the given character, if found on the
current line.
*/
skipTo(ch) {
let found = this.string.indexOf(ch, this.pos);
if (found > -1) {
this.pos = found;
return true;
}
}
/**
Move back `n` characters.
*/
backUp(n) {
this.pos -= n;
}
/**
Get the column position at `this.pos`.
*/
column() {
if (this.lastColumnPos < this.start) {
this.lastColumnValue = countCol(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
this.lastColumnPos = this.start;
}
return this.lastColumnValue;
}
/**
Get the indentation column of the current line.
*/
indentation() {
var _a2;
return (_a2 = this.overrideIndent) !== null && _a2 !== void 0 ? _a2 : countCol(this.string, null, this.tabSize);
}
/**
Match the input against the given string or regular expression
(which should start with a `^`). Return true or the regexp match
if it matches.
Unless `consume` is set to `false`, this will move `this.pos`
past the matched text.
When matching a string `caseInsensitive` can be set to true to
make the match case-insensitive.
*/
match(pattern, consume, caseInsensitive) {
if (typeof pattern == "string") {
let cased = (str) => caseInsensitive ? str.toLowerCase() : str;
let substr = this.string.substr(this.pos, pattern.length);
if (cased(substr) == cased(pattern)) {
if (consume !== false)
this.pos += pattern.length;
return true;
} else
return null;
} else {
let match = this.string.slice(this.pos).match(pattern);
if (match && match.index > 0)
return null;
if (match && consume !== false)
this.pos += match[0].length;
return match;
}
}
/**
Get the current token.
*/
current() {
return this.string.slice(this.start, this.pos);
}
};
function fullParser(spec) {
return {
name: spec.name || "",
token: spec.token,
blankLine: spec.blankLine || (() => {
}),
startState: spec.startState || (() => true),
copyState: spec.copyState || defaultCopyState,
indent: spec.indent || (() => null),
languageData: spec.languageData || {},
tokenTable: spec.tokenTable || noTokens
};
}
function defaultCopyState(state) {
if (typeof state != "object")
return state;
let newState = {};
for (let prop in state) {
let val = state[prop];
newState[prop] = val instanceof Array ? val.slice() : val;
}
return newState;
}
var IndentedFrom = /* @__PURE__ */ new WeakMap();
var StreamLanguage = class _StreamLanguage extends Language {
constructor(parser) {
let data = defineLanguageFacet(parser.languageData);
let p = fullParser(parser), self;
let impl = new class extends Parser {
createParse(input, fragments, ranges) {
return new Parse(self, input, fragments, ranges);
}
}();
super(data, impl, [indentService.of((cx, pos) => this.getIndent(cx, pos))], parser.name);
this.topNode = docID(data);
self = this;
this.streamParser = p;
this.stateAfter = new NodeProp({ perNode: true });
this.tokenTable = parser.tokenTable ? new TokenTable(p.tokenTable) : defaultTokenTable;
}
/**
Define a stream language.
*/
static define(spec) {
return new _StreamLanguage(spec);
}
getIndent(cx, pos) {
let tree = syntaxTree(cx.state), at = tree.resolve(pos);
while (at && at.type != this.topNode)
at = at.parent;
if (!at)
return null;
let from = void 0;
let { overrideIndentation } = cx.options;
if (overrideIndentation) {
from = IndentedFrom.get(cx.state);
if (from != null && from < pos - 1e4)
from = void 0;
}
let start = findState(this, tree, 0, at.from, from !== null && from !== void 0 ? from : pos), statePos, state;
if (start) {
state = start.state;
statePos = start.pos + 1;
} else {
state = this.streamParser.startState(cx.unit);
statePos = 0;
}
if (pos - statePos > 1e4)
return null;
while (statePos < pos) {
let line2 = cx.state.doc.lineAt(statePos), end = Math.min(pos, line2.to);
if (line2.length) {
let indentation = overrideIndentation ? overrideIndentation(line2.from) : -1;
let stream = new StringStream(line2.text, cx.state.tabSize, cx.unit, indentation < 0 ? void 0 : indentation);
while (stream.pos < end - line2.from)
readToken(this.streamParser.token, stream, state);
} else {
this.streamParser.blankLine(state, cx.unit);
}
if (end == pos)
break;
statePos = line2.to + 1;
}
let line = cx.lineAt(pos);
if (overrideIndentation && from == null)
IndentedFrom.set(cx.state, line.from);
return this.streamParser.indent(state, /^\s*(.*)/.exec(line.text)[1], cx);
}
get allowsNesting() {
return false;
}
};
function findState(lang, tree, off, startPos, before) {
let state = off >= startPos && off + tree.length <= before && tree.prop(lang.stateAfter);
if (state)
return { state: lang.streamParser.copyState(state), pos: off + tree.length };
for (let i = tree.children.length - 1; i >= 0; i--) {
let child = tree.children[i], pos = off + tree.positions[i];
let found = child instanceof Tree && pos < before && findState(lang, child, pos, startPos, before);
if (found)
return found;
}
return null;
}
function cutTree(lang, tree, from, to, inside) {
if (inside && from <= 0 && to >= tree.length)
return tree;
if (!inside && tree.type == lang.topNode)
inside = true;
for (let i = tree.children.length - 1; i >= 0; i--) {
let pos = tree.positions[i], child = tree.children[i], inner;
if (pos < to && child instanceof Tree) {
if (!(inner = cutTree(lang, child, from - pos, to - pos, inside)))
break;
return !inside ? inner : new Tree(tree.type, tree.children.slice(0, i).concat(inner), tree.positions.slice(0, i + 1), pos + inner.length);
}
}
return null;
}
function findStartInFragments(lang, fragments, startPos, editorState) {
for (let f of fragments) {
let from = f.from + (f.openStart ? 25 : 0), to = f.to - (f.openEnd ? 25 : 0);
let found = from <= startPos && to > startPos && findState(lang, f.tree, 0 - f.offset, startPos, to), tree;
if (found && (tree = cutTree(lang, f.tree, startPos + f.offset, found.pos + f.offset, false)))
return { state: found.state, tree };
}
return { state: lang.streamParser.startState(editorState ? getIndentUnit(editorState) : 4), tree: Tree.empty };
}
var Parse = class {
constructor(lang, input, fragments, ranges) {
this.lang = lang;
this.input = input;
this.fragments = fragments;
this.ranges = ranges;
this.stoppedAt = null;
this.chunks = [];
this.chunkPos = [];
this.chunk = [];
this.chunkReused = void 0;
this.rangeIndex = 0;
this.to = ranges[ranges.length - 1].to;
let context = ParseContext.get(), from = ranges[0].from;
let { state, tree } = findStartInFragments(lang, fragments, from, context === null || context === void 0 ? void 0 : context.state);
this.state = state;
this.parsedPos = this.chunkStart = from + tree.length;
for (let i = 0; i < tree.children.length; i++) {
this.chunks.push(tree.children[i]);
this.chunkPos.push(tree.positions[i]);
}
if (context && this.parsedPos < context.viewport.from - 1e5) {
this.state = this.lang.streamParser.startState(getIndentUnit(context.state));
context.skipUntilInView(this.parsedPos, context.viewport.from);
this.parsedPos = context.viewport.from;
}
this.moveRangeIndex();
}
advance() {
let context = ParseContext.get();
let parseEnd = this.stoppedAt == null ? this.to : Math.min(this.to, this.stoppedAt);
let end = Math.min(
parseEnd,
this.chunkStart + 2048
/* ChunkSize */
);
if (context)
end = Math.min(end, context.viewport.to);
while (this.parsedPos < end)
this.parseLine(context);
if (this.chunkStart < this.parsedPos)
this.finishChunk();
if (this.parsedPos >= parseEnd)
return this.finish();
if (context && this.parsedPos >= context.viewport.to) {
context.skipUntilInView(this.parsedPos, parseEnd);
return this.finish();
}
return null;
}
stopAt(pos) {
this.stoppedAt = pos;
}
lineAfter(pos) {
let chunk = this.input.chunk(pos);
if (!this.input.lineChunks) {
let eol = chunk.indexOf("\n");
if (eol > -1)
chunk = chunk.slice(0, eol);
} else if (chunk == "\n") {
chunk = "";
}
return pos + chunk.length <= this.to ? chunk : chunk.slice(0, this.to - pos);
}
nextLine() {
let from = this.parsedPos, line = this.lineAfter(from), end = from + line.length;
for (let index = this.rangeIndex; ; ) {
let rangeEnd = this.ranges[index].to;
if (rangeEnd >= end)
break;
line = line.slice(0, rangeEnd - (end - line.length));
index++;
if (index == this.ranges.length)
break;
let rangeStart = this.ranges[index].from;
let after = this.lineAfter(rangeStart);
line += after;
end = rangeStart + after.length;
}
return { line, end };
}
skipGapsTo(pos, offset, side) {
for (; ; ) {
let end = this.ranges[this.rangeIndex].to, offPos = pos + offset;
if (side > 0 ? end > offPos : end >= offPos)
break;
let start = this.ranges[++this.rangeIndex].from;
offset += start - end;
}
return offset;
}
moveRangeIndex() {
while (this.ranges[this.rangeIndex].to < this.parsedPos)
this.rangeIndex++;
}
emitToken(id, from, to, size, offset) {
if (this.ranges.length > 1) {
offset = this.skipGapsTo(from, offset, 1);
from += offset;
let len0 = this.chunk.length;
offset = this.skipGapsTo(to, offset, -1);
to += offset;
size += this.chunk.length - len0;
}
this.chunk.push(id, from, to, size);
return offset;
}
parseLine(context) {
let { line, end } = this.nextLine(), offset = 0, { streamParser } = this.lang;
let stream = new StringStream(line, context ? context.state.tabSize : 4, context ? getIndentUnit(context.state) : 2);
if (stream.eol()) {
streamParser.blankLine(this.state, stream.indentUnit);
} else {
while (!stream.eol()) {
let token = readToken(streamParser.token, stream, this.state);
if (token)
offset = this.emitToken(this.lang.tokenTable.resolve(token), this.parsedPos + stream.start, this.parsedPos + stream.pos, 4, offset);
if (stream.start > 1e4)
break;
}
}
this.parsedPos = end;
this.moveRangeIndex();
if (this.parsedPos < this.to)
this.parsedPos++;
}
finishChunk() {
let tree = Tree.build({
buffer: this.chunk,
start: this.chunkStart,
length: this.parsedPos - this.chunkStart,
nodeSet,
topID: 0,
maxBufferLength: 2048,
reused: this.chunkReused
});
tree = new Tree(tree.type, tree.children, tree.positions, tree.length, [[this.lang.stateAfter, this.lang.streamParser.copyState(this.state)]]);
this.chunks.push(tree);
this.chunkPos.push(this.chunkStart - this.ranges[0].from);
this.chunk = [];
this.chunkReused = void 0;
this.chunkStart = this.parsedPos;
}
finish() {
return new Tree(this.lang.topNode, this.chunks, this.chunkPos, this.parsedPos - this.ranges[0].from).balance();
}
};
function readToken(token, stream, state) {
stream.start = stream.pos;
for (let i = 0; i < 10; i++) {
let result = token(stream, state);
if (stream.pos > stream.start)
return result;
}
throw new Error("Stream parser failed to advance stream.");
}
var noTokens = /* @__PURE__ */ Object.create(null);
var typeArray = [NodeType.none];
var nodeSet = new NodeSet(typeArray);
var warned = [];
var defaultTable = /* @__PURE__ */ Object.create(null);
for (let [legacyName, name] of [
["variable", "variableName"],
["variable-2", "variableName.special"],
["string-2", "string.special"],
["def", "variableName.definition"],
["tag", "tagName"],
["attribute", "attributeName"],
["type", "typeName"],
["builtin", "variableName.standard"],
["qualifier", "modifier"],
["error", "invalid"],
["header", "heading"],
["property", "propertyName"]
])
defaultTable[legacyName] = createTokenType(noTokens, name);
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 tag = null;
for (let part of tagStr.split(".")) {
let value = extra[part] || tags[part];
if (!value) {
warnForPart(part, `Unknown highlighting tag ${part}`);
} else if (typeof value == "function") {
if (!tag)
warnForPart(part, `Modifier ${part} used at start of tag`);
else
tag = value(tag);
} else {
if (tag)
warnForPart(part, `Tag ${part} used as modifier`);
else
tag = value;
}
}
if (!tag)
return 0;
let name = tagStr.replace(/ /g, "_"), type = NodeType.define({
id: typeArray.length,
name,
props: [styleTags({ [name]: tag })]
});
typeArray.push(type);
return type.id;
}
function docID(data) {
let type = NodeType.define({ id: typeArray.length, name: "Document", props: [languageDataProp.add(() => data)] });
typeArray.push(type);
return type;
}
export {
languageDataProp,
defineLanguageFacet,
sublanguageProp,
Language,
LRLanguage,
syntaxTree,
ensureSyntaxTree,
syntaxTreeAvailable,
forceParsing,
syntaxParserRunning,
DocInput,
ParseContext,
language,
LanguageSupport,
LanguageDescription,
indentService,
indentUnit,
getIndentUnit,
indentString,
getIndentation,
indentRange,
IndentContext,
indentNodeProp,
TreeIndentContext,
delimitedIndent,
flatIndent,
continuedIndent,
indentOnInput,
foldService,
foldNodeProp,
foldInside,
foldable,
foldEffect,
unfoldEffect,
foldState,
foldedRanges,
foldCode,
unfoldCode,
foldAll,
unfoldAll,
toggleFold,
foldKeymap,
codeFolding,
foldGutter,
HighlightStyle,
syntaxHighlighting,
highlightingFor,
defaultHighlightStyle,
bracketMatching,
bracketMatchingHandle,
matchBrackets,
StringStream,
StreamLanguage
};
//# sourceMappingURL=chunk-D63OSQ34.js.map