@matdata/yasqe 5.20.3 → 6.1.0

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.
Files changed (76) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +76 -59
  3. package/build/prefixes.json +2169 -2115
  4. package/build/ts/grammar/tokenizer.d.ts +9 -3
  5. package/build/ts/grammar/tokenizer.js +34 -6
  6. package/build/ts/grammar/tokenizer.js.map +1 -1
  7. package/build/ts/src/autocompleters/index.d.ts +4 -2
  8. package/build/ts/src/autocompleters/index.js +9 -33
  9. package/build/ts/src/autocompleters/index.js.map +1 -1
  10. package/build/ts/src/autocompleters/variables.js +17 -19
  11. package/build/ts/src/autocompleters/variables.js.map +1 -1
  12. package/build/ts/src/defaults.d.ts +17 -53
  13. package/build/ts/src/defaults.js +2 -5
  14. package/build/ts/src/defaults.js.map +1 -1
  15. package/build/ts/src/editor/autocompletion.d.ts +32 -0
  16. package/build/ts/src/editor/autocompletion.js +94 -0
  17. package/build/ts/src/editor/autocompletion.js.map +1 -0
  18. package/build/ts/src/editor/doc.d.ts +32 -0
  19. package/build/ts/src/editor/doc.js +121 -0
  20. package/build/ts/src/editor/doc.js.map +1 -0
  21. package/build/ts/src/editor/facade.d.ts +94 -0
  22. package/build/ts/src/editor/facade.js +392 -0
  23. package/build/ts/src/editor/facade.js.map +1 -0
  24. package/build/ts/src/editor/folding.d.ts +16 -0
  25. package/build/ts/src/editor/folding.js +190 -0
  26. package/build/ts/src/editor/folding.js.map +1 -0
  27. package/build/ts/src/editor/gutters.d.ts +8 -0
  28. package/build/ts/src/editor/gutters.js +113 -0
  29. package/build/ts/src/editor/gutters.js.map +1 -0
  30. package/build/ts/src/editor/keymap.d.ts +11 -0
  31. package/build/ts/src/editor/keymap.js +88 -0
  32. package/build/ts/src/editor/keymap.js.map +1 -0
  33. package/build/ts/src/editor/language.d.ts +11 -0
  34. package/build/ts/src/editor/language.js +19 -0
  35. package/build/ts/src/editor/language.js.map +1 -0
  36. package/build/ts/src/editor/tokenizerRunner.d.ts +37 -0
  37. package/build/ts/src/editor/tokenizerRunner.js +115 -0
  38. package/build/ts/src/editor/tokenizerRunner.js.map +1 -0
  39. package/build/ts/src/index.d.ts +49 -100
  40. package/build/ts/src/index.js +179 -100
  41. package/build/ts/src/index.js.map +1 -1
  42. package/build/ts/src/prefixes.json +2191 -2137
  43. package/build/ts/src/tooltip.js +9 -6
  44. package/build/ts/src/tooltip.js.map +1 -1
  45. package/build/yasqe.min.css +1 -1
  46. package/build/yasqe.min.css.map +3 -3
  47. package/build/yasqe.min.js +76 -91
  48. package/build/yasqe.min.js.map +4 -4
  49. package/grammar/tokenizer.ts +62 -8
  50. package/package.json +11 -6
  51. package/src/autocompleters/index.ts +24 -53
  52. package/src/autocompleters/show-hint.scss +17 -9
  53. package/src/autocompleters/variables.ts +20 -24
  54. package/src/defaults.ts +2 -6
  55. package/src/editor/autocompletion.ts +147 -0
  56. package/src/editor/doc.ts +151 -0
  57. package/src/editor/facade.ts +558 -0
  58. package/src/editor/folding.ts +225 -0
  59. package/src/editor/gutters.ts +152 -0
  60. package/src/editor/keymap.ts +133 -0
  61. package/src/editor/language.ts +47 -0
  62. package/src/editor/tokenizerRunner.ts +198 -0
  63. package/src/index.ts +193 -127
  64. package/src/prefixes.json +2169 -2115
  65. package/src/scss/buttons.scss +4 -2
  66. package/src/scss/codemirrorMods.scss +107 -11
  67. package/src/scss/yasqe.scss +4 -2
  68. package/src/tooltip.ts +16 -13
  69. package/build/ts/src/CodeMirror.d.ts +0 -30
  70. package/build/ts/src/CodeMirror.js +0 -20
  71. package/build/ts/src/CodeMirror.js.map +0 -1
  72. package/build/ts/src/prefixFold.d.ts +0 -8
  73. package/build/ts/src/prefixFold.js +0 -87
  74. package/build/ts/src/prefixFold.js.map +0 -1
  75. package/src/CodeMirror.ts +0 -54
  76. package/src/prefixFold.ts +0 -94
