@uiw/react-codemirror 4.19.16 → 4.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -135,12 +135,12 @@ __webpack_require__.r(__webpack_exports__);
135
135
 
136
136
  // EXPORTS
137
137
  __webpack_require__.d(__webpack_exports__, {
138
- "basicSetup": () => (/* reexport */ basicSetup),
138
+ basicSetup: () => (/* reexport */ basicSetup),
139
139
  "default": () => (/* binding */ src),
140
- "getDefaultExtensions": () => (/* reexport */ getDefaultExtensions),
141
- "getStatistics": () => (/* reexport */ getStatistics),
142
- "minimalSetup": () => (/* reexport */ minimalSetup),
143
- "useCodeMirror": () => (/* reexport */ useCodeMirror)
140
+ getDefaultExtensions: () => (/* reexport */ getDefaultExtensions),
141
+ getStatistics: () => (/* reexport */ getStatistics),
142
+ minimalSetup: () => (/* reexport */ minimalSetup),
143
+ useCodeMirror: () => (/* reexport */ useCodeMirror)
144
144
  });
145
145
 
146
146
  ;// CONCATENATED MODULE: ../node_modules/@babel/runtime/helpers/esm/typeof.js
@@ -3092,20 +3092,22 @@ class StyleModule {
3092
3092
  }
3093
3093
  }
3094
3094
 
3095
- let adoptedSet = null
3095
+ let adoptedSet = new Map //<Document, StyleSet>
3096
3096
 
