@matdata/yasqe 5.15.0 → 5.16.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/__tests__/share-test.js +30 -1
- package/build/ts/src/__tests__/share-test.js.map +1 -1
- package/build/ts/src/index.d.ts +5 -1
- package/build/ts/src/index.js +58 -27
- package/build/ts/src/index.js.map +1 -1
- package/build/ts/src/sparql.js +32 -5
- package/build/ts/src/sparql.js.map +1 -1
- package/build/yasqe.min.css +1 -1
- package/build/yasqe.min.css.map +3 -3
- package/build/yasqe.min.js +73 -73
- package/build/yasqe.min.js.map +3 -3
- package/package.json +1 -1
- package/src/__tests__/share-test.ts +32 -1
- package/src/index.ts +68 -30
- package/src/scss/buttons.scss +23 -15
- package/src/sparql.ts +43 -5
package/package.json
CHANGED
|
@@ -105,7 +105,7 @@ describe("Share Functionality", () => {
|
|
|
105
105
|
" }",
|
|
106
106
|
' ContentType = "application/x-www-form-urlencoded"',
|
|
107
107
|
' Body = "query=SELECT"',
|
|
108
|
-
' OutFile = "
|
|
108
|
+
' OutFile = "sparql-generated.json"',
|
|
109
109
|
"}",
|
|
110
110
|
"",
|
|
111
111
|
"Invoke-WebRequest @params",
|
|
@@ -117,6 +117,37 @@ describe("Share Functionality", () => {
|
|
|
117
117
|
expect(psString).to.include("Headers");
|
|
118
118
|
expect(psString).to.include("OutFile");
|
|
119
119
|
expect(psString).to.include("Accept");
|
|
120
|
+
expect(psString).to.include("sparql-generated");
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("should format PowerShell commands with here-string for query", () => {
|
|
124
|
+
const query = "SELECT * WHERE { ?s ?p ?o }";
|
|
125
|
+
const lines = [
|
|
126
|
+
'$query = @"',
|
|
127
|
+
query,
|
|
128
|
+
'"@',
|
|
129
|
+
"",
|
|
130
|
+
"$params = @{",
|
|
131
|
+
' Uri = "https://example.com/sparql"',
|
|
132
|
+
' Method = "Post"',
|
|
133
|
+
" Headers = @{",
|
|
134
|
+
' "Accept" = "application/sparql-results+json"',
|
|
135
|
+
" }",
|
|
136
|
+
' ContentType = "application/x-www-form-urlencoded"',
|
|
137
|
+
' Body = "query=$([System.Net.WebUtility]::UrlEncode($query))"',
|
|
138
|
+
' OutFile = "sparql-generated.json"',
|
|
139
|
+
"}",
|
|
140
|
+
"",
|
|
141
|
+
"Invoke-WebRequest @params",
|
|
142
|
+
];
|
|
143
|
+
const psString = lines.join("\n");
|
|
144
|
+
|
|
145
|
+
expect(psString).to.include('$query = @"');
|
|
146
|
+
expect(psString).to.include('"@');
|
|
147
|
+
expect(psString).to.include(query);
|
|
148
|
+
expect(psString).to.include('Body = "query=$([System.Net.WebUtility]::UrlEncode($query))"');
|
|
149
|
+
expect(psString).to.not.include('Body = "query=`$query"'); // Should NOT escape the variable
|
|
150
|
+
expect(psString).to.include("sparql-generated");
|
|
120
151
|
});
|
|
121
152
|
|
|
122
153
|
it("should format wget commands with proper line breaks", () => {
|
package/src/index.ts
CHANGED
|
@@ -46,6 +46,10 @@ export interface Yasqe {
|
|
|
46
46
|
off(eventName: "autocompletionClose", handler: (instance: Yasqe) => void): void;
|
|
47
47
|
on(eventName: "resize", handler: (instance: Yasqe, newSize: string) => void): void;
|
|
48
48
|
off(eventName: "resize", handler: (instance: Yasqe, newSize: string) => void): void;
|
|
49
|
+
on(eventName: "saveManagedQuery", handler: () => void): void;
|
|
50
|
+
off(eventName: "saveManagedQuery", handler: () => void): void;
|
|
51
|
+
on(eventName: "downloadRqFile", handler: () => void): void;
|
|
52
|
+
off(eventName: "downloadRqFile", handler: () => void): void;
|
|
49
53
|
on(eventName: string, handler: () => void): void;
|
|
50
54
|
}
|
|
51
55
|
|
|
@@ -59,7 +63,7 @@ export class Yasqe extends CodeMirror {
|
|
|
59
63
|
private abortController: AbortController | undefined;
|
|
60
64
|
private queryStatus: "valid" | "error" | undefined;
|
|
61
65
|
private queryBtn: HTMLButtonElement | undefined;
|
|
62
|
-
private
|
|
66
|
+
private saveBtnWrapper: HTMLDivElement | undefined;
|
|
63
67
|
private fullscreenBtn: HTMLButtonElement | undefined;
|
|
64
68
|
private hamburgerBtn: HTMLButtonElement | undefined;
|
|
65
69
|
private hamburgerMenu: HTMLDivElement | undefined;
|
|
@@ -570,24 +574,42 @@ export class Yasqe extends CodeMirror {
|
|
|
570
574
|
}
|
|
571
575
|
|
|
572
576
|
/**
|
|
573
|
-
* Draw save
|
|
577
|
+
* Draw save buttons (THIRD)
|
|
574
578
|
*/
|
|
575
|
-
const
|
|
576
|
-
addClass(
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
579
|
+
const saveBtnWrapper = document.createElement("div");
|
|
580
|
+
addClass(saveBtnWrapper, "yasqe_saveWrapper");
|
|
581
|
+
saveBtnWrapper.style.display = "none"; // Hidden by default, shown when workspace is configured
|
|
582
|
+
this.saveBtnWrapper = saveBtnWrapper;
|
|
583
|
+
|
|
584
|
+
const saveManagedBtn = document.createElement("button");
|
|
585
|
+
addClass(saveManagedBtn, "yasqe_saveManagedButton");
|
|
586
|
+
const saveManagedIcon = document.createElement("i");
|
|
587
|
+
addClass(saveManagedIcon, "fas");
|
|
588
|
+
addClass(saveManagedIcon, "fa-database");
|
|
589
|
+
saveManagedIcon.setAttribute("aria-hidden", "true");
|
|
590
|
+
saveManagedBtn.appendChild(saveManagedIcon);
|
|
591
|
+
saveManagedBtn.title = "Save as managed query";
|
|
592
|
+
saveManagedBtn.setAttribute("aria-label", "Save as managed query");
|
|
593
|
+
saveManagedBtn.onclick = () => {
|
|
584
594
|
this.emit("saveManagedQuery");
|
|
585
595
|
};
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
596
|
+
saveBtnWrapper.appendChild(saveManagedBtn);
|
|
597
|
+
|
|
598
|
+
const saveRqBtn = document.createElement("button");
|
|
599
|
+
addClass(saveRqBtn, "yasqe_saveRqButton");
|
|
600
|
+
const saveRqIcon = document.createElement("i");
|
|
601
|
+
addClass(saveRqIcon, "fas");
|
|
602
|
+
addClass(saveRqIcon, "fa-file-download");
|
|
603
|
+
saveRqIcon.setAttribute("aria-hidden", "true");
|
|
604
|
+
saveRqBtn.appendChild(saveRqIcon);
|
|
605
|
+
saveRqBtn.title = "Save as .rq file";
|
|
606
|
+
saveRqBtn.setAttribute("aria-label", "Save as .rq file");
|
|
607
|
+
saveRqBtn.onclick = () => {
|
|
608
|
+
this.emit("downloadRqFile");
|
|
609
|
+
};
|
|
610
|
+
saveBtnWrapper.appendChild(saveRqBtn);
|
|
611
|
+
|
|
612
|
+
buttons.appendChild(saveBtnWrapper);
|
|
591
613
|
|
|
592
614
|
/**
|
|
593
615
|
* Draw format btn (FOURTH)
|
|
@@ -671,21 +693,37 @@ export class Yasqe extends CodeMirror {
|
|
|
671
693
|
this.hamburgerMenu.appendChild(shareItem);
|
|
672
694
|
}
|
|
673
695
|
|
|
674
|
-
const
|
|
675
|
-
|
|
676
|
-
const
|
|
677
|
-
addClass(
|
|
678
|
-
addClass(
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
const
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
696
|
+
const saveManagedItem = document.createElement("button");
|
|
697
|
+
saveManagedItem.className = "yasqe_hamburgerMenuItem";
|
|
698
|
+
const saveManagedIconMenu = document.createElement("i");
|
|
699
|
+
addClass(saveManagedIconMenu, "fas");
|
|
700
|
+
addClass(saveManagedIconMenu, "fa-database");
|
|
701
|
+
saveManagedIconMenu.setAttribute("aria-hidden", "true");
|
|
702
|
+
saveManagedItem.appendChild(saveManagedIconMenu);
|
|
703
|
+
const saveManagedLabel = document.createElement("span");
|
|
704
|
+
saveManagedLabel.textContent = "Save as managed query";
|
|
705
|
+
saveManagedItem.appendChild(saveManagedLabel);
|
|
706
|
+
saveManagedItem.onclick = () => {
|
|
685
707
|
this.closeHamburgerMenu();
|
|
686
708
|
this.emit("saveManagedQuery");
|
|
687
709
|
};
|
|
688
|
-
this.hamburgerMenu.appendChild(
|
|
710
|
+
this.hamburgerMenu.appendChild(saveManagedItem);
|
|
711
|
+
|
|
712
|
+
const saveRqItem = document.createElement("button");
|
|
713
|
+
saveRqItem.className = "yasqe_hamburgerMenuItem";
|
|
714
|
+
const saveRqIconMenu = document.createElement("i");
|
|
715
|
+
addClass(saveRqIconMenu, "fas");
|
|
716
|
+
addClass(saveRqIconMenu, "fa-file-download");
|
|
717
|
+
saveRqIconMenu.setAttribute("aria-hidden", "true");
|
|
718
|
+
saveRqItem.appendChild(saveRqIconMenu);
|
|
719
|
+
const saveRqLabel = document.createElement("span");
|
|
720
|
+
saveRqLabel.textContent = "Save as .rq file";
|
|
721
|
+
saveRqItem.appendChild(saveRqLabel);
|
|
722
|
+
saveRqItem.onclick = () => {
|
|
723
|
+
this.closeHamburgerMenu();
|
|
724
|
+
this.emit("downloadRqFile");
|
|
725
|
+
};
|
|
726
|
+
this.hamburgerMenu.appendChild(saveRqItem);
|
|
689
727
|
|
|
690
728
|
if (this.config.showFormatButton) {
|
|
691
729
|
const formatItem = document.createElement("button");
|
|
@@ -1553,8 +1591,8 @@ export class Yasqe extends CodeMirror {
|
|
|
1553
1591
|
}
|
|
1554
1592
|
|
|
1555
1593
|
public setSaveButtonVisible(visible: boolean) {
|
|
1556
|
-
if (this.
|
|
1557
|
-
this.
|
|
1594
|
+
if (this.saveBtnWrapper) {
|
|
1595
|
+
this.saveBtnWrapper.style.display = visible ? "inline-flex" : "none";
|
|
1558
1596
|
}
|
|
1559
1597
|
}
|
|
1560
1598
|
|
package/src/scss/buttons.scss
CHANGED
|
@@ -293,25 +293,33 @@
|
|
|
293
293
|
}
|
|
294
294
|
}
|
|
295
295
|
|
|
296
|
-
.
|
|
296
|
+
.yasqe_saveWrapper {
|
|
297
|
+
position: relative;
|
|
297
298
|
display: inline-flex;
|
|
298
299
|
align-items: center;
|
|
299
|
-
|
|
300
|
-
border: none;
|
|
301
|
-
background: none;
|
|
302
|
-
cursor: pointer;
|
|
303
|
-
padding: 6px;
|
|
300
|
+
vertical-align: middle;
|
|
304
301
|
margin-left: 8px;
|
|
305
|
-
height: 36px;
|
|
306
|
-
width: 36px;
|
|
307
|
-
color: var(--yasgui-text-secondary, #505050);
|
|
308
302
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
303
|
+
.yasqe_saveManagedButton,
|
|
304
|
+
.yasqe_saveRqButton {
|
|
305
|
+
display: inline-flex;
|
|
306
|
+
align-items: center;
|
|
307
|
+
justify-content: center;
|
|
308
|
+
border: none;
|
|
309
|
+
background: none;
|
|
310
|
+
cursor: pointer;
|
|
311
|
+
padding: 6px;
|
|
312
|
+
height: 36px;
|
|
313
|
+
width: 36px;
|
|
314
|
+
color: var(--yasgui-text-secondary, #505050);
|
|
312
315
|
|
|
313
|
-
|
|
314
|
-
|
|
316
|
+
i {
|
|
317
|
+
font-size: 20px;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
&:hover {
|
|
321
|
+
color: #337ab7;
|
|
322
|
+
}
|
|
315
323
|
}
|
|
316
324
|
}
|
|
317
325
|
|
|
@@ -441,7 +449,7 @@
|
|
|
441
449
|
@media (max-width: 768px) {
|
|
442
450
|
.yasqe_buttons {
|
|
443
451
|
.yasqe_share,
|
|
444
|
-
.
|
|
452
|
+
.yasqe_saveWrapper,
|
|
445
453
|
.yasqe_formatButton,
|
|
446
454
|
.yasqe_fullscreenButton {
|
|
447
455
|
display: none !important;
|
package/src/sparql.ts
CHANGED
|
@@ -520,10 +520,48 @@ export function getAsPowerShellString(yasqe: Yasqe, _config?: Config["requestCon
|
|
|
520
520
|
lines.push(headersLines.join("\n"));
|
|
521
521
|
lines.push(" }");
|
|
522
522
|
}
|
|
523
|
-
lines.push(` OutFile = "
|
|
523
|
+
lines.push(` OutFile = "sparql-generated.${fileExtension}"`);
|
|
524
524
|
lines.push("}");
|
|
525
525
|
} else if (ajaxConfig.reqMethod === "POST") {
|
|
526
|
-
|
|
526
|
+
// Extract the query/update parameter and other parameters separately
|
|
527
|
+
// Determine the query parameter name first (query takes precedence over update)
|
|
528
|
+
const queryParamName = ajaxConfig.args.query !== undefined ? "query" : "update";
|
|
529
|
+
const queryParam = ajaxConfig.args[queryParamName];
|
|
530
|
+
|
|
531
|
+
const otherArgs: RequestArgs = {};
|
|
532
|
+
for (const key in ajaxConfig.args) {
|
|
533
|
+
if (key !== "query" && key !== "update") {
|
|
534
|
+
otherArgs[key] = ajaxConfig.args[key];
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// Build the query string using here-string for easy editing
|
|
539
|
+
if (queryParam) {
|
|
540
|
+
// Handle both string and string[] cases - use first element if array
|
|
541
|
+
const queryText = Array.isArray(queryParam) ? queryParam[0] : queryParam;
|
|
542
|
+
lines.push(`$${queryParamName} = @"`);
|
|
543
|
+
lines.push(queryText);
|
|
544
|
+
lines.push(`"@`);
|
|
545
|
+
lines.push("");
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// Build the body with the query variable and any other parameters
|
|
549
|
+
// The query must be URL-encoded for application/x-www-form-urlencoded
|
|
550
|
+
let bodyExpression: string;
|
|
551
|
+
const urlEncodeExpr = `[System.Net.WebUtility]::UrlEncode($${queryParamName})`;
|
|
552
|
+
if (queryParam && Object.keys(otherArgs).length > 0) {
|
|
553
|
+
// Both query variable and other args
|
|
554
|
+
const otherArgsString = queryString.stringify(otherArgs);
|
|
555
|
+
bodyExpression = `"${queryParamName}=$(${urlEncodeExpr})&${escapePowerShellString(otherArgsString)}"`;
|
|
556
|
+
} else if (queryParam) {
|
|
557
|
+
// Only query variable - use subexpression for URL encoding
|
|
558
|
+
bodyExpression = `"${queryParamName}=$(${urlEncodeExpr})"`;
|
|
559
|
+
} else {
|
|
560
|
+
// Only other args (shouldn't happen, but handle it)
|
|
561
|
+
const otherArgsString = queryString.stringify(otherArgs);
|
|
562
|
+
bodyExpression = `"${escapePowerShellString(otherArgsString)}"`;
|
|
563
|
+
}
|
|
564
|
+
|
|
527
565
|
lines.push("$params = @{");
|
|
528
566
|
lines.push(` Uri = "${escapePowerShellString(url)}"`);
|
|
529
567
|
lines.push(` Method = "Post"`);
|
|
@@ -533,8 +571,8 @@ export function getAsPowerShellString(yasqe: Yasqe, _config?: Config["requestCon
|
|
|
533
571
|
lines.push(" }");
|
|
534
572
|
}
|
|
535
573
|
lines.push(` ContentType = "application/x-www-form-urlencoded"`);
|
|
536
|
-
lines.push(` Body =
|
|
537
|
-
lines.push(` OutFile = "
|
|
574
|
+
lines.push(` Body = ${bodyExpression}`);
|
|
575
|
+
lines.push(` OutFile = "sparql-generated.${fileExtension}"`);
|
|
538
576
|
lines.push("}");
|
|
539
577
|
} else {
|
|
540
578
|
// Handle other methods (PUT, DELETE, etc.)
|
|
@@ -552,7 +590,7 @@ export function getAsPowerShellString(yasqe: Yasqe, _config?: Config["requestCon
|
|
|
552
590
|
lines.push(` ContentType = "application/x-www-form-urlencoded"`);
|
|
553
591
|
lines.push(` Body = "${body.replace(/"/g, '`"')}"`);
|
|
554
592
|
}
|
|
555
|
-
lines.push(` OutFile = "
|
|
593
|
+
lines.push(` OutFile = "sparql-generated.${fileExtension}"`);
|
|
556
594
|
lines.push("}");
|
|
557
595
|
}
|
|
558
596
|
|