@matdata/yasqe 5.20.3 → 6.0.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.
- package/CHANGELOG.md +1 -1
- package/README.md +76 -59
- package/build/prefixes.json +2190 -2136
- package/build/ts/grammar/tokenizer.d.ts +9 -3
- package/build/ts/grammar/tokenizer.js +34 -6
- package/build/ts/grammar/tokenizer.js.map +1 -1
- package/build/ts/src/autocompleters/index.d.ts +4 -2
- package/build/ts/src/autocompleters/index.js +9 -33
- package/build/ts/src/autocompleters/index.js.map +1 -1
- package/build/ts/src/autocompleters/variables.js +17 -19
- package/build/ts/src/autocompleters/variables.js.map +1 -1
- package/build/ts/src/defaults.d.ts +17 -53
- package/build/ts/src/defaults.js +2 -5
- package/build/ts/src/defaults.js.map +1 -1
- package/build/ts/src/editor/autocompletion.d.ts +32 -0
- package/build/ts/src/editor/autocompletion.js +94 -0
- package/build/ts/src/editor/autocompletion.js.map +1 -0
- package/build/ts/src/editor/doc.d.ts +32 -0
- package/build/ts/src/editor/doc.js +121 -0
- package/build/ts/src/editor/doc.js.map +1 -0
- package/build/ts/src/editor/facade.d.ts +94 -0
- package/build/ts/src/editor/facade.js +392 -0
- package/build/ts/src/editor/facade.js.map +1 -0
- package/build/ts/src/editor/folding.d.ts +16 -0
- package/build/ts/src/editor/folding.js +190 -0
- package/build/ts/src/editor/folding.js.map +1 -0
- package/build/ts/src/editor/gutters.d.ts +8 -0
- package/build/ts/src/editor/gutters.js +113 -0
- package/build/ts/src/editor/gutters.js.map +1 -0
- package/build/ts/src/editor/keymap.d.ts +11 -0
- package/build/ts/src/editor/keymap.js +88 -0
- package/build/ts/src/editor/keymap.js.map +1 -0
- package/build/ts/src/editor/language.d.ts +11 -0
- package/build/ts/src/editor/language.js +19 -0
- package/build/ts/src/editor/language.js.map +1 -0
- package/build/ts/src/editor/tokenizerRunner.d.ts +37 -0
- package/build/ts/src/editor/tokenizerRunner.js +115 -0
- package/build/ts/src/editor/tokenizerRunner.js.map +1 -0
- package/build/ts/src/index.d.ts +49 -100
- package/build/ts/src/index.js +179 -100
- package/build/ts/src/index.js.map +1 -1
- package/build/ts/src/prefixes.json +2191 -2137
- package/build/ts/src/tooltip.js +9 -6
- package/build/ts/src/tooltip.js.map +1 -1
- package/build/yasqe.min.css +1 -1
- package/build/yasqe.min.css.map +3 -3
- package/build/yasqe.min.js +76 -91
- package/build/yasqe.min.js.map +4 -4
- package/grammar/tokenizer.ts +62 -8
- package/package.json +11 -6
- package/src/autocompleters/index.ts +24 -53
- package/src/autocompleters/show-hint.scss +17 -9
- package/src/autocompleters/variables.ts +20 -24
- package/src/defaults.ts +2 -6
- package/src/editor/autocompletion.ts +147 -0
- package/src/editor/doc.ts +151 -0
- package/src/editor/facade.ts +558 -0
- package/src/editor/folding.ts +225 -0
- package/src/editor/gutters.ts +152 -0
- package/src/editor/keymap.ts +133 -0
- package/src/editor/language.ts +47 -0
- package/src/editor/tokenizerRunner.ts +198 -0
- package/src/index.ts +193 -127
- package/src/prefixes.json +2190 -2136
- package/src/scss/buttons.scss +4 -2
- package/src/scss/codemirrorMods.scss +107 -11
- package/src/scss/yasqe.scss +4 -2
- package/src/tooltip.ts +16 -13
- package/build/ts/src/CodeMirror.d.ts +0 -30
- package/build/ts/src/CodeMirror.js +0 -20
- package/build/ts/src/CodeMirror.js.map +0 -1
- package/build/ts/src/prefixFold.d.ts +0 -8
- package/build/ts/src/prefixFold.js +0 -87
- package/build/ts/src/prefixFold.js.map +0 -1
- package/src/CodeMirror.ts +0 -54
- 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 "./
|
|
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
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
|
|
107
|
-
|
|
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(
|
|
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"
|
|
281
|
+
this.off("change", this.handleChange);
|
|
224
282
|
this.off("blur", this.handleBlur);
|
|
225
|
-
this.off("changes"
|
|
226
|
-
this.off("cursorActivity"
|
|
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
|
|
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
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
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 =
|
|
2169
|
+
const firstPrefixLine = findFirstPrefixLineInDoc(this.runner, this.view.state.doc);
|
|
2074
2170
|
if (firstPrefixLine === undefined) return; //nothing to collapse
|
|
2075
|
-
this.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
2221
|
-
export type
|
|
2222
|
-
export type
|
|
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
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
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
|
|
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
|
-
|
|
2346
|
-
highlightSelectionMatches: { showToken?: RegExp; annotateScrollbar?: boolean };
|
|
2413
|
+
highlightSelectionMatches: boolean | { showToken?: RegExp; annotateScrollbar?: boolean };
|
|
2347
2414
|
tabMode: string;
|
|
2348
|
-
foldGutter:
|
|
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>;
|