3097
3097
  class StyleSet {
3098
3098
  constructor(root) {
3099
- if (!root.head && root.adoptedStyleSheets && typeof CSSStyleSheet != "undefined") {
3100
- if (adoptedSet) {
3101
- root.adoptedStyleSheets = [adoptedSet.sheet, ...root.adoptedStyleSheets]
3102
- return root[SET] = adoptedSet
3099
+ let doc = root.ownerDocument || root, win = doc.defaultView
3100
+ if (!root.head && root.adoptedStyleSheets && win.CSSStyleSheet) {
3101
+ let adopted = adoptedSet.get(doc)
3102
+ if (adopted) {
3103
+ root.adoptedStyleSheets = [adopted.sheet, ...root.adoptedStyleSheets]
3104
+ return root[SET] = adopted
3103
3105
  }
3104
- this.sheet = new CSSStyleSheet
3106
+ this.sheet = new win.CSSStyleSheet
3105
3107
  root.adoptedStyleSheets = [this.sheet, ...root.adoptedStyleSheets]
3106
- adoptedSet = this
3108
+ adoptedSet.set(doc, this)
3107
3109
  } else {
3108
- this.styleTag = (root.ownerDocument || root).createElement("style")
3110
+ this.styleTag = doc.createElement("style")
3109
3111
  let target = root.head || root
3110
3112
  target.insertBefore(this.styleTag, target.firstChild)
3111
3113
  }
@@ -5757,7 +5759,7 @@ function selectedLineRanges(state) {
5757
5759
  if (last >= 0 && ranges[last].to > fromLine.from)
5758
5760
  ranges[last].to = toLine.to;
5759
5761
  else
5760
- ranges.push({ from: fromLine.from, to: toLine.to });
5762
+ ranges.push({ from: fromLine.from + /^\s*/.exec(fromLine.text)[0].length, to: toLine.to });
5761
5763
  }
5762
5764
  return ranges;
5763
5765
  }
@@ -6280,6 +6282,8 @@ function moveBySubword(view, range, forward) {
6280
6282
  return false;
6281
6283
  pos += forward ? next.length : -next.length;
6282
6284
  let nextCat = categorize(next), ahead;
6285
+ if (nextCat == CharCategory.Word && next.charCodeAt(0) < 128 && /[\W_]/.test(next))
6286
+ nextCat = -1; // Treat word punctuation specially
6283
6287
  if (cat == CharCategory.Space)
6284
6288
  cat = nextCat;
6285
6289
  if (cat != nextCat)
@@ -7203,7 +7207,7 @@ The default keymap. Includes all bindings from
7203
7207
  - Shift-Alt-ArrowUp: [`copyLineUp`](https://codemirror.net/6/docs/ref/#commands.copyLineUp)
7204
7208
  - Shift-Alt-ArrowDown: [`copyLineDown`](https://codemirror.net/6/docs/ref/#commands.copyLineDown)
7205
7209
  - Escape: [`simplifySelection`](https://codemirror.net/6/docs/ref/#commands.simplifySelection)
7206
- - Ctrl-Enter (Comd-Enter on macOS): [`insertBlankLine`](https://codemirror.net/6/docs/ref/#commands.insertBlankLine)
7210
+ - Ctrl-Enter (Cmd-Enter on macOS): [`insertBlankLine`](https://codemirror.net/6/docs/ref/#commands.insertBlankLine)
7207
7211
  - Alt-l (Ctrl-l on macOS): [`selectLine`](https://codemirror.net/6/docs/ref/#commands.selectLine)
7208
7212
  - Ctrl-i (Cmd-i on macOS): [`selectParentSyntax`](https://codemirror.net/6/docs/ref/#commands.selectParentSyntax)
7209
7213
  - Ctrl-[ (Cmd-[ on macOS): [`indentLess`](https://codemirror.net/6/docs/ref/#commands.indentLess)
@@ -7243,7 +7247,7 @@ const indentWithTab = { key: "Tab", run: indentMore, shift: indentLess };
7243
7247
 
7244
7248
 
7245
7249
 
7246
- ;// CONCATENATED MODULE: ../node_modules/crelt/index.es.js
7250
+ ;// CONCATENATED MODULE: ../node_modules/crelt/index.js
7247
7251
  function crelt() {
7248
7252
  var elt = arguments[0]
7249
7253
  if (typeof elt == "string") elt = document.createElement(elt)
@@ -8118,9 +8122,10 @@ const findNext = /*@__PURE__*/searchCommand((view, { query }) => {
8118
8122
  let config = view.state.facet(searchConfigFacet);
8119
8123
  view.dispatch({
8120
8124
  selection,
8121
- effects: [announceMatch(view, next), config.scrollToMatch(selection.main)],
8125
+ effects: [announceMatch(view, next), config.scrollToMatch(selection.main, view)],
8122
8126
  userEvent: "select.search"
8123
8127
  });
8128
+ selectSearchInput(view);
8124
8129
  return true;
8125
8130
  });
8126
8131
  /**
@@ -8137,9 +8142,10 @@ const findPrevious = /*@__PURE__*/searchCommand((view, { query }) => {
8137
8142
  let config = view.state.facet(searchConfigFacet);
8138
8143
  view.dispatch({
8139
8144
  selection,
8140
- effects: [announceMatch(view, prev), config.scrollToMatch(selection.main)],
8145
+ effects: [announceMatch(view, prev), config.scrollToMatch(selection.main, view)],
8141
8146
  userEvent: "select.search"
8142
8147
  });
8148
+ selectSearchInput(view);
8143
8149
  return true;
8144
8150
  });
8145
8151
  /**
@@ -8199,7 +8205,7 @@ const replaceNext = /*@__PURE__*/searchCommand((view, { query }) => {
8199
8205
  let off = changes.length == 0 || changes[0].from >= next.to ? 0 : next.to - next.from - replacement.length;
8200
8206
  selection = state_.EditorSelection.single(next.from - off, next.to - off);
8201
8207
  effects.push(announceMatch(view, next));
8202
- effects.push(state.facet(searchConfigFacet).scrollToMatch(selection.main));
8208
+ effects.push(state.facet(searchConfigFacet).scrollToMatch(selection.main, view));
8203
8209
  }
8204
8210
  view.dispatch({
8205
8211
  changes, selection, effects,
@@ -8245,16 +8251,22 @@ function defaultQuery(state, fallback) {
8245
8251
  wholeWord: (_d = fallback === null || fallback === void 0 ? void 0 : fallback.wholeWord) !== null && _d !== void 0 ? _d : config.wholeWord
8246
8252
  });
8247
8253
  }
8254
+ function getSearchInput(view) {
8255
+ let panel = (0,view_.getPanel)(view, createSearchPanel);
8256
+ return panel && panel.dom.querySelector("[main-field]");
8257
+ }
8258
+ function selectSearchInput(view) {
8259
+ let input = getSearchInput(view);
8260
+ if (input && input == view.root.activeElement)
8261
+ input.select();
8262
+ }
8248
8263
  /**
8249
8264
  Make sure the search panel is open and focused.
8250
8265
  */
8251
8266
  const openSearchPanel = view => {
8252
8267
  let state = view.state.field(searchState, false);
8253
8268
  if (state && state.panel) {
8254
- let panel = (0,view_.getPanel)(view, createSearchPanel);
8255
- if (!panel)
8256
- return false;
8257
- let searchInput = panel.dom.querySelector("[main-field]");
8269
+ let searchInput = getSearchInput(view);
8258
8270
  if (searchInput && searchInput != view.root.activeElement) {
8259
8271
  let query = defaultQuery(view.state, state.query.spec);
8260
8272
  if (query.valid)
@@ -8618,13 +8630,14 @@ function ifNotIn(nodes, source) {
8618
8630
  };
8619
8631
  }
8620
8632
  class Option {
8621
- constructor(completion, source, match) {
8633
+ constructor(completion, source, match, score) {
8622
8634
  this.completion = completion;
8623
8635
  this.source = source;
8624
8636
  this.match = match;
8637
+ this.score = score;
8625
8638
  }
8626
8639
  }
8627
- function cur(state) { return state.selection.main.head; }
8640
+ function cur(state) { return state.selection.main.from; }
8628
8641
  // Make sure the given regexp has a $ at its end and, if `start` is
8629
8642
  // true, a ^ at its start.
8630
8643
  function ensureAnchor(expr, start) {
@@ -8646,30 +8659,17 @@ completion's text in the main selection range, and any other
8646
8659
  selection range that has the same text in front of it.
8647
8660
  */
8648
8661
  function insertCompletionText(state, text, from, to) {
8662
+ let { main } = state.selection, fromOff = from - main.from, toOff = to - main.from;
8649
8663
  return Object.assign(Object.assign({}, state.changeByRange(range => {
8650
- if (range == state.selection.main)
8651
- return {
8652
- changes: { from: from, to: to, insert: text },
8653
- range: state_.EditorSelection.cursor(from + text.length)
8654
- };
8655
- let len = to - from;
8656
- if (!range.empty ||
8657
- len && state.sliceDoc(range.from - len, range.from) != state.sliceDoc(from, to))
8664
+ if (range != main && from != to &&
8665
+ state.sliceDoc(range.from + fromOff, range.from + toOff) != state.sliceDoc(from, to))
8658
8666
  return { range };
8659
8667
  return {
8660
- changes: { from: range.from - len, to: range.from, insert: text },
8661
- range: state_.EditorSelection.cursor(range.from - len + text.length)
8668
+ changes: { from: range.from + fromOff, to: to == main.from ? range.to : range.from + toOff, insert: text },
8669
+ range: state_.EditorSelection.cursor(range.from + fromOff + text.length)
8662
8670
  };
8663
8671
  })), { userEvent: "input.complete" });
8664
8672
  }
8665
- function applyCompletion(view, option) {
8666
- const apply = option.completion.apply || option.completion.label;
8667
- let result = option.source;
8668
- if (typeof apply == "string")
8669
- view.dispatch(Object.assign(Object.assign({}, insertCompletionText(view.state, apply, result.from, result.to)), { annotations: pickedCompletion.of(option.completion) }));
8670
- else
8671
- apply(view, option.completion, result.from, result.to);
8672
- }
8673
8673
  const SourceCache = /*@__PURE__*/new WeakMap();
8674
8674
  function asSource(source) {
8675
8675
  if (!Array.isArray(source))
@@ -8679,6 +8679,8 @@ function asSource(source) {
8679
8679
  SourceCache.set(source, known = completeFromList(source));
8680
8680
  return known;
8681
8681
  }
8682
+ const startCompletionEffect = /*@__PURE__*/state_.StateEffect.define();
8683
+ const closeCompletionEffect = /*@__PURE__*/state_.StateEffect.define();
8682
8684
 
8683
8685
  // A pattern matcher for fuzzy completion matching. Create an instance
8684
8686
  // once for a pattern, and then use that to match any number of
@@ -8711,7 +8713,7 @@ class FuzzyMatcher {
8711
8713
  // is. See `Penalty` above.
8712
8714
  match(word) {
8713
8715
  if (this.pattern.length == 0)
8714
- return [0];
8716
+ return [-100 /* Penalty.NotFull */];
8715
8717
  if (word.length < this.pattern.length)
8716
8718
  return null;
8717
8719
  let { chars, folded, any, precise, byWord } = this;
@@ -8824,6 +8826,7 @@ const completionConfig = /*@__PURE__*/state_.Facet.define({
8824
8826
  aboveCursor: false,
8825
8827
  icons: true,
8826
8828
  addToOptions: [],
8829
+ positionInfo: defaultPositionInfo,
8827
8830
  compareCompletions: (a, b) => a.label.localeCompare(b.label),
8828
8831
  interactionDelay: 75
8829
8832
  }, {
@@ -8839,6 +8842,262 @@ const completionConfig = /*@__PURE__*/state_.Facet.define({
8839
8842
  function joinClass(a, b) {
8840
8843
  return a ? b ? a + " " + b : a : b;
8841
8844
  }
8845
+ function defaultPositionInfo(view, list, option, info, space) {
8846
+ let rtl = view.textDirection == view_.Direction.RTL, left = rtl, narrow = false;
8847
+ let side = "top", offset, maxWidth;
8848
+ let spaceLeft = list.left - space.left, spaceRight = space.right - list.right;
8849
+ let infoWidth = info.right - info.left, infoHeight = info.bottom - info.top;
8850
+ if (left && spaceLeft < Math.min(infoWidth, spaceRight))
8851
+ left = false;
8852
+ else if (!left && spaceRight < Math.min(infoWidth, spaceLeft))
8853
+ left = true;
8854
+ if (infoWidth <= (left ? spaceLeft : spaceRight)) {
8855
+ offset = Math.max(space.top, Math.min(option.top, space.bottom - infoHeight)) - list.top;
8856
+ maxWidth = Math.min(400 /* Info.Width */, left ? spaceLeft : spaceRight);
8857
+ }
8858
+ else {
8859
+ narrow = true;
8860
+ maxWidth = Math.min(400 /* Info.Width */, (rtl ? list.right : space.right - list.left) - 30 /* Info.Margin */);
8861
+ let spaceBelow = space.bottom - list.bottom;
8862
+ if (spaceBelow >= infoHeight || spaceBelow > list.top) { // Below the completion
8863
+ offset = option.bottom - list.top;
8864
+ }
8865
+ else { // Above it
8866
+ side = "bottom";
8867
+ offset = list.bottom - option.top;
8868
+ }
8869
+ }
8870
+ return {
8871
+ style: `${side}: ${offset}px; max-width: ${maxWidth}px`,
8872
+ class: "cm-completionInfo-" + (narrow ? (rtl ? "left-narrow" : "right-narrow") : left ? "left" : "right")
8873
+ };
8874
+ }
8875
+
8876
+ /**
8877
+ Returns a command that moves the completion selection forward or
8878
+ backward by the given amount.
8879
+ */
8880
+ function moveCompletionSelection(forward, by = "option") {
8881
+ return (view) => {
8882
+ let cState = view.state.field(completionState, false);
8883
+ if (!cState || !cState.open || cState.open.disabled ||
8884
+ Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay)
8885
+ return false;
8886
+ let step = 1, tooltip;
8887
+ if (by == "page" && (tooltip = (0,view_.getTooltip)(view, cState.open.tooltip)))
8888
+ step = Math.max(2, Math.floor(tooltip.dom.offsetHeight /
8889
+ tooltip.dom.querySelector("li").offsetHeight) - 1);
8890
+ let { length } = cState.open.options;
8891
+ let selected = cState.open.selected > -1 ? cState.open.selected + step * (forward ? 1 : -1) : forward ? 0 : length - 1;
8892
+ if (selected < 0)
8893
+ selected = by == "page" ? 0 : length - 1;
8894
+ else if (selected >= length)
8895
+ selected = by == "page" ? length - 1 : 0;
8896
+ view.dispatch({ effects: setSelectedEffect.of(selected) });
8897
+ return true;
8898
+ };
8899
+ }
8900
+ /**
8901
+ Accept the current completion.
8902
+ */
8903
+ const acceptCompletion = (view) => {
8904
+ let cState = view.state.field(completionState, false);
8905
+ if (view.state.readOnly || !cState || !cState.open || cState.open.selected < 0 ||
8906
+ Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay)
8907
+ return false;
8908
+ if (!cState.open.disabled)
8909
+ return applyCompletion(view, cState.open.options[cState.open.selected]);
8910
+ return true;
8911
+ };
8912
+ /**
8913
+ Explicitly start autocompletion.
8914
+ */
8915
+ const startCompletion = (view) => {
8916
+ let cState = view.state.field(completionState, false);
8917
+ if (!cState)
8918
+ return false;
8919
+ view.dispatch({ effects: startCompletionEffect.of(true) });
8920
+ return true;
8921
+ };
8922
+ /**
8923
+ Close the currently active completion.
8924
+ */
8925
+ const closeCompletion = (view) => {
8926
+ let cState = view.state.field(completionState, false);
8927
+ if (!cState || !cState.active.some(a => a.state != 0 /* State.Inactive */))
8928
+ return false;
8929
+ view.dispatch({ effects: closeCompletionEffect.of(null) });
8930
+ return true;
8931
+ };
8932
+ class RunningQuery {
8933
+ constructor(active, context) {
8934
+ this.active = active;
8935
+ this.context = context;
8936
+ this.time = Date.now();
8937
+ this.updates = [];
8938
+ // Note that 'undefined' means 'not done yet', whereas 'null' means
8939
+ // 'query returned null'.
8940
+ this.done = undefined;
8941
+ }
8942
+ }
8943
+ const DebounceTime = 50, MaxUpdateCount = 50, MinAbortTime = 1000;
8944
+ const completionPlugin = /*@__PURE__*/view_.ViewPlugin.fromClass(class {
8945
+ constructor(view) {
8946
+ this.view = view;
8947
+ this.debounceUpdate = -1;
8948
+ this.running = [];
8949
+ this.debounceAccept = -1;
8950
+ this.composing = 0 /* CompositionState.None */;
8951
+ for (let active of view.state.field(completionState).active)
8952
+ if (active.state == 1 /* State.Pending */)
8953
+ this.startQuery(active);
8954
+ }
8955
+ update(update) {
8956
+ let cState = update.state.field(completionState);
8957
+ if (!update.selectionSet && !update.docChanged && update.startState.field(completionState) == cState)
8958
+ return;
8959
+ let doesReset = update.transactions.some(tr => {
8960
+ return (tr.selection || tr.docChanged) && !getUserEvent(tr);
8961
+ });
8962
+ for (let i = 0; i < this.running.length; i++) {
8963
+ let query = this.running[i];
8964
+ if (doesReset ||
8965
+ query.updates.length + update.transactions.length > MaxUpdateCount && Date.now() - query.time > MinAbortTime) {
8966
+ for (let handler of query.context.abortListeners) {
8967
+ try {
8968
+ handler();
8969
+ }
8970
+ catch (e) {
8971
+ (0,view_.logException)(this.view.state, e);
8972
+ }
8973
+ }
8974
+ query.context.abortListeners = null;
8975
+ this.running.splice(i--, 1);
8976
+ }
8977
+ else {
8978
+ query.updates.push(...update.transactions);
8979
+ }
8980
+ }
8981
+ if (this.debounceUpdate > -1)
8982
+ clearTimeout(this.debounceUpdate);
8983
+ this.debounceUpdate = cState.active.some(a => a.state == 1 /* State.Pending */ && !this.running.some(q => q.active.source == a.source))
8984
+ ? setTimeout(() => this.startUpdate(), DebounceTime) : -1;
8985
+ if (this.composing != 0 /* CompositionState.None */)
8986
+ for (let tr of update.transactions) {
8987
+ if (getUserEvent(tr) == "input")
8988
+ this.composing = 2 /* CompositionState.Changed */;
8989
+ else if (this.composing == 2 /* CompositionState.Changed */ && tr.selection)
8990
+ this.composing = 3 /* CompositionState.ChangedAndMoved */;
8991
+ }
8992
+ }
8993
+ startUpdate() {
8994
+ this.debounceUpdate = -1;
8995
+ let { state } = this.view, cState = state.field(completionState);
8996
+ for (let active of cState.active) {
8997
+ if (active.state == 1 /* State.Pending */ && !this.running.some(r => r.active.source == active.source))
8998
+ this.startQuery(active);
8999
+ }
9000
+ }
9001
+ startQuery(active) {
9002
+ let { state } = this.view, pos = cur(state);
9003
+ let context = new CompletionContext(state, pos, active.explicitPos == pos);
9004
+ let pending = new RunningQuery(active, context);
9005
+ this.running.push(pending);
9006
+ Promise.resolve(active.source(context)).then(result => {
9007
+ if (!pending.context.aborted) {
9008
+ pending.done = result || null;
9009
+ this.scheduleAccept();
9010
+ }
9011
+ }, err => {
9012
+ this.view.dispatch({ effects: closeCompletionEffect.of(null) });
9013
+ (0,view_.logException)(this.view.state, err);
9014
+ });
9015
+ }
9016
+ scheduleAccept() {
9017
+ if (this.running.every(q => q.done !== undefined))
9018
+ this.accept();
9019
+ else if (this.debounceAccept < 0)
9020
+ this.debounceAccept = setTimeout(() => this.accept(), DebounceTime);
9021
+ }
9022
+ // For each finished query in this.running, try to create a result
9023
+ // or, if appropriate, restart the query.
9024
+ accept() {
9025
+ var _a;
9026
+ if (this.debounceAccept > -1)
9027
+ clearTimeout(this.debounceAccept);
9028
+ this.debounceAccept = -1;
9029
+ let updated = [];
9030
+ let conf = this.view.state.facet(completionConfig);
9031
+ for (let i = 0; i < this.running.length; i++) {
9032
+ let query = this.running[i];
9033
+ if (query.done === undefined)
9034
+ continue;
9035
+ this.running.splice(i--, 1);
9036
+ if (query.done) {
9037
+ let active = new ActiveResult(query.active.source, query.active.explicitPos, query.done, query.done.from, (_a = query.done.to) !== null && _a !== void 0 ? _a : cur(query.updates.length ? query.updates[0].startState : this.view.state));
9038
+ // Replay the transactions that happened since the start of
9039
+ // the request and see if that preserves the result
9040
+ for (let tr of query.updates)
9041
+ active = active.update(tr, conf);
9042
+ if (active.hasResult()) {
9043
+ updated.push(active);
9044
+ continue;
9045
+ }
9046
+ }
9047
+ let current = this.view.state.field(completionState).active.find(a => a.source == query.active.source);
9048
+ if (current && current.state == 1 /* State.Pending */) {
9049
+ if (query.done == null) {
9050
+ // Explicitly failed. Should clear the pending status if it
9051
+ // hasn't been re-set in the meantime.
9052
+ let active = new ActiveSource(query.active.source, 0 /* State.Inactive */);
9053
+ for (let tr of query.updates)
9054
+ active = active.update(tr, conf);
9055
+ if (active.state != 1 /* State.Pending */)
9056
+ updated.push(active);
9057
+ }
9058
+ else {
9059
+ // Cleared by subsequent transactions. Restart.
9060
+ this.startQuery(current);
9061
+ }
9062
+ }
9063
+ }
9064
+ if (updated.length)
9065
+ this.view.dispatch({ effects: setActiveEffect.of(updated) });
9066
+ }
9067
+ }, {
9068
+ eventHandlers: {
9069
+ blur(event) {
9070
+ let state = this.view.state.field(completionState, false);
9071
+ if (state && state.tooltip && this.view.state.facet(completionConfig).closeOnBlur) {
9072
+ let dialog = state.open && (0,view_.getTooltip)(this.view, state.open.tooltip);
9073
+ if (!dialog || !dialog.dom.contains(event.relatedTarget))
9074
+ this.view.dispatch({ effects: closeCompletionEffect.of(null) });
9075
+ }
9076
+ },
9077
+ compositionstart() {
9078
+ this.composing = 1 /* CompositionState.Started */;
9079
+ },
9080
+ compositionend() {
9081
+ if (this.composing == 3 /* CompositionState.ChangedAndMoved */) {
9082
+ // Safari fires compositionend events synchronously, possibly
9083
+ // from inside an update, so dispatch asynchronously to avoid reentrancy
9084
+ setTimeout(() => this.view.dispatch({ effects: startCompletionEffect.of(false) }), 20);
9085
+ }
9086
+ this.composing = 0 /* CompositionState.None */;
9087
+ }
9088
+ }
9089
+ });
9090
+ function applyCompletion(view, option) {
9091
+ const apply = option.completion.apply || option.completion.label;
9092
+ let result = view.state.field(completionState).active.find(a => a.source == option.source);
9093
+ if (!(result instanceof ActiveResult))
9094
+ return false;
9095
+ if (typeof apply == "string")
9096
+ view.dispatch(Object.assign(Object.assign({}, insertCompletionText(view.state, apply, result.from, result.to)), { annotations: pickedCompletion.of(option.completion) }));
9097
+ else
9098
+ apply(view, option.completion, result.from, result.to);
9099
+ return true;
9100
+ }
8842
9101
 
8843
9102
  function optionContent(config) {
8844
9103
  let content = config.addToOptions.slice();
@@ -8903,9 +9162,9 @@ class CompletionTooltip {
8903
9162
  this.view = view;
8904
9163
  this.stateField = stateField;
8905
9164
  this.info = null;
8906
- this.placeInfo = {
9165
+ this.placeInfoReq = {
8907
9166
  read: () => this.measureInfo(),
8908
- write: (pos) => this.positionInfo(pos),
9167
+ write: (pos) => this.placeInfo(pos),
8909
9168
  key: this
8910
9169
  };
8911
9170
  this.space = null;
@@ -8929,10 +9188,16 @@ class CompletionTooltip {
8929
9188
  }
8930
9189
  }
8931
9190
  });
9191
+ this.dom.addEventListener("focusout", (e) => {
9192
+ let state = view.state.field(this.stateField, false);
9193
+ if (state && state.tooltip && view.state.facet(completionConfig).closeOnBlur &&
9194
+ e.relatedTarget != view.contentDOM)
9195
+ view.dispatch({ effects: closeCompletionEffect.of(null) });
9196
+ });
8932
9197
  this.list = this.dom.appendChild(this.createListBox(options, cState.id, this.range));
8933
9198
  this.list.addEventListener("scroll", () => {
8934
9199
  if (this.info)
8935
- this.view.requestMeasure(this.placeInfo);
9200
+ this.view.requestMeasure(this.placeInfoReq);
8936
9201
  });
8937
9202
  }
8938
9203
  mount() { this.updateSel(); }
@@ -8962,7 +9227,7 @@ class CompletionTooltip {
8962
9227
  positioned(space) {
8963
9228
  this.space = space;
8964
9229
  if (this.info)
8965
- this.view.requestMeasure(this.placeInfo);
9230
+ this.view.requestMeasure(this.placeInfoReq);
8966
9231
  }
8967
9232
  updateSel() {
8968
9233
  let cState = this.view.state.field(this.stateField), open = cState.open;
@@ -8972,7 +9237,7 @@ class CompletionTooltip {
8972
9237
  this.list = this.dom.appendChild(this.createListBox(open.options, cState.id, this.range));
8973
9238
  this.list.addEventListener("scroll", () => {
8974
9239
  if (this.info)
8975
- this.view.requestMeasure(this.placeInfo);
9240
+ this.view.requestMeasure(this.placeInfoReq);
8976
9241
  });
8977
9242
  }
8978
9243
  if (this.updateSelectedOption(open.selected)) {
@@ -9003,12 +9268,15 @@ class CompletionTooltip {
9003
9268
  dom.className = "cm-tooltip cm-completionInfo";
9004
9269
  dom.appendChild(content);
9005
9270
  this.dom.appendChild(dom);
9006
- this.view.requestMeasure(this.placeInfo);
9271
+ this.view.requestMeasure(this.placeInfoReq);
9007
9272
  }
9008
9273
  updateSelectedOption(selected) {
9009
9274
  let set = null;
9010
9275
  for (let opt = this.list.firstChild, i = this.range.from; opt; opt = opt.nextSibling, i++) {
9011
- if (i == selected) {
9276
+ if (opt.nodeName != "LI" || !opt.id) {
9277
+ i--; // A section header
9278
+ }
9279
+ else if (i == selected) {
9012
9280
  if (!opt.hasAttribute("aria-selected")) {
9013
9281
  opt.setAttribute("aria-selected", "true");
9014
9282
  set = opt;
@@ -9038,41 +9306,17 @@ class CompletionTooltip {
9038
9306
  if (selRect.top > Math.min(space.bottom, listRect.bottom) - 10 ||
9039
9307
  selRect.bottom < Math.max(space.top, listRect.top) + 10)
9040
9308
  return null;
9041
- let rtl = this.view.textDirection == view_.Direction.RTL, left = rtl, narrow = false, maxWidth;
9042
- let top = "", bottom = "";
9043
- let spaceLeft = listRect.left - space.left, spaceRight = space.right - listRect.right;
9044
- if (left && spaceLeft < Math.min(infoRect.width, spaceRight))
9045
- left = false;
9046
- else if (!left && spaceRight < Math.min(infoRect.width, spaceLeft))
9047
- left = true;
9048
- if (infoRect.width <= (left ? spaceLeft : spaceRight)) {
9049
- top = (Math.max(space.top, Math.min(selRect.top, space.bottom - infoRect.height)) - listRect.top) + "px";
9050
- maxWidth = Math.min(400 /* Info.Width */, left ? spaceLeft : spaceRight) + "px";
9051
- }
9052
- else {
9053
- narrow = true;
9054
- maxWidth = Math.min(400 /* Info.Width */, (rtl ? listRect.right : space.right - listRect.left) - 30 /* Info.Margin */) + "px";
9055
- let spaceBelow = space.bottom - listRect.bottom;
9056
- if (spaceBelow >= infoRect.height || spaceBelow > listRect.top) // Below the completion
9057
- top = (selRect.bottom - listRect.top) + "px";
9058
- else // Above it
9059
- bottom = (listRect.bottom - selRect.top) + "px";
9060
- }
9061
- return {
9062
- top, bottom, maxWidth,
9063
- class: narrow ? (rtl ? "left-narrow" : "right-narrow") : left ? "left" : "right",
9064
- };
9309
+ return this.view.state.facet(completionConfig).positionInfo(this.view, listRect, selRect, infoRect, space);
9065
9310
  }
9066
- positionInfo(pos) {
9311
+ placeInfo(pos) {
9067
9312
  if (this.info) {
9068
9313
  if (pos) {
9069
- this.info.style.top = pos.top;
9070
- this.info.style.bottom = pos.bottom;
9071
- this.info.style.maxWidth = pos.maxWidth;
9072
- this.info.className = "cm-tooltip cm-completionInfo cm-completionInfo-" + pos.class;
9314
+ if (pos.style)
9315
+ this.info.style.cssText = pos.style;
9316
+ this.info.className = "cm-tooltip cm-completionInfo " + (pos.class || "");
9073
9317
  }
9074
9318
  else {
9075
- this.info.style.top = "-1e6px";
9319
+ this.info.style.cssText = "top: -1e6px";
9076
9320
  }
9077
9321
  }
9078
9322
  }
@@ -9082,8 +9326,22 @@ class CompletionTooltip {
9082
9326
  ul.setAttribute("role", "listbox");
9083
9327
  ul.setAttribute("aria-expanded", "true");
9084
9328
  ul.setAttribute("aria-label", this.view.state.phrase("Completions"));
9329
+ let curSection = null;
9085
9330
  for (let i = range.from; i < range.to; i++) {
9086
- let { completion, match } = options[i];
9331
+ let { completion, match } = options[i], { section } = completion;
9332
+ if (section) {
9333
+ let name = typeof section == "string" ? section : section.name;
9334
+ if (name != curSection && (i > range.from || range.from == 0)) {
9335
+ curSection = name;
9336
+ if (typeof section != "string" && section.header) {
9337
+ ul.appendChild(section.header(section));
9338
+ }
9339
+ else {
9340
+ let header = ul.appendChild(document.createElement("completion-section"));
9341
+ header.textContent = name;
9342
+ }
9343
+ }
9344
+ }
9087
9345
  const li = ul.appendChild(document.createElement("li"));
9088
9346
  li.id = id + "-" + i;
9089
9347
  li.setAttribute("role", "option");
@@ -9124,32 +9382,55 @@ function score(option) {
9124
9382
  (option.type ? 1 : 0);
9125
9383
  }
9126
9384
  function sortOptions(active, state) {
9127
- let options = [], i = 0;
9385
+ let options = [];
9386
+ let sections = null;
9387
+ let addOption = (option) => {
9388
+ options.push(option);
9389
+ let { section } = option.completion;
9390
+ if (section) {
9391
+ if (!sections)
9392
+ sections = [];
9393
+ let name = typeof section == "string" ? section : section.name;
9394
+ if (!sections.some(s => s.name == name))
9395
+ sections.push(typeof section == "string" ? { name } : section);
9396
+ }
9397
+ };
9128
9398
  for (let a of active)
9129
9399
  if (a.hasResult()) {
9130
9400
  if (a.result.filter === false) {
9131
9401
  let getMatch = a.result.getMatch;
9132
9402
  for (let option of a.result.options) {
9133
- let match = [1e9 - i++];
9403
+ let match = [1e9 - options.length];
9134
9404
  if (getMatch)
9135
9405
  for (let n of getMatch(option))
9136
9406
  match.push(n);
9137
- options.push(new Option(option, a, match));
9407
+ addOption(new Option(option, a.source, match, match[0]));
9138
9408
  }
9139
9409
  }
9140
9410
  else {
9141
9411
  let matcher = new FuzzyMatcher(state.sliceDoc(a.from, a.to)), match;
9142
9412
  for (let option of a.result.options)
9143
9413
  if (match = matcher.match(option.label)) {
9144
- if (option.boost != null)
9145
- match[0] += option.boost;
9146
- options.push(new Option(option, a, match));
9414
+ addOption(new Option(option, a.source, match, match[0] + (option.boost || 0)));
9147
9415
  }
9148
9416
  }
9149
9417
  }
9418
+ if (sections) {
9419
+ let sectionOrder = Object.create(null), pos = 0;
9420
+ let cmp = (a, b) => { var _a, _b; return ((_a = a.rank) !== null && _a !== void 0 ? _a : 1e9) - ((_b = b.rank) !== null && _b !== void 0 ? _b : 1e9) || (a.name < b.name ? -1 : 1); };
9421
+ for (let s of sections.sort(cmp)) {
9422
+ pos -= 1e5;
9423
+ sectionOrder[s.name] = pos;
9424
+ }
9425
+ for (let option of options) {
9426
+ let { section } = option.completion;
9427
+ if (section)
9428
+ option.score += sectionOrder[typeof section == "string" ? section : section.name];
9429
+ }
9430
+ }
9150
9431
  let result = [], prev = null;
9151
9432
  let compare = state.facet(completionConfig).compareCompletions;
9152
- for (let opt of options.sort((a, b) => (b.match[0] - a.match[0]) || compare(a.completion, b.completion))) {
9433
+ for (let opt of options.sort((a, b) => (b.score - a.score) || compare(a.completion, b.completion))) {
9153
9434
  if (!prev || prev.label != opt.completion.label || prev.detail != opt.completion.detail ||
9154
9435
  (prev.type != null && opt.completion.type != null && prev.type != opt.completion.type) ||
9155
9436
  prev.apply != opt.completion.apply)
@@ -9343,8 +9624,6 @@ function checkValid(validFor, state, from, to) {
9343
9624
  let text = state.sliceDoc(from, to);
9344
9625
  return typeof validFor == "function" ? validFor(text, from, to, state) : ensureAnchor(validFor, true).test(text);
9345
9626
  }
9346
- const startCompletionEffect = /*@__PURE__*/state_.StateEffect.define();
9347
- const closeCompletionEffect = /*@__PURE__*/state_.StateEffect.define();
9348
9627
  const setActiveEffect = /*@__PURE__*/state_.StateEffect.define({
9349
9628
  map(sources, mapping) { return sources.map(s => s.map(mapping)); }
9350
9629
  });
@@ -9358,218 +9637,6 @@ const completionState = /*@__PURE__*/state_.StateField.define({
9358
9637
  ]
9359
9638
  });
9360
9639
 
9361
- /**
9362
- Returns a command that moves the completion selection forward or
9363
- backward by the given amount.
9364
- */
9365
- function moveCompletionSelection(forward, by = "option") {
9366
- return (view) => {
9367
- let cState = view.state.field(completionState, false);
9368
- if (!cState || !cState.open || cState.open.disabled ||
9369
- Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay)
9370
- return false;
9371
- let step = 1, tooltip;
9372
- if (by == "page" && (tooltip = (0,view_.getTooltip)(view, cState.open.tooltip)))
9373
- step = Math.max(2, Math.floor(tooltip.dom.offsetHeight /
9374
- tooltip.dom.querySelector("li").offsetHeight) - 1);
9375
- let { length } = cState.open.options;
9376
- let selected = cState.open.selected > -1 ? cState.open.selected + step * (forward ? 1 : -1) : forward ? 0 : length - 1;
9377
- if (selected < 0)
9378
- selected = by == "page" ? 0 : length - 1;
9379
- else if (selected >= length)
9380
- selected = by == "page" ? length - 1 : 0;
9381
- view.dispatch({ effects: setSelectedEffect.of(selected) });
9382
- return true;
9383
- };
9384
- }
9385
- /**
9386
- Accept the current completion.
9387
- */
9388
- const acceptCompletion = (view) => {
9389
- let cState = view.state.field(completionState, false);
9390
- if (view.state.readOnly || !cState || !cState.open || cState.open.selected < 0 ||
9391
- Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay)
9392
- return false;
9393
- if (!cState.open.disabled)
9394
- applyCompletion(view, cState.open.options[cState.open.selected]);
9395
- return true;
9396
- };
9397
- /**
9398
- Explicitly start autocompletion.
9399
- */
9400
- const startCompletion = (view) => {
9401
- let cState = view.state.field(completionState, false);
9402
- if (!cState)
9403
- return false;
9404
- view.dispatch({ effects: startCompletionEffect.of(true) });
9405
- return true;
9406
- };
9407
- /**
9408
- Close the currently active completion.
9409
- */
9410
- const closeCompletion = (view) => {
9411
- let cState = view.state.field(completionState, false);
9412
- if (!cState || !cState.active.some(a => a.state != 0 /* State.Inactive */))
9413
- return false;
9414
- view.dispatch({ effects: closeCompletionEffect.of(null) });
9415
- return true;
9416
- };
9417
- class RunningQuery {
9418
- constructor(active, context) {
9419
- this.active = active;
9420
- this.context = context;
9421
- this.time = Date.now();
9422
- this.updates = [];
9423
- // Note that 'undefined' means 'not done yet', whereas 'null' means
9424
- // 'query returned null'.
9425
- this.done = undefined;
9426
- }
9427
- }
9428
- const DebounceTime = 50, MaxUpdateCount = 50, MinAbortTime = 1000;
9429
- const completionPlugin = /*@__PURE__*/view_.ViewPlugin.fromClass(class {
9430
- constructor(view) {
9431
- this.view = view;
9432
- this.debounceUpdate = -1;
9433
- this.running = [];
9434
- this.debounceAccept = -1;
9435
- this.composing = 0 /* CompositionState.None */;
9436
- for (let active of view.state.field(completionState).active)
9437
- if (active.state == 1 /* State.Pending */)
9438
- this.startQuery(active);
9439
- }
9440
- update(update) {
9441
- let cState = update.state.field(completionState);
9442
- if (!update.selectionSet && !update.docChanged && update.startState.field(completionState) == cState)
9443
- return;
9444
- let doesReset = update.transactions.some(tr => {
9445
- return (tr.selection || tr.docChanged) && !getUserEvent(tr);
9446
- });
9447
- for (let i = 0; i < this.running.length; i++) {
9448
- let query = this.running[i];
9449
- if (doesReset ||
9450
- query.updates.length + update.transactions.length > MaxUpdateCount && Date.now() - query.time > MinAbortTime) {
9451
- for (let handler of query.context.abortListeners) {
9452
- try {
9453
- handler();
9454
- }
9455
- catch (e) {
9456
- (0,view_.logException)(this.view.state, e);
9457
- }
9458
- }
9459
- query.context.abortListeners = null;
9460
- this.running.splice(i--, 1);
9461
- }
9462
- else {
9463
- query.updates.push(...update.transactions);
9464
- }
9465
- }
9466
- if (this.debounceUpdate > -1)
9467
- clearTimeout(this.debounceUpdate);
9468
- this.debounceUpdate = cState.active.some(a => a.state == 1 /* State.Pending */ && !this.running.some(q => q.active.source == a.source))
9469
- ? setTimeout(() => this.startUpdate(), DebounceTime) : -1;
9470
- if (this.composing != 0 /* CompositionState.None */)
9471
- for (let tr of update.transactions) {
9472
- if (getUserEvent(tr) == "input")
9473
- this.composing = 2 /* CompositionState.Changed */;
9474
- else if (this.composing == 2 /* CompositionState.Changed */ && tr.selection)
9475
- this.composing = 3 /* CompositionState.ChangedAndMoved */;
9476
- }
9477
- }
9478
- startUpdate() {
9479
- this.debounceUpdate = -1;
9480
- let { state } = this.view, cState = state.field(completionState);
9481
- for (let active of cState.active) {
9482
- if (active.state == 1 /* State.Pending */ && !this.running.some(r => r.active.source == active.source))
9483
- this.startQuery(active);
9484
- }
9485
- }
9486
- startQuery(active) {
9487
- let { state } = this.view, pos = cur(state);
9488
- let context = new CompletionContext(state, pos, active.explicitPos == pos);
9489
- let pending = new RunningQuery(active, context);
9490
- this.running.push(pending);
9491
- Promise.resolve(active.source(context)).then(result => {
9492
- if (!pending.context.aborted) {
9493
- pending.done = result || null;
9494
- this.scheduleAccept();
9495
- }
9496
- }, err => {
9497
- this.view.dispatch({ effects: closeCompletionEffect.of(null) });
9498
- (0,view_.logException)(this.view.state, err);
9499
- });
9500
- }
9501
- scheduleAccept() {
9502
- if (this.running.every(q => q.done !== undefined))
9503
- this.accept();
9504
- else if (this.debounceAccept < 0)
9505
- this.debounceAccept = setTimeout(() => this.accept(), DebounceTime);
9506
- }
9507
- // For each finished query in this.running, try to create a result
9508
- // or, if appropriate, restart the query.
9509
- accept() {
9510
- var _a;
9511
- if (this.debounceAccept > -1)
9512
- clearTimeout(this.debounceAccept);
9513
- this.debounceAccept = -1;
9514
- let updated = [];
9515
- let conf = this.view.state.facet(completionConfig);
9516
- for (let i = 0; i < this.running.length; i++) {
9517
- let query = this.running[i];
9518
- if (query.done === undefined)
9519
- continue;
9520
- this.running.splice(i--, 1);
9521
- if (query.done) {
9522
- let active = new ActiveResult(query.active.source, query.active.explicitPos, query.done, query.done.from, (_a = query.done.to) !== null && _a !== void 0 ? _a : cur(query.updates.length ? query.updates[0].startState : this.view.state));
9523
- // Replay the transactions that happened since the start of
9524
- // the request and see if that preserves the result
9525
- for (let tr of query.updates)
9526
- active = active.update(tr, conf);
9527
- if (active.hasResult()) {
9528
- updated.push(active);
9529
- continue;
9530
- }
9531
- }
9532
- let current = this.view.state.field(completionState).active.find(a => a.source == query.active.source);
9533
- if (current && current.state == 1 /* State.Pending */) {
9534
- if (query.done == null) {
9535
- // Explicitly failed. Should clear the pending status if it
9536
- // hasn't been re-set in the meantime.
9537
- let active = new ActiveSource(query.active.source, 0 /* State.Inactive */);
9538
- for (let tr of query.updates)
9539
- active = active.update(tr, conf);
9540
- if (active.state != 1 /* State.Pending */)
9541
- updated.push(active);
9542
- }
9543
- else {
9544
- // Cleared by subsequent transactions. Restart.
9545
- this.startQuery(current);
9546
- }
9547
- }
9548
- }
9549
- if (updated.length)
9550
- this.view.dispatch({ effects: setActiveEffect.of(updated) });
9551
- }
9552
- }, {
9553
- eventHandlers: {
9554
- blur() {
9555
- let state = this.view.state.field(completionState, false);
9556
- if (state && state.tooltip && this.view.state.facet(completionConfig).closeOnBlur)
9557
- this.view.dispatch({ effects: closeCompletionEffect.of(null) });
9558
- },
9559
- compositionstart() {
9560
- this.composing = 1 /* CompositionState.Started */;
9561
- },
9562
- compositionend() {
9563
- if (this.composing == 3 /* CompositionState.ChangedAndMoved */) {
9564
- // Safari fires compositionend events synchronously, possibly
9565
- // from inside an update, so dispatch asynchronously to avoid reentrancy
9566
- setTimeout(() => this.view.dispatch({ effects: startCompletionEffect.of(false) }), 20);
9567
- }
9568
- this.composing = 0 /* CompositionState.None */;
9569
- }
9570
- }
9571
- });
9572
-
9573
9640
  const autocomplete_dist_baseTheme = /*@__PURE__*/view_.EditorView.baseTheme({
9574
9641
  ".cm-tooltip.cm-tooltip-autocomplete": {
9575
9642
  "& > ul": {
@@ -9584,13 +9651,21 @@ const autocomplete_dist_baseTheme = /*@__PURE__*/view_.EditorView.baseTheme({
9584
9651
  listStyle: "none",
9585
9652
  margin: 0,
9586
9653
  padding: 0,
9654
+ "& > li, & > completion-section": {
9655
+ padding: "1px 3px",
9656
+ lineHeight: 1.2
9657
+ },
9587
9658
  "& > li": {
9588
9659
  overflowX: "hidden",
9589
9660
  textOverflow: "ellipsis",
9590
- cursor: "pointer",
9591
- padding: "1px 3px",
9592
- lineHeight: 1.2
9661
+ cursor: "pointer"
9593
9662
  },
9663
+ "& > completion-section": {
9664
+ display: "list-item",
9665
+ borderBottom: "1px solid silver",
9666
+ paddingLeft: "0.5em",
9667
+ opacity: 0.7
9668
+ }
9594
9669
  }
9595
9670
  },
9596
9671
  "&light .cm-tooltip-autocomplete ul li[aria-selected]": {
@@ -9853,7 +9928,7 @@ function snippet(template) {
9853
9928
  let spec = {
9854
9929
  changes: { from, to, insert: Text.of(text) },
9855
9930
  scrollIntoView: true,
9856
- annotations: pickedCompletion.of(completion)
9931
+ annotations: completion ? pickedCompletion.of(completion) : undefined
9857
9932
  };
9858
9933
  if (ranges.length)
9859
9934
  spec.selection = fieldSelection(ranges, 0);
@@ -9897,6 +9972,22 @@ const nextSnippetField = /*@__PURE__*/moveField(1);
9897
9972
  Move to the previous snippet field, if available.
9898
9973
  */
9899
9974
  const prevSnippetField = /*@__PURE__*/moveField(-1);
9975
+ /**
9976
+ Check if there is an active snippet with a next field for
9977
+ `nextSnippetField` to move to.
9978
+ */
9979
+ function hasNextSnippetField(state) {
9980
+ let active = state.field(snippetState, false);
9981
+ return !!(active && active.ranges.some(r => r.field == active.active + 1));
9982
+ }
9983
+ /**
9984
+ Returns true if there is an active snippet and a previous field
9985
+ for `prevSnippetField` to move to.
9986
+ */
9987
+ function hasPrevSnippetField(state) {
9988
+ let active = state.field(snippetState, false);
9989
+ return !!(active && active.active > 0);
9990
+ }
9900
9991
  const defaultSnippetKeymap = [
9901
9992
  { key: "Tab", run: nextSnippetField, shift: prevSnippetField },
9902
9993
  { key: "Escape", run: clearSnippet }
@@ -10024,9 +10115,6 @@ const closeBracketEffect = /*@__PURE__*/state_.StateEffect.define({
10024
10115
  return mapped == null ? undefined : mapped;
10025
10116
  }
10026
10117
  });
10027
- const skipBracketEffect = /*@__PURE__*/state_.StateEffect.define({
10028
- map(value, mapping) { return mapping.mapPos(value); }
10029
- });
10030
10118
  const closedBracket = /*@__PURE__*/new class extends state_.RangeValue {
10031
10119
  };
10032
10120
  closedBracket.startSide = 1;
@@ -10041,12 +10129,9 @@ const bracketState = /*@__PURE__*/state_.StateField.define({
10041
10129
  value = state_.RangeSet.empty;
10042
10130
  }
10043
10131
  value = value.map(tr.changes);
10044
- for (let effect of tr.effects) {
10132
+ for (let effect of tr.effects)
10045
10133
  if (effect.is(closeBracketEffect))
10046
10134
  value = value.update({ add: [closedBracket.range(effect.value, effect.value + 1)] });
10047
- else if (effect.is(skipBracketEffect))
10048
- value = value.update({ filter: from => from != effect.value });
10049
- }
10050
10135
  return value;
10051
10136
  }
10052
10137
  });
@@ -10174,15 +10259,15 @@ function handleOpen(state, open, close, closeBefore) {
10174
10259
  });
10175
10260
  }
10176
10261
  function handleClose(state, _open, close) {
10177
- let dont = null, moved = state.selection.ranges.map(range => {
10262
+ let dont = null, changes = state.changeByRange(range => {
10178
10263
  if (range.empty && nextChar(state.doc, range.head) == close)
10179
- return state_.EditorSelection.cursor(range.head + close.length);
10180
- return dont = range;
10264
+ return { changes: { from: range.head, to: range.head + close.length, insert: close },
10265
+ range: state_.EditorSelection.cursor(range.head + close.length) };
10266
+ return dont = { range };
10181
10267
  });
10182
- return dont ? null : state.update({
10183
- selection: state_.EditorSelection.create(moved, state.selection.mainIndex),
10268
+ return dont ? null : state.update(changes, {
10184
10269
  scrollIntoView: true,
10185
- effects: state.selection.ranges.map(({ from }) => skipBracketEffect.of(from))
10270
+ userEvent: "input.type"
10186
10271
  });
10187
10272
  }
10188
10273
  // Handles cases where the open and close token are the same, and
@@ -10203,8 +10288,9 @@ function handleSame(state, token, allowTriple, config) {
10203
10288
  }
10204
10289
  else if (closedBracketAt(state, pos)) {
10205
10290
  let isTriple = allowTriple && state.sliceDoc(pos, pos + token.length * 3) == token + token + token;
10206
- return { range: state_.EditorSelection.cursor(pos + token.length * (isTriple ? 3 : 1)),
10207
- effects: skipBracketEffect.of(pos) };
10291
+ let content = isTriple ? token + token + token : token;
10292
+ return { changes: { from: pos, to: pos + content.length, insert: content },
10293
+ range: state_.EditorSelection.cursor(pos + content.length) };
10208
10294
  }
10209
10295
  }
10210
10296
  else if (allowTriple && state.sliceDoc(pos - 2 * token.length, pos) == token + token &&
@@ -10403,17 +10489,7 @@ function hideTooltip(tr, tooltip) {
10403
10489
  return !!(tr.effects.some(e => e.is(setDiagnosticsEffect)) || tr.changes.touchesRange(tooltip.pos));
10404
10490
  }
10405
10491
  function maybeEnableLint(state, effects) {
10406
- return state.field(lintState, false) ? effects : effects.concat(state_.StateEffect.appendConfig.of([
10407
- lintState,
10408
- view_.EditorView.decorations.compute([lintState], state => {
10409
- let { selected, panel } = state.field(lintState);
10410
- return !selected || !panel || selected.from == selected.to ? view_.Decoration.none : view_.Decoration.set([
10411
- activeMark.range(selected.from, selected.to)
10412
- ]);
10413
- }),
10414
- (0,view_.hoverTooltip)(lintTooltip, { hideOn: hideTooltip }),
10415
- lint_dist_baseTheme
10416
- ]));
10492
+ return state.field(lintState, false) ? effects : effects.concat(state_.StateEffect.appendConfig.of(lintExtensions));
10417
10493
  }
10418
10494
  /**
10419
10495
  Returns a transaction spec which updates the current set of
@@ -10545,7 +10621,7 @@ const lintKeymap = [
10545
10621
  { key: "Mod-Shift-m", run: openLintPanel, preventDefault: true },
10546
10622
  { key: "F8", run: nextDiagnostic }
10547
10623
  ];
10548
- const lintPlugin = /*@__PURE__*/view_.ViewPlugin.fromClass(class {
10624
+ const lintPlugin = /*@__PURE__*/(/* unused pure expression or super */ null && (ViewPlugin.fromClass(class {
10549
10625
  constructor(view) {
10550
10626
  this.view = view;
10551
10627
  this.timeout = -1;
@@ -10567,7 +10643,7 @@ const lintPlugin = /*@__PURE__*/view_.ViewPlugin.fromClass(class {
10567
10643
  let all = annotations.reduce((a, b) => a.concat(b));
10568
10644
  if (this.view.state.doc == state.doc)
10569
10645
  this.view.dispatch(setDiagnostics(this.view.state, all));
10570
- }, error => { (0,view_.logException)(this.view.state, error); });
10646
+ }, error => { logException(this.view.state, error); });
10571
10647
  }
10572
10648
  }
10573
10649
  update(update) {
@@ -10590,7 +10666,7 @@ const lintPlugin = /*@__PURE__*/view_.ViewPlugin.fromClass(class {
10590
10666
  destroy() {
10591
10667
  clearTimeout(this.timeout);
10592
10668
  }
10593
- });
10669
+ })));
10594
10670
  const lintConfig = /*@__PURE__*/state_.Facet.define({
10595
10671
  combine(input) {
10596
10672
  return Object.assign({ sources: input.map(i => i.source) }, (0,state_.combineConfig)(input.map(i => i.config), {
@@ -10601,8 +10677,7 @@ const lintConfig = /*@__PURE__*/state_.Facet.define({
10601
10677
  }, {
10602
10678
  needsRefresh: (a, b) => !a ? b : !b ? a : u => a(u) || b(u)
10603
10679
  }));
10604
- },
10605
- enables: lintPlugin
10680
+ }
10606
10681
  });
10607
10682
  /**
10608
10683
  Given a diagnostic source, this function returns an extension that
@@ -10610,7 +10685,11 @@ enables linting with that source. It will be called whenever the
10610
10685
  editor is idle (after its content changed).
10611
10686
  */
10612
10687
  function linter(source, config = {}) {
10613
- return lintConfig.of({ source, config });
10688
+ return [
10689
+ lintConfig.of({ source, config }),
10690
+ lintPlugin,
10691
+ lintExtensions
10692
+ ];
10614
10693
  }
10615
10694
  /**
10616
10695
  Forces any linters [configured](https://codemirror.net/6/docs/ref/#lint.linter) to run when the
@@ -11072,6 +11151,17 @@ const lintGutterTheme = /*@__PURE__*/view_.EditorView.baseTheme({
11072
11151
  content: /*@__PURE__*/svg(`<circle cx="20" cy="20" r="15" fill="#f87" stroke="#f43" stroke-width="6"/>`)
11073
11152
  },
11074
11153
  });
11154
+ const lintExtensions = [
11155
+ lintState,
11156
+ /*@__PURE__*/view_.EditorView.decorations.compute([lintState], state => {
11157
+ let { selected, panel } = state.field(lintState);
11158
+ return !selected || !panel || selected.from == selected.to ? view_.Decoration.none : view_.Decoration.set([
11159
+ activeMark.range(selected.from, selected.to)
11160
+ ]);
11161
+ }),
11162
+ /*@__PURE__*/(0,view_.hoverTooltip)(lintTooltip, { hideOn: hideTooltip }),
11163
+ lint_dist_baseTheme
11164
+ ];
11075
11165
  const lintGutterConfig = /*@__PURE__*/state_.Facet.define({
11076
11166
  combine(configs) {
11077
11167
  return (0,state_.combineConfig)(configs, {