package/src/index.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import "./scss/yasqe.scss";
2
2
  import "./scss/buttons.scss";
3
+ import "./scss/codemirrorMods.scss";
3
4
  import "leaflet/dist/leaflet.css";
4
- import { findFirstPrefixLine } from "./prefixFold";
5
+ import { findFirstPrefixLine as findFirstPrefixLineInDoc, foldAt, unfoldAt } from "./editor/folding";
5
6
  import { getPrefixesFromQuery, addPrefixes, removePrefixes, Prefixes } from "./prefixUtils";
6
7
  import { getPreviousNonWsToken, getNextNonWsToken, getCompleteToken } from "./tokenUtils";
7
- import * as sparql11Mode from "../grammar/tokenizer";
8
8
  import { Storage as YStorage } from "@matdata/yasgui-utils";
9
9
  import * as queryString from "query-string";
10
10
  import tooltip from "./tooltip";
@@ -15,7 +15,12 @@ import * as Autocompleter from "./autocompleters";
15
15
  import { merge, mergeWith, escape } from "lodash-es";
16
16
 
17
17
  import getDefaults from "./defaults";
18
- import CodeMirror from "./CodeMirror";
18
+ import { EditorFacade, EditorOptions } from "./editor/facade";
19
+ import { runMode as runTokenizer } from "./editor/tokenizerRunner";
20
+ import type { Position, Token, TokenizerState } from "./editor/tokenizerRunner";
21
+ import type { ExtraKeys } from "./editor/keymap";
22
+ import type { HintFn, HintList } from "./editor/autocompletion";
23
+ import { isCompletionActive, openCompletion, hideCompletion } from "./editor/autocompletion";
19
24
  import { YasqeAjaxConfig } from "./sparql";
20
25
  import { spfmt } from "sparql-formatter";
21
26
  import * as L from "leaflet";
