@matdata/yasqe 5.2.0 → 5.3.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/README.md +128 -144
- package/build/ts/grammar/tokenizer.d.ts +8 -0
- package/build/ts/grammar/tokenizer.js +21 -1
- package/build/ts/grammar/tokenizer.js.map +1 -1
- package/build/ts/src/defaults.d.ts +2 -0
- package/build/ts/src/defaults.js +4 -2
- package/build/ts/src/defaults.js.map +1 -1
- package/build/ts/src/imgs.d.ts +1 -0
- package/build/ts/src/imgs.js +1 -0
- package/build/ts/src/imgs.js.map +1 -1
- package/build/ts/src/index.d.ts +10 -0
- package/build/ts/src/index.js +104 -0
- package/build/ts/src/index.js.map +1 -1
- package/build/ts/src/prefixFold.js +2 -0
- package/build/ts/src/prefixFold.js.map +1 -1
- package/build/ts/src/prefixUtils.js.map +1 -1
- package/build/yasqe.min.css +1 -1
- package/build/yasqe.min.css.map +3 -3
- package/build/yasqe.min.js +84 -46
- package/build/yasqe.min.js.map +4 -4
- package/grammar/_tokenizer-table.d.ts +9 -0
- package/grammar/tokenizer.ts +27 -1
- package/package.json +3 -2
- package/src/defaults.ts +4 -2
- package/src/imgs.ts +2 -0
- package/src/index.ts +145 -1
- package/src/prefixFold.ts +1 -0
- package/src/prefixUtils.ts +5 -2
- package/src/scss/buttons.scss +20 -0
- package/src/scss/yasqe.scss +12 -0
- package/src/sparql-formatter.d.ts +10 -0
package/grammar/tokenizer.ts
CHANGED
|
@@ -36,6 +36,10 @@ export interface State {
|
|
|
36
36
|
lastPredicateOffset: number;
|
|
37
37
|
currentPnameNs: string | undefined;
|
|
38
38
|
possibleFullIri: boolean;
|
|
39
|
+
inConstructTemplate: boolean;
|
|
40
|
+
seenWhereClause: boolean;
|
|
41
|
+
constructVariables: { [varName: string]: string };
|
|
42
|
+
whereVariables: { [varName: string]: string };
|
|
39
43
|
}
|
|
40
44
|
export interface Token {
|
|
41
45
|
quotePos: "end" | "start" | "content" | undefined;
|
|
@@ -467,6 +471,13 @@ export default function (config: CodeMirror.EditorConfiguration): CodeMirror.Mod
|
|
|
467
471
|
case "storeProperty":
|
|
468
472
|
state.storeProperty = true;
|
|
469
473
|
break;
|
|
474
|
+
case "constructTemplate":
|
|
475
|
+
state.inConstructTemplate = true;
|
|
476
|
+
break;
|
|
477
|
+
case "whereClause":
|
|
478
|
+
state.inConstructTemplate = false;
|
|
479
|
+
state.seenWhereClause = true;
|
|
480
|
+
break;
|
|
470
481
|
}
|
|
471
482
|
}
|
|
472
483
|
|
|
@@ -517,7 +528,18 @@ export default function (config: CodeMirror.EditorConfiguration): CodeMirror.Mod
|
|
|
517
528
|
// Incremental LL1 parse
|
|
518
529
|
while (state.stack.length > 0 && tokenCat && state.OK && !finished) {
|
|
519
530
|
topSymbol = state.stack.pop();
|
|
520
|
-
if (topSymbol === "var" && tokenOb.string)
|
|
531
|
+
if (topSymbol === "var" && tokenOb.string) {
|
|
532
|
+
state.variables[tokenOb.string] = tokenOb.string;
|
|
533
|
+
// Track variables separately for CONSTRUCT template validation
|
|
534
|
+
if (state.queryType === "CONSTRUCT") {
|
|
535
|
+
if (state.inConstructTemplate) {
|
|
536
|
+
state.constructVariables[tokenOb.string] = tokenOb.string;
|
|
537
|
+
} else if (state.seenWhereClause) {
|
|
538
|
+
// Only track as WHERE variable if we've actually entered the WHERE clause
|
|
539
|
+
state.whereVariables[tokenOb.string] = tokenOb.string;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
521
543
|
if (!ll1_table[topSymbol]) {
|
|
522
544
|
// Top symbol is a terminal
|
|
523
545
|
if (topSymbol == tokenCat) {
|
|
@@ -721,6 +743,10 @@ export default function (config: CodeMirror.EditorConfiguration): CodeMirror.Mod
|
|
|
721
743
|
errorMsg: undefined,
|
|
722
744
|
inPrefixDecl: false,
|
|
723
745
|
possibleFullIri: false,
|
|
746
|
+
inConstructTemplate: false,
|
|
747
|
+
seenWhereClause: false,
|
|
748
|
+
constructVariables: {},
|
|
749
|
+
whereVariables: {},
|
|
724
750
|
};
|
|
725
751
|
},
|
|
726
752
|
indent: indent,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matdata/yasqe",
|
|
3
3
|
"description": "Yet Another SPARQL Query Editor",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.3.0",
|
|
5
5
|
"main": "build/yasqe.min.js",
|
|
6
6
|
"types": "build/ts/src/index.d.ts",
|
|
7
7
|
"license": "MIT",
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"@matdata/yasgui-utils": "^4.6.1",
|
|
28
28
|
"codemirror": "^5.51.0",
|
|
29
29
|
"lodash-es": "^4.17.15",
|
|
30
|
-
"query-string": "^6.10.1"
|
|
30
|
+
"query-string": "^6.10.1",
|
|
31
|
+
"sparql-formatter": "^1.0.2"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
34
|
"@types/codemirror": "0.0.100",
|
package/src/defaults.ts
CHANGED
|
@@ -27,7 +27,7 @@ SELECT * WHERE {
|
|
|
27
27
|
rangeFinder: new (<any>CodeMirror).fold.combine((<any>CodeMirror).fold.brace, (<any>CodeMirror).fold.prefix),
|
|
28
28
|
},
|
|
29
29
|
collapsePrefixesOnLoad: false,
|
|
30
|
-
gutters: ["gutterErrorBar", "CodeMirror-linenumbers", "CodeMirror-foldgutter"],
|
|
30
|
+
gutters: ["gutterErrorBar", "gutterConstructWarning", "CodeMirror-linenumbers", "CodeMirror-foldgutter"],
|
|
31
31
|
matchBrackets: true,
|
|
32
32
|
fixedGutter: true,
|
|
33
33
|
syntaxErrorCheck: true,
|
|
@@ -68,7 +68,7 @@ SELECT * WHERE {
|
|
|
68
68
|
},
|
|
69
69
|
"Shift-Ctrl-F": function (_yasqe: any) {
|
|
70
70
|
const yasqe: Yasqe = _yasqe;
|
|
71
|
-
yasqe.
|
|
71
|
+
yasqe.format();
|
|
72
72
|
},
|
|
73
73
|
"Ctrl-S": function (_yasqe: any) {
|
|
74
74
|
const yasqe: Yasqe = _yasqe;
|
|
@@ -130,6 +130,8 @@ SELECT * WHERE {
|
|
|
130
130
|
editorHeight: "300px",
|
|
131
131
|
queryingDisabled: undefined,
|
|
132
132
|
prefixCcApi: prefixCcApi,
|
|
133
|
+
showFormatButton: true,
|
|
134
|
+
checkConstructVariables: true,
|
|
133
135
|
};
|
|
134
136
|
const requestConfig: PlainRequestConfig = {
|
|
135
137
|
queryArgument: undefined, //undefined means: get query argument based on query mode
|
package/src/imgs.ts
CHANGED
|
@@ -12,3 +12,5 @@ export var fullscreen =
|
|
|
12
12
|
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/></svg>';
|
|
13
13
|
export var fullscreenExit =
|
|
14
14
|
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"/></svg>';
|
|
15
|
+
export var format =
|
|
16
|
+
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 3v18h18v-2H5V3H3zm14 4V5l-4 4 4 4V9h4V7h-4zM7 9v2h10V9H7zm0 4v2h10v-2H7zm0 4v2h10v-2H7z"/></svg>';
|
package/src/index.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { merge, escape } from "lodash-es";
|
|
|
16
16
|
import getDefaults from "./defaults";
|
|
17
17
|
import CodeMirror from "./CodeMirror";
|
|
18
18
|
import { YasqeAjaxConfig } from "./sparql";
|
|
19
|
+
import { spfmt } from "sparql-formatter";
|
|
19
20
|
|
|
20
21
|
export interface Yasqe {
|
|
21
22
|
on(eventName: "query", handler: (instance: Yasqe, req: Request, abortController?: AbortController) => void): void;
|
|
@@ -84,13 +85,30 @@ export class Yasqe extends CodeMirror {
|
|
|
84
85
|
if (storageId) {
|
|
85
86
|
const persConf = this.storage.get<any>(storageId);
|
|
86
87
|
if (persConf && typeof persConf === "string") {
|
|
87
|
-
this.persistentConfig = { query: persConf, editorHeight: this.config.editorHeight };
|
|
88
|
+
this.persistentConfig = { query: persConf, editorHeight: this.config.editorHeight };
|
|
88
89
|
} else {
|
|
89
90
|
this.persistentConfig = persConf;
|
|
90
91
|
}
|
|
91
92
|
if (!this.persistentConfig)
|
|
92
93
|
this.persistentConfig = { query: this.getValue(), editorHeight: this.config.editorHeight };
|
|
94
|
+
|
|
95
|
+
// Ensure autoformatOnQuery is true by default
|
|
96
|
+
if (this.persistentConfig && typeof this.persistentConfig.autoformatOnQuery === "undefined") {
|
|
97
|
+
this.persistentConfig.autoformatOnQuery = true;
|
|
98
|
+
}
|
|
99
|
+
|
|
93
100
|
if (this.persistentConfig && this.persistentConfig.query) this.setValue(this.persistentConfig.query);
|
|
101
|
+
} else {
|
|
102
|
+
// If no storage, ensure persistentConfig exists and autoformatOnQuery is true
|
|
103
|
+
if (!this.persistentConfig) {
|
|
104
|
+
this.persistentConfig = {
|
|
105
|
+
query: this.getValue(),
|
|
106
|
+
editorHeight: this.config.editorHeight,
|
|
107
|
+
autoformatOnQuery: true,
|
|
108
|
+
};
|
|
109
|
+
} else if (typeof this.persistentConfig.autoformatOnQuery === "undefined") {
|
|
110
|
+
this.persistentConfig.autoformatOnQuery = true;
|
|
111
|
+
}
|
|
94
112
|
}
|
|
95
113
|
this.config.autocompleters.forEach((c) => this.enableCompleter(c).then(() => {}, console.warn));
|
|
96
114
|
if (this.config.consumeShareLink) {
|
|
@@ -99,6 +117,7 @@ export class Yasqe extends CodeMirror {
|
|
|
99
117
|
window.addEventListener("hashchange", this.handleHashChange);
|
|
100
118
|
}
|
|
101
119
|
this.checkSyntax();
|
|
120
|
+
this.checkConstructVariables();
|
|
102
121
|
// Size codemirror to the
|
|
103
122
|
if (this.persistentConfig && this.persistentConfig.editorHeight) {
|
|
104
123
|
this.getWrapperElement().style.height = this.persistentConfig.editorHeight;
|
|
@@ -115,6 +134,7 @@ export class Yasqe extends CodeMirror {
|
|
|
115
134
|
};
|
|
116
135
|
private handleChange() {
|
|
117
136
|
this.checkSyntax();
|
|
137
|
+
this.checkConstructVariables();
|
|
118
138
|
this.updateQueryButton();
|
|
119
139
|
}
|
|
120
140
|
private handleBlur() {
|
|
@@ -123,6 +143,7 @@ export class Yasqe extends CodeMirror {
|
|
|
123
143
|
private handleChanges() {
|
|
124
144
|
// e.g. handle blur
|
|
125
145
|
this.checkSyntax();
|
|
146
|
+
this.checkConstructVariables();
|
|
126
147
|
this.updateQueryButton();
|
|
127
148
|
}
|
|
128
149
|
private handleCursorActivity() {
|
|
@@ -347,6 +368,23 @@ export class Yasqe extends CodeMirror {
|
|
|
347
368
|
this.updateQueryButton();
|
|
348
369
|
}
|
|
349
370
|
|
|
371
|
+
/**
|
|
372
|
+
* Draw format btn
|
|
373
|
+
*/
|
|
374
|
+
if (this.config.showFormatButton) {
|
|
375
|
+
const formatBtn = document.createElement("button");
|
|
376
|
+
addClass(formatBtn, "yasqe_formatButton");
|
|
377
|
+
const formatIcon = drawSvgStringAsElement(imgs.format);
|
|
378
|
+
addClass(formatIcon, "formatIcon");
|
|
379
|
+
formatBtn.appendChild(formatIcon);
|
|
380
|
+
formatBtn.onclick = () => {
|
|
381
|
+
this.format();
|
|
382
|
+
};
|
|
383
|
+
formatBtn.title = "Format query (Shift+Ctrl+F)";
|
|
384
|
+
formatBtn.setAttribute("aria-label", "Format query");
|
|
385
|
+
buttons.appendChild(formatBtn);
|
|
386
|
+
}
|
|
387
|
+
|
|
350
388
|
/**
|
|
351
389
|
* Draw fullscreen btn
|
|
352
390
|
*/
|
|
@@ -643,6 +681,32 @@ export class Yasqe extends CodeMirror {
|
|
|
643
681
|
}
|
|
644
682
|
});
|
|
645
683
|
}
|
|
684
|
+
|
|
685
|
+
public formatQuery() {
|
|
686
|
+
try {
|
|
687
|
+
const currentQuery = this.getValue();
|
|
688
|
+
const formatted = spfmt.format(currentQuery);
|
|
689
|
+
this.setValue(formatted);
|
|
690
|
+
// Collapse prefixes after formatting
|
|
691
|
+
this.collapsePrefixes(true);
|
|
692
|
+
} catch (error) {
|
|
693
|
+
console.warn(
|
|
694
|
+
"Failed to format SPARQL query using sparql-formatter. This may be due to syntax errors in the query. Falling back to legacy formatter.",
|
|
695
|
+
error,
|
|
696
|
+
);
|
|
697
|
+
// If formatting fails, fall back to the built-in autoformat
|
|
698
|
+
this.autoformat();
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
public format() {
|
|
703
|
+
const formatterType = this.persistentConfig?.formatterType || "sparql-formatter";
|
|
704
|
+
if (formatterType === "legacy") {
|
|
705
|
+
this.autoformat();
|
|
706
|
+
} else {
|
|
707
|
+
this.formatQuery();
|
|
708
|
+
}
|
|
709
|
+
}
|
|
646
710
|
//values in the form of {?var: 'value'}, or [{?var: 'value'}]
|
|
647
711
|
public getQueryWithValues(values: string | { [varName: string]: string } | Array<{ [varName: string]: string }>) {
|
|
648
712
|
if (!values) return this.getValue();
|
|
@@ -709,6 +773,7 @@ export class Yasqe extends CodeMirror {
|
|
|
709
773
|
public setCheckSyntaxErrors(isEnabled: boolean) {
|
|
710
774
|
this.config.syntaxErrorCheck = isEnabled;
|
|
711
775
|
this.checkSyntax();
|
|
776
|
+
this.checkConstructVariables();
|
|
712
777
|
}
|
|
713
778
|
public checkSyntax() {
|
|
714
779
|
this.queryValid = true;
|
|
@@ -765,6 +830,77 @@ export class Yasqe extends CodeMirror {
|
|
|
765
830
|
}
|
|
766
831
|
}
|
|
767
832
|
}
|
|
833
|
+
|
|
834
|
+
public setCheckConstructVariables(isEnabled: boolean) {
|
|
835
|
+
this.config.checkConstructVariables = isEnabled;
|
|
836
|
+
if (!isEnabled) {
|
|
837
|
+
// Clear any existing warnings when disabled
|
|
838
|
+
this.clearGutter("gutterConstructWarning");
|
|
839
|
+
} else {
|
|
840
|
+
this.checkConstructVariables();
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
public checkConstructVariables() {
|
|
845
|
+
// Clear any existing warnings first
|
|
846
|
+
this.clearGutter("gutterConstructWarning");
|
|
847
|
+
|
|
848
|
+
// Only check if enabled, query is valid, and it's a CONSTRUCT query
|
|
849
|
+
if (!this.config.checkConstructVariables || !this.queryValid || this.getQueryType() !== "CONSTRUCT") {
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// Get the final state after parsing the entire query
|
|
854
|
+
const lastLine = this.getDoc().lastLine();
|
|
855
|
+
const token: Token = this.getTokenAt({ line: lastLine, ch: this.getDoc().getLine(lastLine).length }, true);
|
|
856
|
+
|
|
857
|
+
const state = token.state as TokenizerState;
|
|
858
|
+
|
|
859
|
+
// Check for undefined variables in CONSTRUCT template
|
|
860
|
+
const undefinedVars: string[] = [];
|
|
861
|
+
for (const varName in state.constructVariables) {
|
|
862
|
+
if (!state.whereVariables[varName]) {
|
|
863
|
+
undefinedVars.push(varName);
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
if (undefinedVars.length === 0) {
|
|
868
|
+
return;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
// Find lines where undefined variables are used in CONSTRUCT template
|
|
872
|
+
// Note: This iterates through all lines but filters by inConstructTemplate flag
|
|
873
|
+
// For large queries, this could be optimized by tracking line ranges during tokenization
|
|
874
|
+
for (let l = 0; l < this.getDoc().lineCount(); ++l) {
|
|
875
|
+
const lineToken: Token = this.getTokenAt({ line: l, ch: this.getDoc().getLine(l).length }, true);
|
|
876
|
+
const lineState = lineToken.state as TokenizerState;
|
|
877
|
+
|
|
878
|
+
// Only mark variables in the CONSTRUCT template
|
|
879
|
+
if (lineState.queryType === "CONSTRUCT" && lineState.inConstructTemplate) {
|
|
880
|
+
const line = this.getDoc().getLine(l);
|
|
881
|
+
// Check if this line contains any undefined variable (use word boundary to avoid partial matches)
|
|
882
|
+
for (const undefinedVar of undefinedVars) {
|
|
883
|
+
// Escape special regex characters in variable name
|
|
884
|
+
// Use negative lookbehind/lookahead to ensure we match the full variable name
|
|
885
|
+
// Variables can be followed by whitespace, punctuation, or end of line
|
|
886
|
+
const escapedVar = undefinedVar.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
887
|
+
const varRegex = new RegExp(`${escapedVar}(?![a-zA-Z0-9_])`);
|
|
888
|
+
if (varRegex.test(line)) {
|
|
889
|
+
const warningEl = drawSvgStringAsElement(imgs.warning);
|
|
890
|
+
warningEl.className = "constructVariableWarning";
|
|
891
|
+
tooltip(
|
|
892
|
+
this,
|
|
893
|
+
warningEl,
|
|
894
|
+
escape(`Variable ${undefinedVar} is used in CONSTRUCT but not defined in WHERE clause`),
|
|
895
|
+
);
|
|
896
|
+
this.setGutterMarker(l, "gutterConstructWarning", warningEl);
|
|
897
|
+
break; // Only one marker per line
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
|
|
768
904
|
/**
|
|
769
905
|
* Token management
|
|
770
906
|
*/
|
|
@@ -875,6 +1011,10 @@ export class Yasqe extends CodeMirror {
|
|
|
875
1011
|
*/
|
|
876
1012
|
public query(config?: Sparql.YasqeAjaxConfig) {
|
|
877
1013
|
if (this.config.queryingDisabled) return Promise.reject("Querying is disabled.");
|
|
1014
|
+
// Auto-format query before execution if enabled in persistent config
|
|
1015
|
+
if (this.persistentConfig?.autoformatOnQuery) {
|
|
1016
|
+
this.format();
|
|
1017
|
+
}
|
|
878
1018
|
// Abort previous request
|
|
879
1019
|
this.abortQuery();
|
|
880
1020
|
return Sparql.executeQuery(this, config);
|
|
@@ -1081,10 +1221,14 @@ export interface Config extends Partial<CodeMirror.EditorConfiguration> {
|
|
|
1081
1221
|
editorHeight: string;
|
|
1082
1222
|
queryingDisabled: string | undefined; // The string will be the message displayed when hovered
|
|
1083
1223
|
prefixCcApi: string; // the suggested default prefixes URL API getter
|
|
1224
|
+
showFormatButton: boolean; // Show a button to format the query
|
|
1225
|
+
checkConstructVariables: boolean; // Check for undefined variables in CONSTRUCT queries
|
|
1084
1226
|
}
|
|
1085
1227
|
export interface PersistentConfig {
|
|
1086
1228
|
query: string;
|
|
1087
1229
|
editorHeight: string;
|
|
1230
|
+
formatterType?: "sparql-formatter" | "legacy"; // Which formatter to use
|
|
1231
|
+
autoformatOnQuery?: boolean; // Auto-format query on execution
|
|
1088
1232
|
}
|
|
1089
1233
|
// export var _Yasqe = _Yasqe;
|
|
1090
1234
|
|
package/src/prefixFold.ts
CHANGED
|
@@ -15,6 +15,7 @@ export function findFirstPrefixLine(yasqe: Yasqe) {
|
|
|
15
15
|
|
|
16
16
|
export function findFirstPrefix(yasqe: Yasqe, line: number, startFromCharIndex = 0, lineText?: string) {
|
|
17
17
|
if (!lineText) lineText = yasqe.getDoc().getLine(line);
|
|
18
|
+
if (!lineText) return undefined;
|
|
18
19
|
lineText = lineText.toUpperCase();
|
|
19
20
|
const charIndex = lineText.indexOf(PREFIX_KEYWORD, startFromCharIndex);
|
|
20
21
|
if (charIndex >= 0) {
|
package/src/prefixUtils.ts
CHANGED
|
@@ -30,7 +30,10 @@ export function removePrefixes(yasqe: Yasqe, prefixes: Prefixes) {
|
|
|
30
30
|
yasqe.setValue(
|
|
31
31
|
yasqe
|
|
32
32
|
.getValue()
|
|
33
|
-
.replace(
|
|
33
|
+
.replace(
|
|
34
|
+
new RegExp("PREFIX\\s*" + pref + ":\\s*" + escapeRegex("<" + prefixes[pref] + ">") + "\\s*", "ig"),
|
|
35
|
+
"",
|
|
36
|
+
),
|
|
34
37
|
);
|
|
35
38
|
}
|
|
36
39
|
yasqe.collapsePrefixes(false);
|
|
@@ -48,7 +51,7 @@ export function getPrefixesFromQuery(yasqe: Yasqe): Token["state"]["prefixes"] {
|
|
|
48
51
|
//as https://github.com/TriplyDB/YASGUI/issues/84)
|
|
49
52
|
return yasqe.getTokenAt(
|
|
50
53
|
{ line: yasqe.getDoc().lastLine(), ch: yasqe.getDoc().getLine(yasqe.getDoc().lastLine()).length },
|
|
51
|
-
true
|
|
54
|
+
true,
|
|
52
55
|
).state.prefixes;
|
|
53
56
|
}
|
|
54
57
|
|
package/src/scss/buttons.scss
CHANGED
|
@@ -212,6 +212,26 @@
|
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
214
|
|
|
215
|
+
.yasqe_formatButton {
|
|
216
|
+
display: inline-block;
|
|
217
|
+
border: none;
|
|
218
|
+
background: none;
|
|
219
|
+
cursor: pointer;
|
|
220
|
+
padding: 0;
|
|
221
|
+
margin-left: 5px;
|
|
222
|
+
|
|
223
|
+
svg {
|
|
224
|
+
height: 25px;
|
|
225
|
+
width: 25px;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
&:hover {
|
|
229
|
+
svg {
|
|
230
|
+
fill: #337ab7;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
215
235
|
.yasqe_fullscreenButton {
|
|
216
236
|
display: inline-block;
|
|
217
237
|
border: none;
|
package/src/scss/yasqe.scss
CHANGED
|
@@ -49,6 +49,18 @@
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
.constructVariableWarning {
|
|
53
|
+
width: 13px;
|
|
54
|
+
height: 13px;
|
|
55
|
+
margin-top: 2px;
|
|
56
|
+
margin-left: 2px;
|
|
57
|
+
svg {
|
|
58
|
+
g {
|
|
59
|
+
fill: orange;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
52
64
|
.yasqe_tooltip {
|
|
53
65
|
background: #333;
|
|
54
66
|
background: rgba(0, 0, 0, 0.8);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
declare module "sparql-formatter" {
|
|
2
|
+
export interface SpfmtFormatter {
|
|
3
|
+
format: (sparql: string, formattingMode?: string, indentDepth?: number) => string;
|
|
4
|
+
parseSparql: (sparql: string) => unknown;
|
|
5
|
+
parseSparqlAsCompact: (sparql: string) => unknown;
|
|
6
|
+
formatAst: (ast: unknown, indentDepth?: number) => string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const spfmt: SpfmtFormatter;
|
|
10
|
+
}
|