basant307/AI_Governance_Project
048
1'use strict';2 3var common = require('@lezer/common');4var state = require('@codemirror/state');5var view = require('@codemirror/view');6var highlight = require('@lezer/highlight');7var styleMod = require('style-mod');8 9var _a;10/**11Node prop stored in a parser's top syntax node to provide the12facet that stores language-specific data for that language.13*/14const languageDataProp = new common.NodeProp();15/**16Helper function to define a facet (to be added to the top syntax17node(s) for a language via18[`languageDataProp`](https://codemirror.net/6/docs/ref/#language.languageDataProp)), that will be19used to associate language data with the language. You20probably only need this when subclassing21[`Language`](https://codemirror.net/6/docs/ref/#language.Language).22*/23function defineLanguageFacet(baseData) {24 return state.Facet.define({25 combine: baseData ? values => values.concat(baseData) : undefined26 });27}28/**29Syntax node prop used to register sublanguages. Should be added to30the top level node type for the language.31*/32const sublanguageProp = new common.NodeProp();33/**34A language object manages parsing and per-language35[metadata](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt). Parse data is36managed as a [Lezer](https://lezer.codemirror.net) tree. The class37can be used directly, via the [`LRLanguage`](https://codemirror.net/6/docs/ref/#language.LRLanguage)38subclass for [Lezer](https://lezer.codemirror.net/) LR parsers, or39via the [`StreamLanguage`](https://codemirror.net/6/docs/ref/#language.StreamLanguage) subclass40for stream parsers.41*/42class Language {43 /**44 Construct a language object. If you need to invoke this45 directly, first define a data facet with46 [`defineLanguageFacet`](https://codemirror.net/6/docs/ref/#language.defineLanguageFacet), and then47 configure your parser to [attach](https://codemirror.net/6/docs/ref/#language.languageDataProp) it48 to the language's outer syntax node.49 */50 constructor(51 /**52 The [language data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt) facet53 used for this language.54 */55 data, parser, extraExtensions = [], 56 /**57 A language name.58 */59 name = "") {60 this.data = data;61 this.name = name;62 // Kludge to define EditorState.tree as a debugging helper,63 // without the EditorState package actually knowing about64 // languages and lezer trees.65 if (!state.EditorState.prototype.hasOwnProperty("tree"))66 Object.defineProperty(state.EditorState.prototype, "tree", { get() { return syntaxTree(this); } });67 this.parser = parser;68 this.extension = [69 language.of(this),70 state.EditorState.languageData.of((state, pos, side) => {71 let top = topNodeAt(state, pos, side), data = top.type.prop(languageDataProp);72 if (!data)73 return [];74 let base = state.facet(data), sub = top.type.prop(sublanguageProp);75 if (sub) {76 let innerNode = top.resolve(pos - top.from, side);77 for (let sublang of sub)78 if (sublang.test(innerNode, state)) {79 let data = state.facet(sublang.facet);80 return sublang.type == "replace" ? data : data.concat(base);81 }82 }83 return base;84 })85 ].concat(extraExtensions);86 }87 /**88 Query whether this language is active at the given position.89 */90 isActiveAt(state, pos, side = -1) {91 return topNodeAt(state, pos, side).type.prop(languageDataProp) == this.data;92 }93 /**94 Find the document regions that were parsed using this language.95 The returned regions will _include_ any nested languages rooted96 in this language, when those exist.97 */98 findRegions(state) {99 let lang = state.facet(language);100 if ((lang === null || lang === void 0 ? void 0 : lang.data) == this.data)101 return [{ from: 0, to: state.doc.length }];102 if (!lang || !lang.allowsNesting)103 return [];104 let result = [];105 let explore = (tree, from) => {106 if (tree.prop(languageDataProp) == this.data) {107 result.push({ from, to: from + tree.length });108 return;109 }110 let mount = tree.prop(common.NodeProp.mounted);111 if (mount) {112 if (mount.tree.prop(languageDataProp) == this.data) {113 if (mount.overlay)114 for (let r of mount.overlay)115 result.push({ from: r.from + from, to: r.to + from });116 else117 result.push({ from: from, to: from + tree.length });118 return;119 }120 else if (mount.overlay) {121 let size = result.length;122 explore(mount.tree, mount.overlay[0].from + from);123 if (result.length > size)124 return;125 }126 }127 for (let i = 0; i < tree.children.length; i++) {128 let ch = tree.children[i];129 if (ch instanceof common.Tree)130 explore(ch, tree.positions[i] + from);131 }132 };133 explore(syntaxTree(state), 0);134 return result;135 }136 /**137 Indicates whether this language allows nested languages. The138 default implementation returns true.139 */140 get allowsNesting() { return true; }141}142/**143@internal144*/145Language.setState = state.StateEffect.define();146function topNodeAt(state, pos, side) {147 let topLang = state.facet(language), tree = syntaxTree(state).topNode;148 if (!topLang || topLang.allowsNesting) {149 for (let node = tree; node; node = node.enter(pos, side, common.IterMode.ExcludeBuffers | common.IterMode.EnterBracketed))150 if (node.type.isTop)151 tree = node;152 }153 return tree;154}155/**156A subclass of [`Language`](https://codemirror.net/6/docs/ref/#language.Language) for use with Lezer157[LR parsers](https://lezer.codemirror.net/docs/ref#lr.LRParser)158parsers.159*/160class LRLanguage extends Language {161 constructor(data, parser, name) {162 super(data, parser, [], name);163 this.parser = parser;164 }165 /**166 Define a language from a parser.167 */168 static define(spec) {169 let data = defineLanguageFacet(spec.languageData);170 return new LRLanguage(data, spec.parser.configure({171 props: [languageDataProp.add(type => type.isTop ? data : undefined)]172 }), spec.name);173 }174 /**175 Create a new instance of this language with a reconfigured176 version of its parser and optionally a new name.177 */178 configure(options, name) {179 return new LRLanguage(this.data, this.parser.configure(options), name || this.name);180 }181 get allowsNesting() { return this.parser.hasWrappers(); }182}183/**184Get the syntax tree for a state, which is the current (possibly185incomplete) parse tree of the active186[language](https://codemirror.net/6/docs/ref/#language.Language), or the empty tree if there is no187language available.188*/189function syntaxTree(state) {190 let field = state.field(Language.state, false);191 return field ? field.tree : common.Tree.empty;192}193/**194Try to get a parse tree that spans at least up to `upto`. The195method will do at most `timeout` milliseconds of work to parse196up to that point if the tree isn't already available.197*/198function ensureSyntaxTree(state, upto, timeout = 50) {199 var _a;200 let parse = (_a = state.field(Language.state, false)) === null || _a === void 0 ? void 0 : _a.context;201 if (!parse)202 return null;203 let oldVieport = parse.viewport;204 parse.updateViewport({ from: 0, to: upto });205 let result = parse.isDone(upto) || parse.work(timeout, upto) ? parse.tree : null;206 parse.updateViewport(oldVieport);207 return result;208}209/**210Queries whether there is a full syntax tree available up to the211given document position. If there isn't, the background parse212process _might_ still be working and update the tree further, but213there is no guarantee of that—the parser will [stop214working](https://codemirror.net/6/docs/ref/#language.syntaxParserRunning) when it has spent a215certain amount of time or has moved beyond the visible viewport.216Always returns false if no language has been enabled.217*/218function syntaxTreeAvailable(state, upto = state.doc.length) {219 var _a;220 return ((_a = state.field(Language.state, false)) === null || _a === void 0 ? void 0 : _a.context.isDone(upto)) || false;221}222/**223Move parsing forward, and update the editor state afterwards to224reflect the new tree. Will work for at most `timeout`225milliseconds. Returns true if the parser managed get to the given226position in that time.227*/228function forceParsing(view, upto = view.viewport.to, timeout = 100) {229 let success = ensureSyntaxTree(view.state, upto, timeout);230 if (success != syntaxTree(view.state))231 view.dispatch({});232 return !!success;233}234/**235Tells you whether the language parser is planning to do more236parsing work (in a `requestIdleCallback` pseudo-thread) or has237stopped running, either because it parsed the entire document,238because it spent too much time and was cut off, or because there239is no language parser enabled.240*/241function syntaxParserRunning(view) {242 var _a;243 return ((_a = view.plugin(parseWorker)) === null || _a === void 0 ? void 0 : _a.isWorking()) || false;244}245/**246Lezer-style247[`Input`](https://lezer.codemirror.net/docs/ref#common.Input)248object for a [`Text`](https://codemirror.net/6/docs/ref/#state.Text) object.249*/250class DocInput {251 /**252 Create an input object for the given document.253 */254 constructor(doc) {255 this.doc = doc;256 this.cursorPos = 0;257 this.string = "";258 this.cursor = doc.iter();259 }260 get length() { return this.doc.length; }261 syncTo(pos) {262 this.string = this.cursor.next(pos - this.cursorPos).value;263 this.cursorPos = pos + this.string.length;264 return this.cursorPos - this.string.length;265 }266 chunk(pos) {267 this.syncTo(pos);268 return this.string;269 }270 get lineChunks() { return true; }271 read(from, to) {272 let stringStart = this.cursorPos - this.string.length;273 if (from < stringStart || to >= this.cursorPos)274 return this.doc.sliceString(from, to);275 else276 return this.string.slice(from - stringStart, to - stringStart);277 }278}279let currentContext = null;280/**281A parse context provided to parsers working on the editor content.282*/283class ParseContext {284 constructor(parser, 285 /**286 The current editor state.287 */288 state, 289 /**290 Tree fragments that can be reused by incremental re-parses.291 */292 fragments = [], 293 /**294 @internal295 */296 tree, 297 /**298 @internal299 */300 treeLen, 301 /**302 The current editor viewport (or some overapproximation303 thereof). Intended to be used for opportunistically avoiding304 work (in which case305 [`skipUntilInView`](https://codemirror.net/6/docs/ref/#language.ParseContext.skipUntilInView)306 should be called to make sure the parser is restarted when the307 skipped region becomes visible).308 */309 viewport, 310 /**311 @internal312 */313 skipped, 314 /**315 This is where skipping parsers can register a promise that,316 when resolved, will schedule a new parse. It is cleared when317 the parse worker picks up the promise. @internal318 */319 scheduleOn) {320 this.parser = parser;321 this.state = state;322 this.fragments = fragments;323 this.tree = tree;324 this.treeLen = treeLen;325 this.viewport = viewport;326 this.skipped = skipped;327 this.scheduleOn = scheduleOn;328 this.parse = null;329 /**330 @internal331 */332 this.tempSkipped = [];333 }334 /**335 @internal336 */337 static create(parser, state, viewport) {338 return new ParseContext(parser, state, [], common.Tree.empty, 0, viewport, [], null);339 }340 startParse() {341 return this.parser.startParse(new DocInput(this.state.doc), this.fragments);342 }343 /**344 @internal345 */346 work(until, upto) {347 if (upto != null && upto >= this.state.doc.length)348 upto = undefined;349 if (this.tree != common.Tree.empty && this.isDone(upto !== null && upto !== void 0 ? upto : this.state.doc.length)) {350 this.takeTree();351 return true;352 }353 return this.withContext(() => {354 var _a;355 if (typeof until == "number") {356 let endTime = Date.now() + until;357 until = () => Date.now() > endTime;358 }359 if (!this.parse)360 this.parse = this.startParse();361 if (upto != null && (this.parse.stoppedAt == null || this.parse.stoppedAt > upto) &&362 upto < this.state.doc.length)363 this.parse.stopAt(upto);364 for (;;) {365 let done = this.parse.advance();366 if (done) {367 this.fragments = this.withoutTempSkipped(common.TreeFragment.addTree(done, this.fragments, this.parse.stoppedAt != null));368 this.treeLen = (_a = this.parse.stoppedAt) !== null && _a !== void 0 ? _a : this.state.doc.length;369 this.tree = done;370 this.parse = null;371 if (this.treeLen < (upto !== null && upto !== void 0 ? upto : this.state.doc.length))372 this.parse = this.startParse();373 else374 return true;375 }376 if (until())377 return false;378 }379 });380 }381 /**382 @internal383 */384 takeTree() {385 let pos, tree;386 if (this.parse && (pos = this.parse.parsedPos) >= this.treeLen) {387 if (this.parse.stoppedAt == null || this.parse.stoppedAt > pos)388 this.parse.stopAt(pos);389 this.withContext(() => { while (!(tree = this.parse.advance())) { } });390 this.treeLen = pos;391 this.tree = tree;392 this.fragments = this.withoutTempSkipped(common.TreeFragment.addTree(this.tree, this.fragments, true));393 this.parse = null;394 }395 }396 withContext(f) {397 let prev = currentContext;398 currentContext = this;399 try {400 return f();401 }402 finally {403 currentContext = prev;404 }405 }406 withoutTempSkipped(fragments) {407 for (let r; r = this.tempSkipped.pop();)408 fragments = cutFragments(fragments, r.from, r.to);409 return fragments;410 }411 /**412 @internal413 */414 changes(changes, newState) {415 let { fragments, tree, treeLen, viewport, skipped } = this;416 this.takeTree();417 if (!changes.empty) {418 let ranges = [];419 changes.iterChangedRanges((fromA, toA, fromB, toB) => ranges.push({ fromA, toA, fromB, toB }));420 fragments = common.TreeFragment.applyChanges(fragments, ranges);421 tree = common.Tree.empty;422 treeLen = 0;423 viewport = { from: changes.mapPos(viewport.from, -1), to: changes.mapPos(viewport.to, 1) };424 if (this.skipped.length) {425 skipped = [];426 for (let r of this.skipped) {427 let from = changes.mapPos(r.from, 1), to = changes.mapPos(r.to, -1);428 if (from < to)429 skipped.push({ from, to });430 }431 }432 }433 return new ParseContext(this.parser, newState, fragments, tree, treeLen, viewport, skipped, this.scheduleOn);434 }435 /**436 @internal437 */438 updateViewport(viewport) {439 if (this.viewport.from == viewport.from && this.viewport.to == viewport.to)440 return false;441 this.viewport = viewport;442 let startLen = this.skipped.length;443 for (let i = 0; i < this.skipped.length; i++) {444 let { from, to } = this.skipped[i];445 if (from < viewport.to && to > viewport.from) {446 this.fragments = cutFragments(this.fragments, from, to);447 this.skipped.splice(i--, 1);448 }449 }450 if (this.skipped.length >= startLen)451 return false;452 this.reset();453 return true;454 }455 /**456 @internal457 */458 reset() {459 if (this.parse) {460 this.takeTree();461 this.parse = null;462 }463 }464 /**465 Notify the parse scheduler that the given region was skipped466 because it wasn't in view, and the parse should be restarted467 when it comes into view.468 */469 skipUntilInView(from, to) {470 this.skipped.push({ from, to });471 }472 /**473 Returns a parser intended to be used as placeholder when474 asynchronously loading a nested parser. It'll skip its input and475 mark it as not-really-parsed, so that the next update will parse476 it again.477 478 When `until` is given, a reparse will be scheduled when that479 promise resolves.480 */481 static getSkippingParser(until) {482 return new class extends common.Parser {483 createParse(input, fragments, ranges) {484 let from = ranges[0].from, to = ranges[ranges.length - 1].to;485 let parser = {486 parsedPos: from,487 advance() {488 let cx = currentContext;489 if (cx) {490 for (let r of ranges)491 cx.tempSkipped.push(r);492 if (until)493 cx.scheduleOn = cx.scheduleOn ? Promise.all([cx.scheduleOn, until]) : until;494 }495 this.parsedPos = to;496 return new common.Tree(common.NodeType.none, [], [], to - from);497 },498 stoppedAt: null,499 stopAt() { }500 };501 return parser;502 }503 };504 }505 /**506 @internal507 */508 isDone(upto) {509 upto = Math.min(upto, this.state.doc.length);510 let frags = this.fragments;511 return this.treeLen >= upto && frags.length && frags[0].from == 0 && frags[0].to >= upto;512 }513 /**514 Get the context for the current parse, or `null` if no editor515 parse is in progress.516 */517 static get() { return currentContext; }518}519function cutFragments(fragments, from, to) {520 return common.TreeFragment.applyChanges(fragments, [{ fromA: from, toA: to, fromB: from, toB: to }]);521}522class LanguageState {523 constructor(524 // A mutable parse state that is used to preserve work done during525 // the lifetime of a state when moving to the next state.526 context) {527 this.context = context;528 this.tree = context.tree;529 }530 apply(tr) {531 if (!tr.docChanged && this.tree == this.context.tree)532 return this;533 let newCx = this.context.changes(tr.changes, tr.state);534 // If the previous parse wasn't done, go forward only up to its535 // end position or the end of the viewport, to avoid slowing down536 // state updates with parse work beyond the viewport.537 let upto = this.context.treeLen == tr.startState.doc.length ? undefined538 : Math.max(tr.changes.mapPos(this.context.treeLen), newCx.viewport.to);539 if (!newCx.work(20 /* Work.Apply */, upto))540 newCx.takeTree();541 return new LanguageState(newCx);542 }543 static init(state) {544 let vpTo = Math.min(3000 /* Work.InitViewport */, state.doc.length);545 let parseState = ParseContext.create(state.facet(language).parser, state, { from: 0, to: vpTo });546 if (!parseState.work(20 /* Work.Apply */, vpTo))547 parseState.takeTree();548 return new LanguageState(parseState);549 }550}551Language.state = state.StateField.define({552 create: LanguageState.init,553 update(value, tr) {554 for (let e of tr.effects)555 if (e.is(Language.setState))556 return e.value;557 if (tr.startState.facet(language) != tr.state.facet(language))558 return LanguageState.init(tr.state);559 return value.apply(tr);560 }561});562let requestIdle = (callback) => {563 let timeout = setTimeout(() => callback(), 500 /* Work.MaxPause */);564 return () => clearTimeout(timeout);565};566if (typeof requestIdleCallback != "undefined")567 requestIdle = (callback) => {568 let idle = -1, timeout = setTimeout(() => {569 idle = requestIdleCallback(callback, { timeout: 500 /* Work.MaxPause */ - 100 /* Work.MinPause */ });570 }, 100 /* Work.MinPause */);571 return () => idle < 0 ? clearTimeout(timeout) : cancelIdleCallback(idle);572 };573const isInputPending = typeof navigator != "undefined" && ((_a = navigator.scheduling) === null || _a === void 0 ? void 0 : _a.isInputPending)574 ? () => navigator.scheduling.isInputPending() : null;575const parseWorker = view.ViewPlugin.fromClass(class ParseWorker {576 constructor(view) {577 this.view = view;578 this.working = null;579 this.workScheduled = 0;580 // End of the current time chunk581 this.chunkEnd = -1;582 // Milliseconds of budget left for this chunk583 this.chunkBudget = -1;584 this.work = this.work.bind(this);585 this.scheduleWork();586 }587 update(update) {588 let cx = this.view.state.field(Language.state).context;589 if (cx.updateViewport(update.view.viewport) || this.view.viewport.to > cx.treeLen)590 this.scheduleWork();591 if (update.docChanged || update.selectionSet) {592 if (this.view.hasFocus)593 this.chunkBudget += 50 /* Work.ChangeBonus */;594 this.scheduleWork();595 }596 this.checkAsyncSchedule(cx);597 }598 scheduleWork() {599 if (this.working)600 return;601 let { state } = this.view, field = state.field(Language.state);602 if (field.tree != field.context.tree || !field.context.isDone(state.doc.length))603 this.working = requestIdle(this.work);604 }605 work(deadline) {606 this.working = null;607 let now = Date.now();608 if (this.chunkEnd < now && (this.chunkEnd < 0 || this.view.hasFocus)) { // Start a new chunk609 this.chunkEnd = now + 30000 /* Work.ChunkTime */;610 this.chunkBudget = 3000 /* Work.ChunkBudget */;611 }612 if (this.chunkBudget <= 0)613 return; // No more budget614 let { state, viewport: { to: vpTo } } = this.view, field = state.field(Language.state);615 if (field.tree == field.context.tree && field.context.isDone(vpTo + 100000 /* Work.MaxParseAhead */))616 return;617 let endTime = Date.now() + Math.min(this.chunkBudget, 100 /* Work.Slice */, deadline && !isInputPending ? Math.max(25 /* Work.MinSlice */, deadline.timeRemaining() - 5) : 1e9);618 let viewportFirst = field.context.treeLen < vpTo && state.doc.length > vpTo + 1000;619 let done = field.context.work(() => {620 return isInputPending && isInputPending() || Date.now() > endTime;621 }, vpTo + (viewportFirst ? 0 : 100000 /* Work.MaxParseAhead */));622 this.chunkBudget -= Date.now() - now;623 if (done || this.chunkBudget <= 0) {624 field.context.takeTree();625 this.view.dispatch({ effects: Language.setState.of(new LanguageState(field.context)) });626 }627 if (this.chunkBudget > 0 && !(done && !viewportFirst))628 this.scheduleWork();629 this.checkAsyncSchedule(field.context);630 }631 checkAsyncSchedule(cx) {632 if (cx.scheduleOn) {633 this.workScheduled++;634 cx.scheduleOn635 .then(() => this.scheduleWork())636 .catch(err => view.logException(this.view.state, err))637 .then(() => this.workScheduled--);638 cx.scheduleOn = null;639 }640 }641 destroy() {642 if (this.working)643 this.working();644 }645 isWorking() {646 return !!(this.working || this.workScheduled > 0);647 }648}, {649 eventHandlers: { focus() { this.scheduleWork(); } }650});651/**652The facet used to associate a language with an editor state. Used653by `Language` object's `extension` property (so you don't need to654manually wrap your languages in this). Can be used to access the655current language on a state.656*/657const language = state.Facet.define({658 combine(languages) { return languages.length ? languages[0] : null; },659 enables: language => [660 Language.state,661 parseWorker,662 view.EditorView.contentAttributes.compute([language], state => {663 let lang = state.facet(language);664 return lang && lang.name ? { "data-language": lang.name } : {};665 })666 ]667});668/**669This class bundles a [language](https://codemirror.net/6/docs/ref/#language.Language) with an670optional set of supporting extensions. Language packages are671encouraged to export a function that optionally takes a672configuration object and returns a `LanguageSupport` instance, as673the main way for client code to use the package.674*/675class LanguageSupport {676 /**677 Create a language support object.678 */679 constructor(680 /**681 The language object.682 */683 language, 684 /**685 An optional set of supporting extensions. When nesting a686 language in another language, the outer language is encouraged687 to include the supporting extensions for its inner languages688 in its own set of support extensions.689 */690 support = []) {691 this.language = language;692 this.support = support;693 this.extension = [language, support];694 }695}696/**697Language descriptions are used to store metadata about languages698and to dynamically load them. Their main role is finding the699appropriate language for a filename or dynamically loading nested700parsers.701*/702class LanguageDescription {703 constructor(704 /**705 The name of this language.706 */707 name, 708 /**709 Alternative names for the mode (lowercased, includes `this.name`).710 */711 alias, 712 /**713 File extensions associated with this language.714 */715 extensions, 716 /**717 Optional filename pattern that should be associated with this718 language.719 */720 filename, loadFunc, 721 /**722 If the language has been loaded, this will hold its value.723 */724 support = undefined) {725 this.name = name;726 this.alias = alias;727 this.extensions = extensions;728 this.filename = filename;729 this.loadFunc = loadFunc;730 this.support = support;731 this.loading = null;732 }733 /**734 Start loading the the language. Will return a promise that735 resolves to a [`LanguageSupport`](https://codemirror.net/6/docs/ref/#language.LanguageSupport)736 object when the language successfully loads.737 */738 load() {739 return this.loading || (this.loading = this.loadFunc().then(support => this.support = support, err => { this.loading = null; throw err; }));740 }741 /**742 Create a language description.743 */744 static of(spec) {745 let { load, support } = spec;746 if (!load) {747 if (!support)748 throw new RangeError("Must pass either 'load' or 'support' to LanguageDescription.of");749 load = () => Promise.resolve(support);750 }751 return new LanguageDescription(spec.name, (spec.alias || []).concat(spec.name).map(s => s.toLowerCase()), spec.extensions || [], spec.filename, load, support);752 }753 /**754 Look for a language in the given array of descriptions that755 matches the filename. Will first match756 [`filename`](https://codemirror.net/6/docs/ref/#language.LanguageDescription.filename) patterns,757 and then [extensions](https://codemirror.net/6/docs/ref/#language.LanguageDescription.extensions),758 and return the first language that matches.759 */760 static matchFilename(descs, filename) {761 for (let d of descs)762 if (d.filename && d.filename.test(filename))763 return d;764 let ext = /\.([^.]+)$/.exec(filename);765 if (ext)766 for (let d of descs)767 if (d.extensions.indexOf(ext[1]) > -1)768 return d;769 return null;770 }771 /**772 Look for a language whose name or alias matches the the given773 name (case-insensitively). If `fuzzy` is true, and no direct774 matchs is found, this'll also search for a language whose name775 or alias occurs in the string (for names shorter than three776 characters, only when surrounded by non-word characters).777 */778 static matchLanguageName(descs, name, fuzzy = true) {779 name = name.toLowerCase();780 for (let d of descs)781 if (d.alias.some(a => a == name))782 return d;783 if (fuzzy)784 for (let d of descs)785 for (let a of d.alias) {786 let found = name.indexOf(a);787 if (found > -1 && (a.length > 2 || !/\w/.test(name[found - 1]) && !/\w/.test(name[found + a.length])))788 return d;789 }790 return null;791 }792}793 794/**795Facet that defines a way to provide a function that computes the796appropriate indentation depth, as a column number (see797[`indentString`](https://codemirror.net/6/docs/ref/#language.indentString)), at the start of a given798line. A return value of `null` indicates no indentation can be799determined, and the line should inherit the indentation of the one800above it. A return value of `undefined` defers to the next indent801service.802*/803const indentService = state.Facet.define();804/**805Facet for overriding the unit by which indentation happens. Should806be a string consisting entirely of the same whitespace character.807When not set, this defaults to 2 spaces.808*/809const indentUnit = state.Facet.define({810 combine: values => {811 if (!values.length)812 return " ";813 let unit = values[0];814 if (!unit || /\S/.test(unit) || Array.from(unit).some(e => e != unit[0]))815 throw new Error("Invalid indent unit: " + JSON.stringify(values[0]));816 return unit;817 }818});819/**820Return the _column width_ of an indent unit in the state.821Determined by the [`indentUnit`](https://codemirror.net/6/docs/ref/#language.indentUnit)822facet, and [`tabSize`](https://codemirror.net/6/docs/ref/#state.EditorState^tabSize) when that823contains tabs.824*/825function getIndentUnit(state) {826 let unit = state.facet(indentUnit);827 return unit.charCodeAt(0) == 9 ? state.tabSize * unit.length : unit.length;828}829/**830Create an indentation string that covers columns 0 to `cols`.831Will use tabs for as much of the columns as possible when the832[`indentUnit`](https://codemirror.net/6/docs/ref/#language.indentUnit) facet contains833tabs.834*/835function indentString(state, cols) {836 let result = "", ts = state.tabSize, ch = state.facet(indentUnit)[0];837 if (ch == "\t") {838 while (cols >= ts) {839 result += "\t";840 cols -= ts;841 }842 ch = " ";843 }844 for (let i = 0; i < cols; i++)845 result += ch;846 return result;847}848/**849Get the indentation, as a column number, at the given position.850Will first consult any [indent services](https://codemirror.net/6/docs/ref/#language.indentService)851that are registered, and if none of those return an indentation,852this will check the syntax tree for the [indent node853prop](https://codemirror.net/6/docs/ref/#language.indentNodeProp) and use that if found. Returns a854number when an indentation could be determined, and null855otherwise.856*/857function getIndentation(context, pos) {858 if (context instanceof state.EditorState)859 context = new IndentContext(context);860 for (let service of context.state.facet(indentService)) {861 let result = service(context, pos);862 if (result !== undefined)863 return result;864 }865 let tree = syntaxTree(context.state);866 return tree.length >= pos ? syntaxIndentation(context, tree, pos) : null;867}868/**869Create a change set that auto-indents all lines touched by the870given document range.871*/872function indentRange(state, from, to) {873 let updated = Object.create(null);874 let context = new IndentContext(state, { overrideIndentation: start => { var _a; return (_a = updated[start]) !== null && _a !== void 0 ? _a : -1; } });875 let changes = [];876 for (let pos = from; pos <= to;) {877 let line = state.doc.lineAt(pos);878 pos = line.to + 1;879 let indent = getIndentation(context, line.from);880 if (indent == null)881 continue;882 if (!/\S/.test(line.text))883 indent = 0;884 let cur = /^\s*/.exec(line.text)[0];885 let norm = indentString(state, indent);886 if (cur != norm) {887 updated[line.from] = indent;888 changes.push({ from: line.from, to: line.from + cur.length, insert: norm });889 }890 }891 return state.changes(changes);892}893/**894Indentation contexts are used when calling [indentation895services](https://codemirror.net/6/docs/ref/#language.indentService). They provide helper utilities896useful in indentation logic, and can selectively override the897indentation reported for some lines.898*/899class IndentContext {900 /**901 Create an indent context.902 */903 constructor(904 /**905 The editor state.906 */907 state, 908 /**909 @internal910 */911 options = {}) {912 this.state = state;913 this.options = options;914 this.unit = getIndentUnit(state);915 }916 /**917 Get a description of the line at the given position, taking918 [simulated line919 breaks](https://codemirror.net/6/docs/ref/#language.IndentContext.constructor^options.simulateBreak)920 into account. If there is such a break at `pos`, the `bias`921 argument determines whether the part of the line line before or922 after the break is used.923 */924 lineAt(pos, bias = 1) {925 let line = this.state.doc.lineAt(pos);926 let { simulateBreak, simulateDoubleBreak } = this.options;927 if (simulateBreak != null && simulateBreak >= line.from && simulateBreak <= line.to) {928 if (simulateDoubleBreak && simulateBreak == pos)929 return { text: "", from: pos };930 else if (bias < 0 ? simulateBreak < pos : simulateBreak <= pos)931 return { text: line.text.slice(simulateBreak - line.from), from: simulateBreak };932 else933 return { text: line.text.slice(0, simulateBreak - line.from), from: line.from };934 }935 return line;936 }937 /**938 Get the text directly after `pos`, either the entire line939 or the next 100 characters, whichever is shorter.940 */941 textAfterPos(pos, bias = 1) {942 if (this.options.simulateDoubleBreak && pos == this.options.simulateBreak)943 return "";944 let { text, from } = this.lineAt(pos, bias);945 return text.slice(pos - from, Math.min(text.length, pos + 100 - from));946 }947 /**948 Find the column for the given position.949 */950 column(pos, bias = 1) {951 let { text, from } = this.lineAt(pos, bias);952 let result = this.countColumn(text, pos - from);953 let override = this.options.overrideIndentation ? this.options.overrideIndentation(from) : -1;954 if (override > -1)955 result += override - this.countColumn(text, text.search(/\S|$/));956 return result;957 }958 /**959 Find the column position (taking tabs into account) of the given960 position in the given string.961 */962 countColumn(line, pos = line.length) {963 return state.countColumn(line, this.state.tabSize, pos);964 }965 /**966 Find the indentation column of the line at the given point.967 */968 lineIndent(pos, bias = 1) {969 let { text, from } = this.lineAt(pos, bias);970 let override = this.options.overrideIndentation;971 if (override) {972 let overriden = override(from);973 if (overriden > -1)974 return overriden;975 }976 return this.countColumn(text, text.search(/\S|$/));977 }978 /**979 Returns the [simulated line980 break](https://codemirror.net/6/docs/ref/#language.IndentContext.constructor^options.simulateBreak)981 for this context, if any.982 */983 get simulatedBreak() {984 return this.options.simulateBreak || null;985 }986}987/**988A syntax tree node prop used to associate indentation strategies989with node types. Such a strategy is a function from an indentation990context to a column number (see also991[`indentString`](https://codemirror.net/6/docs/ref/#language.indentString)) or null, where null992indicates that no definitive indentation can be determined.993*/994const indentNodeProp = new common.NodeProp();995// Compute the indentation for a given position from the syntax tree.996function syntaxIndentation(cx, ast, pos) {997 let stack = ast.resolveStack(pos);998 let inner = ast.resolveInner(pos, -1).resolve(pos, 0).enterUnfinishedNodesBefore(pos);999 if (inner != stack.node) {1000 let add = [];1001 for (let cur = inner; cur && !(cur.from < stack.node.from || cur.to > stack.node.to ||1002 cur.from == stack.node.from && cur.type == stack.node.type); cur = cur.parent)1003 add.push(cur);1004 for (let i = add.length - 1; i >= 0; i--)1005 stack = { node: add[i], next: stack };1006 }1007 return indentFor(stack, cx, pos);1008}1009function indentFor(stack, cx, pos) {1010 for (let cur = stack; cur; cur = cur.next) {1011 let strategy = indentStrategy(cur.node);1012 if (strategy)1013 return strategy(TreeIndentContext.create(cx, pos, cur));1014 }1015 return 0;1016}1017function ignoreClosed(cx) {1018 return cx.pos == cx.options.simulateBreak && cx.options.simulateDoubleBreak;1019}1020function indentStrategy(tree) {1021 let strategy = tree.type.prop(indentNodeProp);1022 if (strategy)1023 return strategy;1024 let first = tree.firstChild, close;1025 if (first && (close = first.type.prop(common.NodeProp.closedBy))) {1026 let last = tree.lastChild, closed = last && close.indexOf(last.name) > -1;1027 return cx => delimitedStrategy(cx, true, 1, undefined, closed && !ignoreClosed(cx) ? last.from : undefined);1028 }1029 return tree.parent == null ? topIndent : null;1030}1031function topIndent() { return 0; }1032/**1033Objects of this type provide context information and helper1034methods to indentation functions registered on syntax nodes.1035*/1036class TreeIndentContext extends IndentContext {1037 constructor(base, 1038 /**1039 The position at which indentation is being computed.1040 */1041 pos, 1042 /**1043 @internal1044 */1045 context) {1046 super(base.state, base.options);1047 this.base = base;1048 this.pos = pos;1049 this.context = context;1050 }1051 /**1052 The syntax tree node to which the indentation strategy1053 applies.1054 */1055 get node() { return this.context.node; }1056 /**1057 @internal1058 */1059 static create(base, pos, context) {1060 return new TreeIndentContext(base, pos, context);1061 }1062 /**1063 Get the text directly after `this.pos`, either the entire line1064 or the next 100 characters, whichever is shorter.1065 */1066 get textAfter() {1067 return this.textAfterPos(this.pos);1068 }1069 /**1070 Get the indentation at the reference line for `this.node`, which1071 is the line on which it starts, unless there is a node that is1072 _not_ a parent of this node covering the start of that line. If1073 so, the line at the start of that node is tried, again skipping1074 on if it is covered by another such node.1075 */1076 get baseIndent() {1077 return this.baseIndentFor(this.node);1078 }1079 /**1080 Get the indentation for the reference line of the given node1081 (see [`baseIndent`](https://codemirror.net/6/docs/ref/#language.TreeIndentContext.baseIndent)).1082 */1083 baseIndentFor(node) {1084 let line = this.state.doc.lineAt(node.from);1085 // Skip line starts that are covered by a sibling (or cousin, etc)1086 for (;;) {1087 let atBreak = node.resolve(line.from);1088 while (atBreak.parent && atBreak.parent.from == atBreak.from)1089 atBreak = atBreak.parent;1090 if (isParent(atBreak, node))1091 break;1092 line = this.state.doc.lineAt(atBreak.from);1093 }1094 return this.lineIndent(line.from);1095 }1096 /**1097 Continue looking for indentations in the node's parent nodes,1098 and return the result of that.1099 */1100 continue() {1101 return indentFor(this.context.next, this.base, this.pos);1102 }1103}1104function isParent(parent, of) {1105 for (let cur = of; cur; cur = cur.parent)1106 if (parent == cur)1107 return true;1108 return false;1109}1110// Check whether a delimited node is aligned (meaning there are1111// non-skipped nodes on the same line as the opening delimiter). And1112// if so, return the opening token.1113function bracketedAligned(context) {1114 let tree = context.node;1115 let openToken = tree.childAfter(tree.from), last = tree.lastChild;1116 if (!openToken)1117 return null;1118 let sim = context.options.simulateBreak;1119 let openLine = context.state.doc.lineAt(openToken.from);1120 let lineEnd = sim == null || sim <= openLine.from ? openLine.to : Math.min(openLine.to, sim);1121 for (let pos = openToken.to;;) {1122 let next = tree.childAfter(pos);1123 if (!next || next == last)1124 return null;1125 if (!next.type.isSkipped) {1126 if (next.from >= lineEnd)1127 return null;1128 let space = /^ */.exec(openLine.text.slice(openToken.to - openLine.from))[0].length;1129 return { from: openToken.from, to: openToken.to + space };1130 }1131 pos = next.to;1132 }1133}1134/**1135An indentation strategy for delimited (usually bracketed) nodes.1136Will, by default, indent one unit more than the parent's base1137indent unless the line starts with a closing token. When `align`1138is true and there are non-skipped nodes on the node's opening1139line, the content of the node will be aligned with the end of the1140opening node, like this:1141 1142 foo(bar,1143 baz)1144*/1145function delimitedIndent({ closing, align = true, units = 1 }) {1146 return (context) => delimitedStrategy(context, align, units, closing);1147}1148function delimitedStrategy(context, align, units, closing, closedAt) {1149 let after = context.textAfter, space = after.match(/^\s*/)[0].length;1150 let closed = closing && after.slice(space, space + closing.length) == closing || closedAt == context.pos + space;1151 let aligned = align ? bracketedAligned(context) : null;1152 if (aligned)1153 return closed ? context.column(aligned.from) : context.column(aligned.to);1154 return context.baseIndent + (closed ? 0 : context.unit * units);1155}1156/**1157An indentation strategy that aligns a node's content to its base1158indentation.1159*/1160const flatIndent = (context) => context.baseIndent;1161/**1162Creates an indentation strategy that, by default, indents1163continued lines one unit more than the node's base indentation.1164You can provide `except` to prevent indentation of lines that1165match a pattern (for example `/^else\b/` in `if`/`else`1166constructs), and you can change the amount of units used with the1167`units` option.1168*/1169function continuedIndent({ except, units = 1 } = {}) {1170 return (context) => {1171 let matchExcept = except && except.test(context.textAfter);1172 return context.baseIndent + (matchExcept ? 0 : units * context.unit);1173 };1174}1175const DontIndentBeyond = 200;1176/**1177Enables reindentation on input. When a language defines an1178`indentOnInput` field in its [language1179data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt), which must hold a regular1180expression, the line at the cursor will be reindented whenever new1181text is typed and the input from the start of the line up to the1182cursor matches that regexp.1183 1184To avoid unneccesary reindents, it is recommended to start the1185regexp with `^` (usually followed by `\s*`), and end it with `$`.1186For example, `/^\s*\}$/` will reindent when a closing brace is1187added at the start of a line.1188*/1189function indentOnInput() {1190 return state.EditorState.transactionFilter.of(tr => {1191 if (!tr.docChanged || !tr.isUserEvent("input.type") && !tr.isUserEvent("input.complete"))1192 return tr;1193 let rules = tr.startState.languageDataAt("indentOnInput", tr.startState.selection.main.head);1194 if (!rules.length)1195 return tr;1196 let doc = tr.newDoc, { head } = tr.newSelection.main, line = doc.lineAt(head);1197 if (head > line.from + DontIndentBeyond)1198 return tr;1199 let lineStart = doc.sliceString(line.from, head);1200 if (!rules.some(r => r.test(lineStart)))