@@ -34,7 +39,6 @@ export interface Yasqe {
34
39
  off(eventName: "queryAbort", handler: (instance: Yasqe, req: Request) => void): void;
35
40
  on(eventName: "queryResponse", handler: (instance: Yasqe, response: any, duration: number) => void): void;
36
41
  off(eventName: "queryResponse", handler: (instance: Yasqe, response: any, duration: number) => void): void;
37
- showHint: (conf: HintConfig) => void;
38
42
  on(eventName: "error", handler: (instance: Yasqe) => void): void;
39
43
  off(eventName: "error", handler: (instance: Yasqe) => void): void;
40
44
  on(eventName: "blur", handler: (instance: Yasqe) => void): void;
@@ -53,10 +57,61 @@ export interface Yasqe {
53
57
  off(eventName: "saveManagedQuery", handler: () => void): void;
54
58
  on(eventName: "downloadRqFile", handler: () => void): void;
55
59
  off(eventName: "downloadRqFile", handler: () => void): void;
56
- on(eventName: string, handler: () => void): void;
60
+ on(eventName: "change", handler: (instance: Yasqe, changeObj?: any) => void): void;
61
+ off(eventName: "change", handler: (instance: Yasqe, changeObj?: any) => void): void;
62
+ on(eventName: "changes", handler: (instance: Yasqe) => void): void;
63
+ off(eventName: "changes", handler: (instance: Yasqe) => void): void;
64
+ on(eventName: "cursorActivity", handler: (instance: Yasqe) => void): void;
65
+ off(eventName: "cursorActivity", handler: (instance: Yasqe) => void): void;
66
+ on(eventName: "focus", handler: (instance: Yasqe) => void): void;
67
+ off(eventName: "focus", handler: (instance: Yasqe) => void): void;
68
+ on(eventName: string, handler: (...args: any[]) => void): void;
69
+ off(eventName: string, handler: (...args: any[]) => void): void;
57
70
  }
58
71
 
59
- export class Yasqe extends CodeMirror {
72
+ /** Editor option keys that are handed to the underlying CodeMirror 6 editor */
73
+ const EDITOR_OPTION_KEYS: (keyof EditorOptions)[] = [
74
+ "mode",
75
+ "value",
76
+ "lineNumbers",
77
+ "lineWrapping",
78
+ "readOnly",
79
+ "tabSize",
80
+ "indentUnit",
81
+ "indentWithTabs",
82
+ "theme",
83
+ "extraKeys",
84
+ "tabMode",
85
+ "foldGutter",
86
+ "gutters",
87
+ "matchBrackets",
88
+ "highlightSelectionMatches",
89
+ "autoCloseBrackets",
90
+ "fixedGutter",
91
+ "placeholder",
92
+ "autofocus",
93
+ "viewportMargin",
94
+ ];
95
+
96
+ function mergeConfig(conf: PartialConfig): Config {
97
+ // Use mergeWith to replace arrays instead of merging them by index
98
+ // This ensures that snippets: [] properly overrides default snippets
99
+ return mergeWith({}, Yasqe.defaults, conf, (_objValue: any, srcValue: any) => {
100
+ if (Array.isArray(srcValue)) {
101
+ return srcValue;
102
+ }
103
+ });
104
+ }
105
+
106
+ function createRootEl(parent: HTMLElement): HTMLDivElement {
107
+ if (!parent) throw new Error("No parent passed as argument. Dont know where to draw YASQE");
108
+ const rootEl = document.createElement("div");
109
+ rootEl.className = "yasqe";
110
+ parent.appendChild(rootEl);
111
+ return rootEl;
112
+ }
113
+
114
+ export class Yasqe extends EditorFacade {
60
115
  private static storageNamespace = "triply";
61
116
  public autocompleters: { [name: string]: Autocompleter.Completer | undefined } = {};
62
117
  private prevQueryValid = false;
@@ -84,27 +139,15 @@ export class Yasqe extends CodeMirror {
84
139
  public config: Config;
85
140
  public persistentConfig: PersistentConfig | undefined;
86
141
  constructor(parent: HTMLElement, conf: PartialConfig = {}) {
87
- super();
88
- if (!parent) throw new Error("No parent passed as argument. Dont know where to draw YASQE");
89
- this.rootEl = document.createElement("div");
90
- this.rootEl.className = "yasqe";
91
- parent.appendChild(this.rootEl);
92
- // Use mergeWith to replace arrays instead of merging them by index
93
- // This ensures that snippets: [] properly overrides default snippets
94
- this.config = mergeWith({}, Yasqe.defaults, conf, (objValue: any, srcValue: any) => {
95
- if (Array.isArray(srcValue)) {
96
- return srcValue;
97
- }
98
- });
99
- //inherit codemirror props
100
- const cm = (CodeMirror as any)(this.rootEl, this.config);
101
- //Assign our functions to the cm object. This is needed, as some functions (like the ctrl-enter callback)
102
- //get the original cm as argument, and not yasqe
103
- for (const key of Object.getOwnPropertyNames(Yasqe.prototype)) {
104
- cm[key] = (<any>Yasqe.prototype)[key].bind(this);
142
+ const config = mergeConfig(conf);
143
+ const rootEl = createRootEl(parent);
144
+ const editorOptions: EditorOptions = {};
145
+ for (const key of EDITOR_OPTION_KEYS) {
146
+ if ((config as any)[key] !== undefined) (editorOptions as any)[key] = (config as any)[key];
105
147
  }
106
- //Also assign the codemirror functions to our object, so we can easily use those
107
- Object.assign(this, CodeMirror.prototype, cm);
148
+ super(rootEl, editorOptions);
149
+ this.rootEl = rootEl;
150
+ this.config = config;
108
151
 
109
152
  //Do some post processing
110
153
  this.storage = new YStorage(Yasqe.storageNamespace);
@@ -162,21 +205,21 @@ export class Yasqe extends CodeMirror {
162
205
  private handleHashChange = () => {
163
206
  this.config.consumeShareLink?.(this);
164
207
  };
165
- private handleChange() {
208
+ private handleChange = () => {
166
209
  this.checkSyntax();
167
210
  this.checkConstructVariables();
168
211
  this.updateQueryButton();
169
- }
170
- private handleBlur() {
212
+ };
213
+ private handleBlur = () => {
171
214
  this.saveQuery();
172
- }
173
- private handleChanges() {
215
+ };
216
+ private handleChanges = () => {
174
217
  // e.g. handle blur
175
218
  this.checkSyntax();
176
219
  this.checkConstructVariables();
177
220
  this.updateQueryButton();
178
- }
179
- private handleCursorActivity() {
221
+ };
222
+ private handleCursorActivity = () => {
180
223
  this.autocomplete(true);
181
224
 
182
225
  // Check if cursor is on a URI and show DESCRIBE hint
@@ -185,25 +228,40 @@ export class Yasqe extends CodeMirror {
185
228
 
186
229
  if (token && token.type === "variable-3") {
187
230
  // Token type "variable-3" represents URIs (IRI_REF)
188
- this.showNotification("uri-describe-hint", "Hold CTRL - left mouse click on URI to DESCRIBE");
231
+ this.showNotification(
232
+ "uri-describe-hint",
233
+ "CTRL+click: find triples where URI is subject. CTRL+SHIFT+click: find triples where URI is object.",
234
+ );
189
235
  } else {
190
236
  this.hideNotification("uri-describe-hint");
191
237
  }
192
- }
193
- private handleQuery(_yasqe: Yasqe, req: Request, abortController?: AbortController) {
238
+ };
239
+ private handleQuery = (_yasqe: Yasqe, req: Request, abortController?: AbortController) => {
194
240
  this.req = req;
195
241
  this.abortController = abortController;
196
242
  this.updateQueryButton();
197
- }
198
- private handleQueryResponse(_yasqe: Yasqe, _response: any, duration: number) {
243
+ };
244
+ private handleQueryResponse = (_yasqe: Yasqe, _response: any, duration: number) => {
199
245
  this.lastQueryDuration = duration;
200
246
  this.req = undefined;
201
247
  this.updateQueryButton();
202
- }
203
- private handleQueryAbort(_yasqe: Yasqe, _req: Request) {
248
+ };
249
+ private handleQueryAbort = (_yasqe: Yasqe, _req: Request) => {
204
250
  this.req = undefined;
205
251
  this.updateQueryButton();
252
+ };
253
+
254
+ /**
255
+ * Aggregates the hints of all enabled autocompleters. Used by the CodeMirror 6 completion source.
256
+ */
257
+ protected getHintFn(): HintFn | undefined {
258
+ // `pendingHintFn` is set by `autocomplete()`. When the completion was started by other means (e.g. a
259
+ // CodeMirror `startCompletion` command), build the hint function on demand.
260
+ const hintFn = this.pendingHintFn ?? this.buildHintFn(false);
261
+ this.pendingHintFn = undefined;
262
+ return hintFn;
206
263
  }
264
+ private pendingHintFn: HintFn | undefined;
207
265
 
208
266
  private registerEventListeners() {
209
267
  /**
@@ -220,10 +278,10 @@ export class Yasqe extends CodeMirror {
220
278
  }
221
279
 
222
280
  private unregisterEventListeners() {
223
- this.off("change" as any, this.handleChange);
281
+ this.off("change", this.handleChange);
224
282
  this.off("blur", this.handleBlur);
225
- this.off("changes" as any, this.handleChanges);
226
- this.off("cursorActivity" as any, this.handleCursorActivity);
283
+ this.off("changes", this.handleChanges);
284
+ this.off("cursorActivity", this.handleCursorActivity);
227
285
 
228
286
  this.off("query", this.handleQuery);
229
287
  this.off("queryResponse", this.handleQueryResponse);
@@ -232,10 +290,6 @@ export class Yasqe extends CodeMirror {
232
290
  /**
233
291
  * Generic IDE functions
234
292
  */
235
- public emit(event: string, ...data: any[]) {
236
- CodeMirror.signal(this, event, this, ...data);
237
- }
238
-
239
293
  public getStorageId(getter?: Config["persistenceId"]): string | undefined {
240
294
  const persistenceId = getter || this.config.persistenceId;
241
295
  if (!persistenceId) return undefined;
@@ -1435,10 +1489,10 @@ export class Yasqe extends CodeMirror {
1435
1489
  this.horizontalResizeWrapper.addEventListener("dblclick", this.expandEditor);
1436
1490
  this.rootEl.appendChild(this.horizontalResizeWrapper);
1437
1491
  }
1438
- private initDrag() {
1492
+ private initDrag = () => {
1439
1493
  document.documentElement.addEventListener("mousemove", this.doDrag, false);
1440
1494
  document.documentElement.addEventListener("mouseup", this.stopDrag, false);
1441
- }
1495
+ };
1442
1496
  private calculateDragOffset(event: MouseEvent, rootEl: HTMLElement) {
1443
1497
  let parentOffset = 0;
1444
1498
  // offsetParent is, at the time of writing, a working draft. see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetParent
@@ -1451,10 +1505,10 @@ export class Yasqe extends CodeMirror {
1451
1505
  }
1452
1506
  return event.clientY - parentOffset - this.rootEl.offsetTop + scrollOffset;
1453
1507
  }
1454
- private doDrag(event: MouseEvent) {
1508
+ private doDrag = (event: MouseEvent) => {
1455
1509
  this.getWrapperElement().style.height = this.calculateDragOffset(event, this.rootEl) + "px";
1456
- }
1457
- private stopDrag() {
1510
+ };
1511
+ private stopDrag = () => {
1458
1512
  document.documentElement.removeEventListener("mousemove", this.doDrag, false);
1459
1513
  document.documentElement.removeEventListener("mouseup", this.stopDrag, false);
1460
1514
  this.emit("resize", this.getWrapperElement().style.height);
@@ -1469,7 +1523,7 @@ export class Yasqe extends CodeMirror {
1469
1523
  if (this.snippetsResizeHandler) {
1470
1524
  this.snippetsResizeHandler();
1471
1525
  }
1472
- }
1526
+ };
1473
1527
  public duplicateLine() {
1474
1528
  const cur = this.getDoc().getCursor();
1475
1529
  if (cur) {
@@ -1702,11 +1756,7 @@ export class Yasqe extends CodeMirror {
1702
1756
  public autoformat() {
1703
1757
  if (!this.getDoc().somethingSelected()) this.execCommand("selectAll");
1704
1758
  const from = this.getDoc().getCursor("start");
1705
-
1706
- var to: Position = {
1707
- line: this.getDoc().getCursor("end").line,
1708
- ch: this.getDoc().getSelection().length,
1709
- };
1759
+ const to: Position = this.getDoc().getCursor("end");
1710
1760
  var absStart = this.getDoc().indexFromPos(from);
1711
1761
  var absEnd = this.getDoc().indexFromPos(to);
1712
1762
  // Insert additional line breaks where necessary according to the
@@ -1720,7 +1770,7 @@ export class Yasqe extends CodeMirror {
1720
1770
  var startLine = this.getDoc().posFromIndex(absStart).line;
1721
1771
  var endLine = this.getDoc().posFromIndex(absStart + res.length).line;
1722
1772
  for (var i = startLine; i <= endLine; i++) {
1723
- this.indentLine(i, "smart");
1773
+ this.indentLine(i);
1724
1774
  }
1725
1775
  });
1726
1776
  }
@@ -1822,6 +1872,7 @@ export class Yasqe extends CodeMirror {
1822
1872
  this.queryValid = true;
1823
1873
 
1824
1874
  this.clearGutter("gutterErrorBar");
1875
+ this.clearSyntaxErrorHighlight();
1825
1876
 
1826
1877
  var state: TokenizerState;
1827
1878
  for (var l = 0; l < this.getDoc().lineCount(); ++l) {
@@ -1854,6 +1905,18 @@ export class Yasqe extends CodeMirror {
1854
1905
  return;
1855
1906
  }
1856
1907
 
1908
+ const lineLength = this.getDoc().getLine(l).length;
1909
+ const startCh =
1910
+ typeof state.errorStartPos === "number"
1911
+ ? Math.max(0, Math.min(lineLength, state.errorStartPos))
1912
+ : Math.max(0, Math.min(lineLength, token.start));
1913
+ const fallbackEnd = token.string ? startCh + token.string.length : startCh + 1;
1914
+ const endCandidate = typeof state.errorEndPos === "number" ? state.errorEndPos : fallbackEnd;
1915
+ const endCh = Math.max(startCh + 1, Math.min(lineLength, endCandidate));
1916
+ if (endCh > startCh) {
1917
+ this.setSyntaxErrorHighlight({ line: l, ch: startCh }, { line: l, ch: endCh });
1918
+ }
1919
+
1857
1920
  // Add gutter error icon
1858
1921
  const errorEl = document.createElement("i");
1859
1922
  errorEl.className = "fas fa-exclamation-circle parseErrorIcon";
@@ -2059,20 +2122,58 @@ export class Yasqe extends CodeMirror {
2059
2122
  }
2060
2123
  public autocomplete(fromAutoShow = false) {
2061
2124
  if (this.getDoc().somethingSelected()) return;
2062
-
2063
- for (let i in this.config.autocompleters) {
2064
- const autocompleter = this.autocompleters[this.config.autocompleters[i]];
2065
- if (!autocompleter || !autocompleter.autocomplete(fromAutoShow)) continue;
2125
+ const hintFn = this.buildHintFn(fromAutoShow);
2126
+ if (!hintFn) return;
2127
+ this.pendingHintFn = hintFn;
2128
+ openCompletion(this.view);
2129
+ }
2130
+ /**
2131
+ * Collects the hint functions of all completers that are valid at the current position and aggregates
2132
+ * them into a single hint function. Returns `undefined` when no completer applies.
2133
+ */
2134
+ private buildHintFn(fromAutoShow: boolean): HintFn | undefined {
2135
+ const hintFns: HintFn[] = [];
2136
+ for (const name of this.config.autocompleters) {
2137
+ const autocompleter = this.autocompleters[name];
2138
+ if (!autocompleter) continue;
2139
+ const hintFn = autocompleter.autocomplete(fromAutoShow);
2140
+ if (hintFn) hintFns.push(hintFn);
2066
2141
  }
2142
+ if (hintFns.length === 0) return undefined;
2143
+
2144
+ return async (): Promise<HintList | undefined> => {
2145
+ const results = await Promise.all(hintFns.map((fn) => fn()));
2146
+ let aggregated: HintList | undefined;
2147
+ for (const result of results) {
2148
+ if (!result || !result.list || result.list.length === 0) continue;
2149
+ if (!aggregated) {
2150
+ aggregated = { list: [...result.list], from: result.from, to: result.to };
2151
+ } else {
2152
+ aggregated.list.push(...result.list);
2153
+ }
2154
+ }
2155
+ return aggregated;
2156
+ };
2157
+ }
2158
+ public isAutocompletionActive(): boolean {
2159
+ return isCompletionActive(this.view.state);
2160
+ }
2161
+ public hideAutocompletion() {
2162
+ hideCompletion(this.view);
2067
2163
  }
2068
2164
 
2069
2165
  /**
2070
2166
  * Prefix management
2071
2167
  */
2072
2168
  public collapsePrefixes(collapse = true) {
2073
- const firstPrefixLine = findFirstPrefixLine(this);
2169
+ const firstPrefixLine = findFirstPrefixLineInDoc(this.runner, this.view.state.doc);
2074
2170
  if (firstPrefixLine === undefined) return; //nothing to collapse
2075
- this.foldCode(firstPrefixLine, (<any>CodeMirror).fold.prefix, collapse ? "fold" : "unfold");
2171
+ const offset = this.view.state.doc.line(firstPrefixLine + 1).from;
2172
+ if (collapse) {
2173
+ foldAt(this.view, offset);
2174
+ } else {
2175
+ unfoldAt(this.view, offset);
2176
+ }
2076
2177
  }
2077
2178
 
2078
2179
  public getPrefixesFromQuery(): Prefixes {
@@ -2084,15 +2185,11 @@ export class Yasqe extends CodeMirror {
2084
2185
  public removePrefixes(prefixes: Prefixes): void {
2085
2186
  return removePrefixes(this, prefixes);
2086
2187
  }
2188
+ /**
2189
+ * @deprecated CodeMirror 6 positions the autocompletion tooltip itself. Kept for API compatibility.
2190
+ */
2087
2191
  public updateWidget() {
2088
- if (
2089
- (this as any).cursorCoords &&
2090
- (this as any).state.completionActive &&
2091
- (this as any).state.completionActive.widget
2092
- ) {
2093
- const newTop: string = (this as any).cursorCoords(null).bottom;
2094
- (this as any).state.completionActive.widget.hints.style.top = newTop + "px";
2095
- }
2192
+ // no-op
2096
2193
  }
2097
2194
 
2098
2195
  /**
@@ -2161,9 +2258,9 @@ export class Yasqe extends CodeMirror {
2161
2258
  }
2162
2259
  }
2163
2260
 
2164
- public expandEditor() {
2261
+ public expandEditor = () => {
2165
2262
  this.setSize(null, "100%");
2166
- }
2263
+ };
2167
2264
 
2168
2265
  public destroy() {
2169
2266
  // Abort running query
@@ -2180,6 +2277,7 @@ export class Yasqe extends CodeMirror {
2180
2277
  this.disableCompleter(autocompleter);
2181
2278
  }
2182
2279
  window.removeEventListener("hashchange", this.handleHashChange);
2280
+ this.destroyEditor();
2183
2281
  this.rootEl.remove();
2184
2282
  }
2185
2283
 
@@ -2187,7 +2285,13 @@ export class Yasqe extends CodeMirror {
2187
2285
  * Statics
2188
2286
  */
2189
2287
  static Sparql = Sparql;
2190
- static runMode = (<any>CodeMirror).runMode;
2288
+ /**
2289
+ * Tokenizes the given text using the SPARQL tokenizer, calling `callback` for every token with its
2290
+ * text and its style (`null` for whitespace/unstyled tokens). The `mode` argument is ignored and only
2291
+ * kept for backwards compatibility with the CodeMirror 5 `runMode` signature.
2292
+ */
2293
+ static runMode = (text: string, _mode: any, callback: (text: string, style: string | null) => void) =>
2294
+ runTokenizer(text, callback);
2191
2295
  static clearStorage() {
2192
2296
  const storage = new YStorage(Yasqe.storageNamespace);
2193
2297
  storage.removeNamespace();
@@ -2215,61 +2319,24 @@ export class Yasqe extends CodeMirror {
2215
2319
  if (enable && Yasqe.defaults.autocompleters.indexOf(name) < 0) Yasqe.defaults.autocompleters.push(name);
2216
2320
  }
2217
2321
  }
2218
- (<any>Object).assign(CodeMirror.prototype, Yasqe.prototype);
2219
2322
 
2220
- export type TokenizerState = sparql11Mode.State;
2221
- export type Position = CodeMirror.Position;
2222
- export type Token = CodeMirror.Token;
2323
+ export type { TokenizerState, Position, Token } from "./editor/tokenizerRunner";
2324
+ export type { Hint, HintList, HintFn } from "./editor/autocompletion";
2325
+ export type { EditorOptions } from "./editor/facade";
2326
+ export type { ExtraKeys } from "./editor/keymap";
2223
2327
 
2224
- export interface HintList {
2225
- list: Hint[];
2226
- from: Position;
2227
- to: Position;
2228
- }
2229
- export interface Hint {
2230
- text: string;
2231
- displayText?: string;
2232
- className?: string;
2233
- render?: (el: HTMLElement, self: Hint, data: any) => void;
2234
- from?: Position;
2235
- to?: Position;
2236
- }
2237
-
2238
- export type HintFn = { async?: boolean } & (() => Promise<HintList> | HintList);
2328
+ /**
2329
+ * Autocompletion popup configuration.
2330
+ * Most CodeMirror 5 show-hint options are no longer applicable with CodeMirror 6; the remaining ones are
2331
+ * kept for backwards compatibility and are currently informational only.
2332
+ */
2239
2333
  export interface HintConfig {
2240
2334
  completeOnSingleClick?: boolean;
2241
2335
  container?: HTMLElement;
2242
2336
  closeCharacters?: RegExp;
2243
2337
  completeSingle?: boolean;
2244
- // A hinting function, as specified above. It is possible to set the async property on a hinting function to true, in which case it will be called with arguments (cm, callback, ?options), and the completion interface will only be popped up when the hinting function calls the callback, passing it the object holding the completions. The hinting function can also return a promise, and the completion interface will only be popped when the promise resolves. By default, hinting only works when there is no selection. You can give a hinting function a supportsSelection property with a truthy value to indicate that it supports selections.
2245
- hint: HintFn;
2246
-
2247
- // Whether the pop-up should be horizontally aligned with the start of the word (true, default), or with the cursor (false).
2248
2338
  alignWithWord?: boolean;
2249
- // When enabled (which is the default), the pop-up will close when the editor is unfocused.
2250
2339
  closeOnUnfocus?: boolean;
2251
- // Allows you to provide a custom key map of keys to be active when the pop-up is active. The handlers will be called with an extra argument, a handle to the completion menu, which has moveFocus(n), setFocus(n), pick(), and close() methods (see the source for details), that can be used to change the focused element, pick the current element or close the menu. Additionally menuSize() can give you access to the size of the current dropdown menu, length give you the number of available completions, and data give you full access to the completion returned by the hinting function.
2252
- customKeys?: any;
2253
-
2254
- // Like customKeys above, but the bindings will be added to the set of default bindings, instead of replacing them.
2255
- extraKeys?: {
2256
- [key: string]: (
2257
- yasqe: Yasqe,
2258
- event: {
2259
- close: () => void;
2260
- data: {
2261
- from: Position;
2262
- to: Position;
2263
- list: Hint[];
2264
- };
2265
- length: number;
2266
- menuSize: () => void;
2267
- moveFocus: (movement: number) => void;
2268
- pick: () => void;
2269
- setFocus: (index: number) => void;
2270
- },
2271
- ) => void;
2272
- };
2273
2340
  }
2274
2341
  export interface BasicAuthConfig {
2275
2342
  username: string;
@@ -2317,8 +2384,9 @@ export interface Snippet {
2317
2384
  code: string;
2318
2385
  group?: string;
2319
2386
  }
2320
- export interface Config extends Partial<CodeMirror.EditorConfiguration> {
2387
+ export interface Config extends Omit<EditorOptions, "extraKeys"> {
2321
2388
  mode: string;
2389
+ extraKeys: ExtraKeys<Yasqe>;
2322
2390
  collapsePrefixesOnLoad: boolean;
2323
2391
  syntaxErrorCheck: boolean;
2324
2392
  /**
@@ -2342,11 +2410,9 @@ export interface Config extends Partial<CodeMirror.EditorConfiguration> {
2342
2410
  showQueryButton: boolean;
2343
2411
  requestConfig: RequestConfig<Yasqe> | ((yasqe: Yasqe) => RequestConfig<Yasqe>);
2344
2412
  pluginButtons: (() => HTMLElement[] | HTMLElement) | undefined;
2345
- //Addon specific addon ts defs, or missing props from codemirror conf
2346
- highlightSelectionMatches: { showToken?: RegExp; annotateScrollbar?: boolean };
2413
+ highlightSelectionMatches: boolean | { showToken?: RegExp; annotateScrollbar?: boolean };
2347
2414
  tabMode: string;
2348
- foldGutter: any; //This should be of type boolean, or an object. However, setting it to any to avoid
2349
- //ts complaining about incorrectly extending, as the cm def only defined it has having a boolean type.
2415
+ foldGutter: boolean | object;
2350
2416
  matchBrackets: boolean;
2351
2417
  autocompleters: string[];
2352
2418
  hintConfig: Partial<HintConfig>;