Skip to content

Commit 09760f4

Browse files
committed
download different formats
1 parent ffe294c commit 09760f4

File tree

4 files changed

+96
-57
lines changed

4 files changed

+96
-57
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ Using the rules section of your configurations, you can specify the list of rule
7272
}
7373
```
7474

75-
Note: if you prefer JSON format, you can create a `.flow-scanner.json` file using the same format. For a more on configurations, review the [scanner documentation](https://flow-scanner.github.io/lightning-flow-scanner-core/#configurations).
75+
Note: if you prefer JSON format, you can create a `.flow-scanner.json` file using the same format. For a more on configurations, review the [scanner documentation](https://flow-scanner.github.io/lightning-flow-scanner-core/#configuration).
7676

7777
### Extension Settings
7878

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@
148148
"webpack-cli": "^5.1.4"
149149
},
150150
"dependencies": {
151-
"@flow-scanner/lightning-flow-scanner-core": "^6.0.4",
151+
"@flow-scanner/lightning-flow-scanner-core": "^6.2.1",
152152
"convert-array-to-csv": "^2.0.0",
153153
"cosmiconfig": "^9.0.0",
154154
"lightning-flow-scanner-core": "^5.9.7",

src/panels/ScanOverviewPanel.ts

Lines changed: 90 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,18 @@ import * as vscode from "vscode";
22
import * as uuid from "uuid";
33
import { convertArrayToCSV } from "convert-array-to-csv";
44
import { ViolationOverview } from "./ViolationOverviewPanel";
5-
import { ScanResult } from "@flow-scanner/lightning-flow-scanner-core";
5+
import { ScanResult, exportSarif } from "@flow-scanner/lightning-flow-scanner-core";
66

77
export class ScanOverview {
88
public static currentPanel: ScanOverview | undefined;
99
public static readonly viewType = "report";
10+
1011
private readonly _panel: vscode.WebviewPanel;
1112
private readonly _extensionUri: vscode.Uri;
1213
private _disposables: vscode.Disposable[] = [];
13-
private isDownloading = false;
14+
private _lastScanResults: ScanResult[] = [];
1415

15-
public static createOrShow(
16-
extensionUri: vscode.Uri,
17-
scanResults: ScanResult[]
18-
) {
16+
public static createOrShow(extensionUri: vscode.Uri, scanResults: ScanResult[]) {
1917
const column = vscode.window.activeTextEditor
2018
? vscode.window.activeTextEditor.viewColumn
2119
: undefined;
@@ -38,11 +36,8 @@ export class ScanOverview {
3836
],
3937
}
4038
);
41-
ScanOverview.currentPanel = new ScanOverview(
42-
panel,
43-
extensionUri,
44-
scanResults
45-
);
39+
40+
ScanOverview.currentPanel = new ScanOverview(panel, extensionUri, scanResults);
4641
}
4742

4843
public static kill() {
@@ -66,51 +61,47 @@ export class ScanOverview {
6661
this._panel.dispose();
6762
while (this._disposables.length) {
6863
const x = this._disposables.pop();
69-
if (x) {
70-
x.dispose();
71-
}
64+
if (x) x.dispose();
7265
}
7366
}
7467

7568
private async _update(scanResults: ScanResult[]) {
69+
this._lastScanResults = scanResults;
7670
const webview = this._panel.webview;
7771
this._panel.webview.html = this._getHtmlForWebview(webview);
72+
7873
webview.onDidReceiveMessage(async (data) => {
7974
switch (data.type) {
8075
case "goToFile": {
81-
if (!data.value) {
82-
return;
83-
}
76+
if (!data.value) return;
8477
vscode.workspace.openTextDocument(data.value.path).then((doc) => {
8578
vscode.window.showTextDocument(doc);
8679
});
8780
break;
8881
}
82+
8983
case "viewAll": {
90-
if (!data.value) {
91-
return;
92-
}
84+
if (!data.value) return;
9385
ViolationOverview.createOrShow(this._extensionUri, data.value, "All");
9486
break;
9587
}
88+
9689
case "goToDetails": {
97-
if (!data.value) {
98-
return;
99-
}
90+
if (!data.value) return;
10091
ViolationOverview.createOrShow(
10192
this._extensionUri,
10293
[data.value],
10394
data.value.flow.label
10495
);
10596
break;
10697
}
98+
10799
case "onError": {
108-
if (!data.value) {
109-
return;
110-
}
100+
if (!data.value) return;
111101
vscode.window.showErrorMessage(data.value);
112102
break;
113103
}
104+
114105
case "init-view": {
115106
if (scanResults) {
116107
webview.postMessage({
@@ -120,18 +111,69 @@ export class ScanOverview {
120111
}
121112
return;
122113
}
114+
123115
case "download": {
124-
let saveResult = await vscode.window.showSaveDialog({
125-
filters: {
126-
csv: [".csv"],
127-
},
128-
});
129-
const csv = convertArrayToCSV(data.value);
130-
await vscode.workspace.fs.writeFile(saveResult, Buffer.from(csv));
131-
await vscode.window.showInformationMessage(
132-
"Downloaded file: " + saveResult.fsPath
133-
);
134-
}
116+
if (!data.value || !Array.isArray(data.value) || data.value.length === 0) {
117+
await vscode.window.showInformationMessage(
118+
"No results found. Please make sure to complete a scan before downloading."
119+
);
120+
return;
121+
}
122+
123+
const formatChoice = await vscode.window.showQuickPick(
124+
[
125+
{ label: "CSV", description: "Comma-separated values", value: "csv" },
126+
{ label: "SARIF",description: "Static Analysis Results Interchange Format", value: "sarif" }
127+
],
128+
{
129+
placeHolder: "Select export format (Esc to cancel)",
130+
canPickMany: false,
131+
ignoreFocusOut: false,
132+
}
133+
);
134+
135+
if (!formatChoice) return;
136+
137+
const chosenFormat = formatChoice.value;
138+
const filterKey = chosenFormat === "sarif" ? "sarif" : "csv";
139+
const filterExt = chosenFormat === "sarif" ? ".sarif" : ".csv";
140+
141+
const defaultUri = vscode.workspace.workspaceFolders?.[0]?.uri;
142+
const saveResult = await vscode.window.showSaveDialog({
143+
defaultUri,
144+
filters: { [filterKey]: [filterExt] },
145+
title: `Save ${chosenFormat.toUpperCase()} file`,
146+
});
147+
148+
if (!saveResult) return;
149+
150+
try {
151+
let content: string;
152+
153+
if (chosenFormat === "sarif") {
154+
// ---- SARIF: use the *original* scan results (they have a real Flow with fsPath)
155+
const originalResults: ScanResult[] = this._lastScanResults ?? [];
156+
if (originalResults.length === 0) {
157+
await vscode.window.showWarningMessage("No original scan data available for SARIF export.");
158+
return;
159+
}
160+
content = exportSarif(originalResults);
161+
} else {
162+
// ---- CSV: keep using the web-view payload (already flattened)
163+
content = convertArrayToCSV(data.value);
164+
}
165+
166+
await vscode.workspace.fs.writeFile(saveResult, Buffer.from(content, "utf-8"));
167+
await vscode.window.showInformationMessage(
168+
`Downloaded ${chosenFormat.toUpperCase()} file: ${saveResult.fsPath}`
169+
);
170+
} catch (err: any) {
171+
await vscode.window.showErrorMessage(
172+
`Failed to export ${chosenFormat.toUpperCase()}: ${err?.message ?? err}`
173+
);
174+
}
175+
break;
176+
}
135177
}
136178
});
137179
}
@@ -141,11 +183,7 @@ export class ScanOverview {
141183
vscode.Uri.joinPath(this._extensionUri, "out/compiled", "ScanOverview.js")
142184
);
143185
const cssUri = webview.asWebviewUri(
144-
vscode.Uri.joinPath(
145-
this._extensionUri,
146-
"out/compiled",
147-
"ScanOverview.css"
148-
)
186+
vscode.Uri.joinPath(this._extensionUri, "out/compiled", "ScanOverview.css")
149187
);
150188
const tabulatorStyles = webview.asWebviewUri(
151189
vscode.Uri.joinPath(this._extensionUri, "media", "tabulator.css")
@@ -157,24 +195,25 @@ export class ScanOverview {
157195
vscode.Uri.joinPath(this._extensionUri, "media", "vscode.css")
158196
);
159197
const nonce = uuid.v4();
198+
160199
return `
161200
<!DOCTYPE html>
162-
<html lang="en">
163-
<head>
164-
<meta charset="UTF-8">
201+
<html lang="en">
202+
<head>
203+
<meta charset="UTF-8">
165204
<meta http-equiv="Content-Security-Policy" content="img-src https: data:; style-src 'unsafe-inline' ${webview.cspSource}; script-src 'nonce-${nonce}';">
166-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
205+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
167206
<link href="${tabulatorStyles}" rel="stylesheet">
168207
<link href="${stylesResetUri}" rel="stylesheet">
169208
<link href="${stylesMainUri}" rel="stylesheet">
170209
<link href="${cssUri}" rel="stylesheet">
171210
<script nonce="${nonce}">
172-
const tsvscode = acquireVsCodeApi();
211+
const tsvscode = acquireVsCodeApi();
173212
</script>
174-
</head>
213+
</head>
175214
<body>
176215
<script src="${scriptUri}" nonce="${nonce}"></script>
177-
</body>
178-
</html>`;
216+
</body>
217+
</html>`;
179218
}
180-
}
219+
}

0 commit comments

Comments
 (0)