@matdata/yasgui 5.11.0 → 5.13.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/build/ts/src/PersistentConfig.d.ts +4 -0
- package/build/ts/src/PersistentConfig.js +12 -0
- package/build/ts/src/PersistentConfig.js.map +1 -1
- package/build/ts/src/Tab.js +2 -1
- package/build/ts/src/Tab.js.map +1 -1
- package/build/ts/src/TabSettingsModal.js +114 -0
- package/build/ts/src/TabSettingsModal.js.map +1 -1
- package/build/ts/src/ThemeManager.d.ts +3 -0
- package/build/ts/src/ThemeManager.js +11 -1
- package/build/ts/src/ThemeManager.js.map +1 -1
- package/build/ts/src/index.d.ts +1 -0
- package/build/ts/src/index.js +2 -0
- package/build/ts/src/index.js.map +1 -1
- package/build/ts/src/queryManagement/QueryBrowser.js +27 -6
- package/build/ts/src/queryManagement/QueryBrowser.js.map +1 -1
- package/build/ts/src/queryManagement/SaveManagedQueryModal.js +3 -3
- package/build/ts/src/queryManagement/SaveManagedQueryModal.js.map +1 -1
- package/build/ts/src/queryManagement/backends/BitbucketProviderClient.js +2 -2
- package/build/ts/src/queryManagement/backends/BitbucketProviderClient.js.map +1 -1
- package/build/ts/src/queryManagement/backends/GiteaProviderClient.js +2 -2
- package/build/ts/src/queryManagement/backends/GiteaProviderClient.js.map +1 -1
- package/build/ts/src/queryManagement/backends/GithubProviderClient.js +2 -2
- package/build/ts/src/queryManagement/backends/GithubProviderClient.js.map +1 -1
- package/build/ts/src/queryManagement/backends/GitlabProviderClient.js +2 -2
- package/build/ts/src/queryManagement/backends/GitlabProviderClient.js.map +1 -1
- package/build/ts/src/queryManagement/backends/InMemoryWorkspaceBackend.js +4 -4
- package/build/ts/src/queryManagement/backends/InMemoryWorkspaceBackend.js.map +1 -1
- package/build/ts/src/queryManagement/normalizeQueryFilename.js +2 -2
- package/build/ts/src/queryManagement/normalizeQueryFilename.js.map +1 -1
- package/build/ts/src/version.d.ts +1 -1
- package/build/ts/src/version.js +1 -1
- package/build/yasgui.min.css +1 -1
- package/build/yasgui.min.css.map +3 -3
- package/build/yasgui.min.js +162 -162
- package/build/yasgui.min.js.map +3 -3
- package/package.json +1 -1
- package/src/PersistentConfig.ts +15 -0
- package/src/Tab.ts +3 -2
- package/src/TabSettingsModal.scss +12 -0
- package/src/TabSettingsModal.ts +144 -0
- package/src/ThemeManager.ts +18 -1
- package/src/github-dark-theme.scss +192 -0
- package/src/index.ts +4 -0
- package/src/queryManagement/QueryBrowser.ts +34 -7
- package/src/queryManagement/SaveManagedQueryModal.ts +3 -3
- package/src/queryManagement/backends/BitbucketProviderClient.ts +2 -2
- package/src/queryManagement/backends/GiteaProviderClient.ts +2 -2
- package/src/queryManagement/backends/GithubProviderClient.ts +2 -2
- package/src/queryManagement/backends/GitlabProviderClient.ts +2 -2
- package/src/queryManagement/backends/InMemoryWorkspaceBackend.ts +4 -4
- package/src/queryManagement/normalizeQueryFilename.ts +4 -2
- package/src/themes.scss +43 -43
- package/src/version.ts +1 -1
package/package.json
CHANGED
package/src/PersistentConfig.ts
CHANGED
|
@@ -19,6 +19,8 @@ export interface PersistedJson {
|
|
|
19
19
|
orientation?: "vertical" | "horizontal";
|
|
20
20
|
showSnippetsBar?: boolean;
|
|
21
21
|
disabledDevButtons?: string[]; // Endpoints of developer-configured buttons that are disabled by user
|
|
22
|
+
codeMirrorThemeLight?: string; // User-selected CodeMirror theme for light mode
|
|
23
|
+
codeMirrorThemeDark?: string; // User-selected CodeMirror theme for dark mode
|
|
22
24
|
}
|
|
23
25
|
function getDefaults(): PersistedJson {
|
|
24
26
|
return {
|
|
@@ -182,6 +184,19 @@ export default class PersistentConfig {
|
|
|
182
184
|
this.toStorage();
|
|
183
185
|
}
|
|
184
186
|
|
|
187
|
+
public getCodeMirrorTheme(mode: "light" | "dark"): string | undefined {
|
|
188
|
+
return mode === "dark" ? this.persistedJson.codeMirrorThemeDark : this.persistedJson.codeMirrorThemeLight;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
public setCodeMirrorTheme(mode: "light" | "dark", theme: string) {
|
|
192
|
+
if (mode === "dark") {
|
|
193
|
+
this.persistedJson.codeMirrorThemeDark = theme;
|
|
194
|
+
} else {
|
|
195
|
+
this.persistedJson.codeMirrorThemeLight = theme;
|
|
196
|
+
}
|
|
197
|
+
this.toStorage();
|
|
198
|
+
}
|
|
199
|
+
|
|
185
200
|
// New endpoint configuration methods
|
|
186
201
|
public getEndpointConfigs(): EndpointConfig[] {
|
|
187
202
|
return this.persistedJson.endpointConfigs || [];
|
package/src/Tab.ts
CHANGED
|
@@ -1216,9 +1216,10 @@ export class Tab extends EventEmitter {
|
|
|
1216
1216
|
}
|
|
1217
1217
|
|
|
1218
1218
|
private initYasqe() {
|
|
1219
|
-
// Set theme based on current
|
|
1219
|
+
// Set theme based on stored preference for current mode
|
|
1220
1220
|
const currentTheme = this.yasgui.getTheme();
|
|
1221
|
-
const
|
|
1221
|
+
const storedCmTheme = this.yasgui.persistentConfig.getCodeMirrorTheme(currentTheme);
|
|
1222
|
+
const cmTheme = storedCmTheme || (currentTheme === "dark" ? "github-dark" : "default");
|
|
1222
1223
|
|
|
1223
1224
|
const yasqeConf: Partial<YasqeConfig> = {
|
|
1224
1225
|
...this.yasgui.config.yasqe,
|
|
@@ -160,6 +160,18 @@
|
|
|
160
160
|
font-style: italic;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
.settingsLink {
|
|
164
|
+
display: inline-block;
|
|
165
|
+
margin-top: 5px;
|
|
166
|
+
font-size: 13px;
|
|
167
|
+
color: var(--yasgui-accent-color, #337ab7);
|
|
168
|
+
text-decoration: none;
|
|
169
|
+
|
|
170
|
+
&:hover {
|
|
171
|
+
text-decoration: underline;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
163
175
|
.settingsField {
|
|
164
176
|
margin-bottom: 10px;
|
|
165
177
|
}
|
package/src/TabSettingsModal.ts
CHANGED
|
@@ -358,6 +358,121 @@ export default class TabSettingsModal {
|
|
|
358
358
|
return;
|
|
359
359
|
}
|
|
360
360
|
|
|
361
|
+
// Available CodeMirror themes
|
|
362
|
+
const themes = [
|
|
363
|
+
{ value: "default", label: "Default" },
|
|
364
|
+
{ value: "github-dark", label: "GitHub Dark Default" },
|
|
365
|
+
{ value: "material-palenight", label: "Material Palenight" },
|
|
366
|
+
{ value: "monokai", label: "Monokai" },
|
|
367
|
+
{ value: "dracula", label: "Dracula" },
|
|
368
|
+
{ value: "nord", label: "Nord" },
|
|
369
|
+
{ value: "solarized dark", label: "Solarized Dark" },
|
|
370
|
+
{ value: "solarized light", label: "Solarized Light" },
|
|
371
|
+
{ value: "twilight", label: "Twilight" },
|
|
372
|
+
{ value: "material", label: "Material" },
|
|
373
|
+
{ value: "cobalt", label: "Cobalt" },
|
|
374
|
+
{ value: "darcula", label: "Darcula" },
|
|
375
|
+
{ value: "gruvbox-dark", label: "Gruvbox Dark" },
|
|
376
|
+
{ value: "oceanic-next", label: "Oceanic Next" },
|
|
377
|
+
{ value: "material-darker", label: "Material Darker" },
|
|
378
|
+
{ value: "blackboard", label: "Blackboard" },
|
|
379
|
+
{ value: "base16-dark", label: "Base16 Dark" },
|
|
380
|
+
{ value: "base16-light", label: "Base16 Light" },
|
|
381
|
+
{ value: "eclipse", label: "Eclipse" },
|
|
382
|
+
{ value: "elegant", label: "Elegant" },
|
|
383
|
+
{ value: "idea", label: "IntelliJ IDEA" },
|
|
384
|
+
{ value: "mbo", label: "MBO" },
|
|
385
|
+
{ value: "neat", label: "Neat" },
|
|
386
|
+
{ value: "neo", label: "Neo" },
|
|
387
|
+
{ value: "night", label: "Night" },
|
|
388
|
+
{ value: "paraiso-dark", label: "Paraiso Dark" },
|
|
389
|
+
{ value: "paraiso-light", label: "Paraiso Light" },
|
|
390
|
+
{ value: "pastel-on-dark", label: "Pastel on Dark" },
|
|
391
|
+
{ value: "rubyblue", label: "Ruby Blue" },
|
|
392
|
+
{ value: "the-matrix", label: "The Matrix" },
|
|
393
|
+
{ value: "tomorrow-night-bright", label: "Tomorrow Night Bright" },
|
|
394
|
+
{ value: "tomorrow-night-eighties", label: "Tomorrow Night 80s" },
|
|
395
|
+
{ value: "vibrant-ink", label: "Vibrant Ink" },
|
|
396
|
+
{ value: "xq-dark", label: "XQ Dark" },
|
|
397
|
+
{ value: "xq-light", label: "XQ Light" },
|
|
398
|
+
];
|
|
399
|
+
|
|
400
|
+
// Light Mode Theme Section
|
|
401
|
+
const themeLightSection = document.createElement("div");
|
|
402
|
+
addClass(themeLightSection, "settingsSection");
|
|
403
|
+
|
|
404
|
+
const themeLightLabel = document.createElement("label");
|
|
405
|
+
themeLightLabel.textContent = "Editor Theme (Light Mode)";
|
|
406
|
+
addClass(themeLightLabel, "settingsLabel");
|
|
407
|
+
|
|
408
|
+
const themeLightHelp = document.createElement("div");
|
|
409
|
+
themeLightHelp.textContent = "Syntax highlighting theme when using light mode.";
|
|
410
|
+
addClass(themeLightHelp, "settingsHelp");
|
|
411
|
+
|
|
412
|
+
const themeLightSelect = document.createElement("select");
|
|
413
|
+
themeLightSelect.id = "codeMirrorThemeLightSelect";
|
|
414
|
+
addClass(themeLightSelect, "settingsSelect");
|
|
415
|
+
|
|
416
|
+
themes.forEach((theme) => {
|
|
417
|
+
const option = document.createElement("option");
|
|
418
|
+
option.value = theme.value;
|
|
419
|
+
option.textContent = theme.label;
|
|
420
|
+
themeLightSelect.appendChild(option);
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
const storedLightTheme = this.tab.yasgui.persistentConfig.getCodeMirrorTheme("light");
|
|
424
|
+
themeLightSelect.value = storedLightTheme || "default";
|
|
425
|
+
|
|
426
|
+
themeLightSection.appendChild(themeLightLabel);
|
|
427
|
+
themeLightSection.appendChild(themeLightHelp);
|
|
428
|
+
themeLightSection.appendChild(themeLightSelect);
|
|
429
|
+
container.appendChild(themeLightSection);
|
|
430
|
+
|
|
431
|
+
// Dark Mode Theme Section
|
|
432
|
+
const themeDarkSection = document.createElement("div");
|
|
433
|
+
addClass(themeDarkSection, "settingsSection");
|
|
434
|
+
|
|
435
|
+
const themeDarkLabel = document.createElement("label");
|
|
436
|
+
themeDarkLabel.textContent = "Editor Theme (Dark Mode)";
|
|
437
|
+
addClass(themeDarkLabel, "settingsLabel");
|
|
438
|
+
|
|
439
|
+
const themeDarkHelp = document.createElement("div");
|
|
440
|
+
themeDarkHelp.textContent = "Syntax highlighting theme when using dark mode.";
|
|
441
|
+
addClass(themeDarkHelp, "settingsHelp");
|
|
442
|
+
|
|
443
|
+
const themeDarkSelect = document.createElement("select");
|
|
444
|
+
themeDarkSelect.id = "codeMirrorThemeDarkSelect";
|
|
445
|
+
addClass(themeDarkSelect, "settingsSelect");
|
|
446
|
+
|
|
447
|
+
themes.forEach((theme) => {
|
|
448
|
+
const option = document.createElement("option");
|
|
449
|
+
option.value = theme.value;
|
|
450
|
+
option.textContent = theme.label;
|
|
451
|
+
themeDarkSelect.appendChild(option);
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
const storedDarkTheme = this.tab.yasgui.persistentConfig.getCodeMirrorTheme("dark");
|
|
455
|
+
themeDarkSelect.value = storedDarkTheme || "github-dark";
|
|
456
|
+
|
|
457
|
+
themeDarkSection.appendChild(themeDarkLabel);
|
|
458
|
+
themeDarkSection.appendChild(themeDarkHelp);
|
|
459
|
+
themeDarkSection.appendChild(themeDarkSelect);
|
|
460
|
+
container.appendChild(themeDarkSection);
|
|
461
|
+
|
|
462
|
+
// Theme reference link
|
|
463
|
+
const themeReferenceSection = document.createElement("div");
|
|
464
|
+
addClass(themeReferenceSection, "settingsSection");
|
|
465
|
+
|
|
466
|
+
const themeReferenceLink = document.createElement("a");
|
|
467
|
+
themeReferenceLink.href = "https://codemirror.net/5/demo/theme.html";
|
|
468
|
+
themeReferenceLink.target = "_blank";
|
|
469
|
+
themeReferenceLink.rel = "noopener noreferrer";
|
|
470
|
+
themeReferenceLink.textContent = "Preview CodeMirror themes →";
|
|
471
|
+
addClass(themeReferenceLink, "settingsLink");
|
|
472
|
+
|
|
473
|
+
themeReferenceSection.appendChild(themeReferenceLink);
|
|
474
|
+
container.appendChild(themeReferenceSection);
|
|
475
|
+
|
|
361
476
|
// Formatter Type Section
|
|
362
477
|
const formatterSection = document.createElement("div");
|
|
363
478
|
addClass(formatterSection, "settingsSection");
|
|
@@ -1355,10 +1470,39 @@ export default class TabSettingsModal {
|
|
|
1355
1470
|
// Save editor settings
|
|
1356
1471
|
const yasqe = this.tab.getYasqe();
|
|
1357
1472
|
if (yasqe && yasqe.persistentConfig) {
|
|
1473
|
+
const codeMirrorThemeLightSelect = document.getElementById("codeMirrorThemeLightSelect") as HTMLSelectElement;
|
|
1474
|
+
const codeMirrorThemeDarkSelect = document.getElementById("codeMirrorThemeDarkSelect") as HTMLSelectElement;
|
|
1358
1475
|
const formatterSelect = document.getElementById("formatterTypeSelect") as HTMLSelectElement;
|
|
1359
1476
|
const autoformatCheckbox = document.getElementById("autoformatOnQuery") as HTMLInputElement;
|
|
1360
1477
|
const constructValidationCheckbox = document.getElementById("checkConstructVariables") as HTMLInputElement;
|
|
1361
1478
|
|
|
1479
|
+
// Save CodeMirror themes for both light and dark modes
|
|
1480
|
+
if (codeMirrorThemeLightSelect) {
|
|
1481
|
+
const selectedTheme = codeMirrorThemeLightSelect.value;
|
|
1482
|
+
this.tab.yasgui.persistentConfig.setCodeMirrorTheme("light", selectedTheme);
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
if (codeMirrorThemeDarkSelect) {
|
|
1486
|
+
const selectedTheme = codeMirrorThemeDarkSelect.value;
|
|
1487
|
+
this.tab.yasgui.persistentConfig.setCodeMirrorTheme("dark", selectedTheme);
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
// Apply the appropriate theme based on current mode
|
|
1491
|
+
const currentMode = this.tab.yasgui.getTheme();
|
|
1492
|
+
const themeToApply =
|
|
1493
|
+
currentMode === "dark"
|
|
1494
|
+
? codeMirrorThemeDarkSelect?.value || "github-dark"
|
|
1495
|
+
: codeMirrorThemeLightSelect?.value || "default";
|
|
1496
|
+
|
|
1497
|
+
// Apply theme to all CodeMirror instances
|
|
1498
|
+
const cmElements = document.querySelectorAll(".CodeMirror");
|
|
1499
|
+
cmElements.forEach((element) => {
|
|
1500
|
+
const cm = (element as any).CodeMirror;
|
|
1501
|
+
if (cm && cm.setOption) {
|
|
1502
|
+
cm.setOption("theme", themeToApply);
|
|
1503
|
+
}
|
|
1504
|
+
});
|
|
1505
|
+
|
|
1362
1506
|
if (formatterSelect) {
|
|
1363
1507
|
yasqe.persistentConfig.formatterType = formatterSelect.value as "sparql-formatter" | "legacy";
|
|
1364
1508
|
}
|
package/src/ThemeManager.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Storage as YStorage } from "@matdata/yasgui-utils";
|
|
2
|
+
import PersistentConfig from "./PersistentConfig";
|
|
2
3
|
|
|
3
4
|
export type Theme = "light" | "dark";
|
|
4
5
|
|
|
@@ -7,6 +8,7 @@ export class ThemeManager {
|
|
|
7
8
|
private storage: YStorage;
|
|
8
9
|
private currentTheme: Theme;
|
|
9
10
|
private rootElement: HTMLElement;
|
|
11
|
+
private persistentConfig?: PersistentConfig;
|
|
10
12
|
|
|
11
13
|
constructor(rootElement: HTMLElement) {
|
|
12
14
|
this.storage = new YStorage("yasgui");
|
|
@@ -15,6 +17,13 @@ export class ThemeManager {
|
|
|
15
17
|
this.applyTheme(this.currentTheme);
|
|
16
18
|
}
|
|
17
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Set PersistentConfig for accessing CodeMirror theme preference
|
|
22
|
+
*/
|
|
23
|
+
public setPersistentConfig(persistentConfig: PersistentConfig): void {
|
|
24
|
+
this.persistentConfig = persistentConfig;
|
|
25
|
+
}
|
|
26
|
+
|
|
18
27
|
/**
|
|
19
28
|
* Get the currently active theme
|
|
20
29
|
*/
|
|
@@ -61,7 +70,15 @@ export class ThemeManager {
|
|
|
61
70
|
* Update CodeMirror theme for all Yasqe editors
|
|
62
71
|
*/
|
|
63
72
|
private updateCodeMirrorTheme(theme: Theme): void {
|
|
64
|
-
|
|
73
|
+
// Get user's stored CodeMirror theme preference for the current mode, or use default
|
|
74
|
+
let cmTheme: string;
|
|
75
|
+
if (this.persistentConfig) {
|
|
76
|
+
const storedTheme = this.persistentConfig.getCodeMirrorTheme(theme);
|
|
77
|
+
cmTheme = storedTheme || (theme === "dark" ? "github-dark" : "default");
|
|
78
|
+
} else {
|
|
79
|
+
// Fallback if persistentConfig not yet available
|
|
80
|
+
cmTheme = theme === "dark" ? "github-dark" : "default";
|
|
81
|
+
}
|
|
65
82
|
|
|
66
83
|
// Find all CodeMirror instances within the root element
|
|
67
84
|
const cmElements = this.rootElement.querySelectorAll(".CodeMirror");
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// GitHub Dark Default CodeMirror Theme
|
|
2
|
+
// Based on GitHub's dark default color scheme
|
|
3
|
+
|
|
4
|
+
.cm-s-github-dark.CodeMirror {
|
|
5
|
+
background-color: #0d1117;
|
|
6
|
+
color: #c9d1d9;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Selection styles - using GitHub's subtle blue highlight
|
|
10
|
+
.cm-s-github-dark div.CodeMirror-selected {
|
|
11
|
+
background: rgba(56, 138, 253, 0.5) !important;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.cm-s-github-dark.CodeMirror ::selection {
|
|
15
|
+
background: rgba(56, 138, 253, 0.308) !important;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.cm-s-github-dark.CodeMirror ::-moz-selection {
|
|
19
|
+
background: rgba(56, 138, 253, 0.5) !important;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.cm-s-github-dark .CodeMirror-line::selection,
|
|
23
|
+
.cm-s-github-dark .CodeMirror-line > span::selection,
|
|
24
|
+
.cm-s-github-dark .CodeMirror-line > span > span::selection {
|
|
25
|
+
background: rgba(56, 138, 253, 0.5) !important;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.cm-s-github-dark .CodeMirror-line::-moz-selection,
|
|
29
|
+
.cm-s-github-dark .CodeMirror-line > span::-moz-selection,
|
|
30
|
+
.cm-s-github-dark .CodeMirror-line > span > span::-moz-selection {
|
|
31
|
+
background: rgba(56, 138, 253, 0.5) !important;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.cm-s-github-dark.CodeMirror-focused div.CodeMirror-selected {
|
|
35
|
+
background: rgba(56, 138, 253, 0.5) !important;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.cm-s-github-dark .CodeMirror-gutters {
|
|
39
|
+
background: #0d1117;
|
|
40
|
+
border-right: 1px solid #30363d;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.cm-s-github-dark .CodeMirror-guttermarker {
|
|
44
|
+
color: #c9d1d9;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.cm-s-github-dark .CodeMirror-guttermarker-subtle {
|
|
48
|
+
color: #6e7681;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.cm-s-github-dark .CodeMirror-linenumber {
|
|
52
|
+
color: #6e7681;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.cm-s-github-dark .CodeMirror-cursor {
|
|
56
|
+
border-left: 1px solid #c9d1d9;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// SPARQL syntax highlighting - GitHub Dark Default colors
|
|
60
|
+
.cm-s-github-dark span.cm-keyword {
|
|
61
|
+
color: #ff7b72; // Keywords (SELECT, WHERE, PREFIX, etc.)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.cm-s-github-dark span.cm-atom {
|
|
65
|
+
color: #f3f9ff; // Variables (?var, $var)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.cm-s-github-dark span.cm-string {
|
|
69
|
+
color: #a5d6ff; // Literals in quotes
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.cm-s-github-dark span.cm-string-2 {
|
|
73
|
+
color: #5784ff; // Prefix namespace (rdf:, foaf:)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.cm-s-github-dark span.cm-variable-3 {
|
|
77
|
+
color: #1b9b8e; // URIs in angle brackets
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.cm-s-github-dark span.cm-number {
|
|
81
|
+
color: #4faaf9; // Numbers
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.cm-s-github-dark span.cm-comment {
|
|
85
|
+
color: #696e74; // Comments
|
|
86
|
+
font-style: italic;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.cm-s-github-dark span.cm-meta {
|
|
90
|
+
color: #ffa657; // Metadata
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.cm-s-github-dark span.cm-operator {
|
|
94
|
+
color: #ff7b72; // Operators
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.cm-s-github-dark span.cm-qualifier {
|
|
98
|
+
color: #79c0ff; // Qualifiers
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.cm-s-github-dark span.cm-property {
|
|
102
|
+
color: #79c0ff; // Properties
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.cm-s-github-dark span.cm-variable {
|
|
106
|
+
color: #c9d1d9; // Default variables
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.cm-s-github-dark span.cm-variable-2 {
|
|
110
|
+
color: #79c0ff;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.cm-s-github-dark span.cm-def {
|
|
114
|
+
color: #d2a8ff; // Definitions
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.cm-s-github-dark span.cm-tag {
|
|
118
|
+
color: #7ee787; // Tags
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.cm-s-github-dark span.cm-attribute {
|
|
122
|
+
color: #79c0ff; // Attributes
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.cm-s-github-dark span.cm-builtin {
|
|
126
|
+
color: #ffa657; // Built-in functions
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.cm-s-github-dark span.cm-bracket {
|
|
130
|
+
color: #c9d1d9; // Brackets (fallback)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Rainbow bracket colors
|
|
134
|
+
.cm-s-github-dark span.cm-bracket-level-0 {
|
|
135
|
+
color: #ffd700; // Gold
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.cm-s-github-dark span.cm-bracket-level-1 {
|
|
139
|
+
color: #d2a8ff; // Purple
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.cm-s-github-dark span.cm-bracket-level-2 {
|
|
143
|
+
color: #d85896; // Blue
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.cm-s-github-dark span.cm-bracket-level-3 {
|
|
147
|
+
color: #229922; // Green
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.cm-s-github-dark span.cm-bracket-paren {
|
|
151
|
+
color: #c9d1d9; // Constant color for () and []
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.cm-s-github-dark span.cm-bracket-mismatch {
|
|
155
|
+
color: #ff7b72; // Red for mismatched brackets
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.cm-s-github-dark span.cm-error {
|
|
159
|
+
color: #f85149;
|
|
160
|
+
border-bottom: 2px dotted #f85149;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Active line
|
|
164
|
+
.cm-s-github-dark .CodeMirror-activeline-background {
|
|
165
|
+
background: rgba(110, 118, 129, 0.1);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Matching brackets
|
|
169
|
+
.cm-s-github-dark .CodeMirror-matchingbracket {
|
|
170
|
+
color: #7ee787 !important;
|
|
171
|
+
background-color: rgba(46, 160, 67, 0.15);
|
|
172
|
+
text-decoration: underline;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.cm-s-github-dark .CodeMirror-nonmatchingbracket {
|
|
176
|
+
color: #ff7b72 !important;
|
|
177
|
+
background-color: rgba(248, 81, 73, 0.15);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Search highlighting
|
|
181
|
+
.cm-s-github-dark .CodeMirror-searching {
|
|
182
|
+
background-color: rgba(255, 206, 0, 0.4);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Override match highlight to use subtle selection color
|
|
186
|
+
.cm-s-github-dark .cm-matchhighlight {
|
|
187
|
+
background-color: rgba(56, 138, 253, 0.5) !important;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.cm-s-github-dark .CodeMirror-focused .CodeMirror-selected {
|
|
191
|
+
background: rgba(56, 138, 253, 0.5) !important;
|
|
192
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -19,6 +19,7 @@ import { ThemeManager, Theme } from "./ThemeManager";
|
|
|
19
19
|
import QueryBrowser from "./queryManagement/QueryBrowser";
|
|
20
20
|
import "./index.scss";
|
|
21
21
|
import "./themes.scss";
|
|
22
|
+
import "./github-dark-theme.scss";
|
|
22
23
|
import "../../yasr/src/scss/global.scss";
|
|
23
24
|
import "codemirror/theme/material-palenight.css";
|
|
24
25
|
|
|
@@ -171,6 +172,9 @@ export class Yasgui extends EventEmitter {
|
|
|
171
172
|
this.themeManager.listenToSystemTheme();
|
|
172
173
|
this.persistentConfig = new PersistentConfig(this);
|
|
173
174
|
|
|
175
|
+
// Set persistentConfig reference in ThemeManager so it can access CodeMirror theme preference
|
|
176
|
+
this.themeManager.setPersistentConfig(this.persistentConfig);
|
|
177
|
+
|
|
174
178
|
// Load persisted showSnippetsBar if available
|
|
175
179
|
const persistedShowSnippetsBar = this.persistentConfig.getShowSnippetsBar();
|
|
176
180
|
if (persistedShowSnippetsBar !== undefined) {
|
|
@@ -3,7 +3,7 @@ import { addClass, removeClass } from "@matdata/yasgui-utils";
|
|
|
3
3
|
import type { WorkspaceConfig, FolderEntry } from "./types";
|
|
4
4
|
import { filterFolderEntriesByName } from "./browserFilter";
|
|
5
5
|
import { getWorkspaceBackend } from "./backends/getWorkspaceBackend";
|
|
6
|
-
import { asWorkspaceBackendError } from "./backends/errors";
|
|
6
|
+
import { asWorkspaceBackendError, isWorkspaceBackendError, WorkspaceBackendError } from "./backends/errors";
|
|
7
7
|
import { getEndpointToAutoSwitch } from "./openManagedQuery";
|
|
8
8
|
import { hashQueryText } from "./textHash";
|
|
9
9
|
import type { BackendType, VersionRef, ManagedTabMetadata } from "./types";
|
|
@@ -36,7 +36,7 @@ export default class QueryBrowser {
|
|
|
36
36
|
private expandedFolderIds = new Set<string>();
|
|
37
37
|
private folderEntriesById = new Map<string, FolderEntry[]>();
|
|
38
38
|
private folderLoadingById = new Set<string>();
|
|
39
|
-
private folderErrorById = new Map<string,
|
|
39
|
+
private folderErrorById = new Map<string, WorkspaceBackendError>();
|
|
40
40
|
|
|
41
41
|
private debouncedSearchHandle?: number;
|
|
42
42
|
|
|
@@ -315,7 +315,7 @@ export default class QueryBrowser {
|
|
|
315
315
|
this.folderEntriesById.set(key, entries);
|
|
316
316
|
} catch (e) {
|
|
317
317
|
const err = asWorkspaceBackendError(e);
|
|
318
|
-
this.folderErrorById.set(key, err
|
|
318
|
+
this.folderErrorById.set(key, err);
|
|
319
319
|
this.folderEntriesById.set(key, []);
|
|
320
320
|
} finally {
|
|
321
321
|
this.folderLoadingById.delete(key);
|
|
@@ -325,6 +325,22 @@ export default class QueryBrowser {
|
|
|
325
325
|
private formatStatusError(err: Error, workspaceType: WorkspaceConfig["type"]) {
|
|
326
326
|
const message = err.message || "Unknown error";
|
|
327
327
|
|
|
328
|
+
// Check for authentication/authorization errors
|
|
329
|
+
if (isWorkspaceBackendError(err)) {
|
|
330
|
+
if (err.code === "AUTH_FAILED") {
|
|
331
|
+
return `⚠️ Authentication failed. Please check your workspace configuration and credentials in Settings → Workspaces.`;
|
|
332
|
+
}
|
|
333
|
+
if (err.code === "FORBIDDEN") {
|
|
334
|
+
return `⚠️ Access forbidden. Please verify your ${workspaceType === "git" ? "token permissions" : "endpoint authentication"} in Settings → Workspaces.`;
|
|
335
|
+
}
|
|
336
|
+
if (err.code === "NETWORK_ERROR") {
|
|
337
|
+
return `⚠️ Unable to connect to workspace. Please check your workspace configuration and network connection.`;
|
|
338
|
+
}
|
|
339
|
+
if (err.code === "NOT_FOUND") {
|
|
340
|
+
return `⚠️ Workspace not found. Please verify your workspace configuration in Settings → Workspaces.`;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
328
344
|
if (message.includes("No GitProviderClient configured")) {
|
|
329
345
|
return "Git workspaces require a supported provider. Supported: GitHub, GitLab, Bitbucket Cloud (bitbucket.org), and Gitea. For self-hosted/enterprise instances, configure a git workspace 'provider' and/or 'apiBaseUrl'.";
|
|
330
346
|
}
|
|
@@ -333,7 +349,8 @@ export default class QueryBrowser {
|
|
|
333
349
|
return "This workspace backend is not supported yet.";
|
|
334
350
|
}
|
|
335
351
|
|
|
336
|
-
|
|
352
|
+
// Generic error with helpful suggestion
|
|
353
|
+
return `⚠️ Failed to load workspace: ${message}. Please check your workspace configuration and authentication in Settings → Workspaces.`;
|
|
337
354
|
}
|
|
338
355
|
|
|
339
356
|
private clearList() {
|
|
@@ -923,7 +940,7 @@ export default class QueryBrowser {
|
|
|
923
940
|
addClass(error, "yasgui-query-browser__tree-meta");
|
|
924
941
|
addClass(error, "yasgui-query-browser__tree-meta--error");
|
|
925
942
|
error.setAttribute("style", makeIndentStyle(depth + 1));
|
|
926
|
-
error.textContent = err;
|
|
943
|
+
error.textContent = this.formatStatusError(err, backend.type);
|
|
927
944
|
this.listEl.appendChild(error);
|
|
928
945
|
}
|
|
929
946
|
|
|
@@ -1041,6 +1058,15 @@ export default class QueryBrowser {
|
|
|
1041
1058
|
if (runId !== this.refreshRunId) return;
|
|
1042
1059
|
|
|
1043
1060
|
const rootKey = this.folderKey(undefined);
|
|
1061
|
+
|
|
1062
|
+
// Check if root folder failed to load
|
|
1063
|
+
const rootError = this.folderErrorById.get(rootKey);
|
|
1064
|
+
if (rootError) {
|
|
1065
|
+
this.setStatus(this.formatStatusError(rootError, workspace.type));
|
|
1066
|
+
this.clearList();
|
|
1067
|
+
return;
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1044
1070
|
const rootEntries = this.folderEntriesById.get(rootKey) || [];
|
|
1045
1071
|
|
|
1046
1072
|
const expandedIds = Array.from(this.expandedFolderIds).sort();
|
|
@@ -1053,8 +1079,9 @@ export default class QueryBrowser {
|
|
|
1053
1079
|
.sort()
|
|
1054
1080
|
.join("|");
|
|
1055
1081
|
const loading = this.folderLoadingById.has(key) ? "1" : "0";
|
|
1056
|
-
const err = this.folderErrorById.get(key)
|
|
1057
|
-
|
|
1082
|
+
const err = this.folderErrorById.get(key);
|
|
1083
|
+
const errStr = err ? `${err.code}:${err.message}` : "";
|
|
1084
|
+
return `${key}:${loading}:${errStr}:${entryPart}`;
|
|
1058
1085
|
})
|
|
1059
1086
|
.join(";");
|
|
1060
1087
|
|
|
@@ -185,7 +185,7 @@ export default class SaveManagedQueryModal {
|
|
|
185
185
|
this.nameEl.addEventListener("input", () => {
|
|
186
186
|
if (this.filenameTouched) return;
|
|
187
187
|
const suggested = this.suggestFilenameFromName(this.nameEl.value);
|
|
188
|
-
if (suggested) this.filenameEl.value = suggested.replace(/\.sparql$/i, "");
|
|
188
|
+
if (suggested) this.filenameEl.value = suggested.replace(/\.(rq|sparql)$/i, "");
|
|
189
189
|
});
|
|
190
190
|
|
|
191
191
|
this.filenameEl = document.createElement("input");
|
|
@@ -373,7 +373,7 @@ export default class SaveManagedQueryModal {
|
|
|
373
373
|
let resolvedFilename = filename;
|
|
374
374
|
|
|
375
375
|
if (isGit) {
|
|
376
|
-
resolvedFilename = resolvedFilename.replace(/\.sparql$/i, "");
|
|
376
|
+
resolvedFilename = resolvedFilename.replace(/\.(rq|sparql)$/i, "");
|
|
377
377
|
if (!resolvedFilename) {
|
|
378
378
|
window.alert("Please enter a filename");
|
|
379
379
|
return;
|
|
@@ -446,7 +446,7 @@ export default class SaveManagedQueryModal {
|
|
|
446
446
|
|
|
447
447
|
const defaultFilename =
|
|
448
448
|
defaults?.filename ?? (defaultName ? (this.suggestFilenameFromName(defaultName) ?? "") : "");
|
|
449
|
-
this.filenameEl.value = defaultFilename.replace(/\.sparql$/i, "");
|
|
449
|
+
this.filenameEl.value = defaultFilename.replace(/\.(rq|sparql)$/i, "");
|
|
450
450
|
this.messageEl.value = defaults?.message ?? "";
|
|
451
451
|
|
|
452
452
|
this.folderPickerOpen = false;
|
|
@@ -217,9 +217,9 @@ export class BitbucketProviderClient extends BaseGitProviderClient {
|
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
if (v.type === "commit_file") {
|
|
220
|
-
if (!/\.sparql$/i.test(name)) continue;
|
|
220
|
+
if (!/\.(rq|sparql)$/i.test(name)) continue;
|
|
221
221
|
const id = relPath ? this.joinPath(relPath, name) : name;
|
|
222
|
-
const label = name.replace(/\.sparql$/i, "");
|
|
222
|
+
const label = name.replace(/\.(rq|sparql)$/i, "");
|
|
223
223
|
entries.push({ kind: "query", id, label, parentId: relPath || undefined });
|
|
224
224
|
}
|
|
225
225
|
}
|
|
@@ -137,9 +137,9 @@ export class GiteaProviderClient extends BaseGitProviderClient {
|
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
if (item.type === "file") {
|
|
140
|
-
if (!/\.sparql$/i.test(item.name)) continue;
|
|
140
|
+
if (!/\.(rq|sparql)$/i.test(item.name)) continue;
|
|
141
141
|
const id = relPath ? this.joinPath(relPath, item.name) : item.name;
|
|
142
|
-
const label = item.name.replace(/\.sparql$/i, "");
|
|
142
|
+
const label = item.name.replace(/\.(rq|sparql)$/i, "");
|
|
143
143
|
entries.push({ kind: "query", id, label, parentId: relPath || undefined });
|
|
144
144
|
}
|
|
145
145
|
}
|
|
@@ -148,11 +148,11 @@ export class GithubProviderClient extends BaseGitProviderClient {
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
if (item.type === "file") {
|
|
151
|
-
if (!/\.sparql$/i.test(item.name)) continue;
|
|
151
|
+
if (!/\.(rq|sparql)$/i.test(item.name)) continue;
|
|
152
152
|
const id = config.rootPath
|
|
153
153
|
? item.path.slice(this.joinPath(config.rootPath).length).replace(/^\//, "")
|
|
154
154
|
: item.path;
|
|
155
|
-
const label = item.name.replace(/\.sparql$/i, "");
|
|
155
|
+
const label = item.name.replace(/\.(rq|sparql)$/i, "");
|
|
156
156
|
entries.push({ kind: "query", id, label, parentId: relPath || undefined });
|
|
157
157
|
}
|
|
158
158
|
}
|
|
@@ -160,9 +160,9 @@ export class GitlabProviderClient extends BaseGitProviderClient {
|
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
if (item.type === "blob") {
|
|
163
|
-
if (!/\.sparql$/i.test(item.name)) continue;
|
|
163
|
+
if (!/\.(rq|sparql)$/i.test(item.name)) continue;
|
|
164
164
|
const id = relPath ? this.joinPath(relPath, item.name) : item.name;
|
|
165
|
-
const label = item.name.replace(/\.sparql$/i, "");
|
|
165
|
+
const label = item.name.replace(/\.(rq|sparql)$/i, "");
|
|
166
166
|
entries.push({ kind: "query", id, label, parentId: relPath || undefined });
|
|
167
167
|
}
|
|
168
168
|
}
|