|
| 1 | +import { CellValue } from '../pure/bqrs-cli-types'; |
| 2 | +import { tryGetRemoteLocation } from '../pure/bqrs-utils'; |
1 | 3 | import { createRemoteFileRef } from '../pure/location-link-utils'; |
2 | 4 | import { parseHighlightedLine, shouldHighlightLine } from '../pure/sarif-utils'; |
| 5 | +import { convertNonPrintableChars } from '../text-utils'; |
3 | 6 | import { RemoteQuery } from './remote-query'; |
4 | | -import { AnalysisAlert, AnalysisResults, CodeSnippet, FileLink, getAnalysisResultCount, HighlightedRegion } from './shared/analysis-result'; |
| 7 | +import { AnalysisAlert, AnalysisRawResults, AnalysisResults, CodeSnippet, FileLink, getAnalysisResultCount, HighlightedRegion } from './shared/analysis-result'; |
5 | 8 |
|
6 | 9 | // Each array item is a line of the markdown file. |
7 | 10 | export type MarkdownFile = string[]; |
@@ -34,7 +37,8 @@ export function generateMarkdown(query: RemoteQuery, analysesResults: AnalysisRe |
34 | 37 | lines.push(...individualResult); |
35 | 38 | } |
36 | 39 | if (analysisResult.rawResults) { |
37 | | - // TODO: Generate markdown table for raw results |
| 40 | + const rawResultTable = generateMarkdownForRawResults(analysisResult.rawResults); |
| 41 | + lines.push(...rawResultTable); |
38 | 42 | } |
39 | 43 | files.push(lines); |
40 | 44 | } |
@@ -198,6 +202,52 @@ function generateMarkdownForPathResults( |
198 | 202 | return buildExpandableMarkdownSection('Show paths', pathLines); |
199 | 203 | } |
200 | 204 |
|
| 205 | +function generateMarkdownForRawResults( |
| 206 | + analysisRawResults: AnalysisRawResults |
| 207 | +): MarkdownFile { |
| 208 | + const tableRows: MarkdownFile = []; |
| 209 | + const columnCount = analysisRawResults.schema.columns.length; |
| 210 | + // Table headers are the column names if they exist, and empty otherwise |
| 211 | + const headers = analysisRawResults.schema.columns.map( |
| 212 | + (column) => column.name || '' |
| 213 | + ); |
| 214 | + const tableHeader = `| ${headers.join(' | ')} |`; |
| 215 | + |
| 216 | + tableRows.push(tableHeader); |
| 217 | + tableRows.push('|' + ' --- |'.repeat(columnCount)); |
| 218 | + |
| 219 | + for (const row of analysisRawResults.resultSet.rows) { |
| 220 | + const cells = row.map((cell) => |
| 221 | + generateMarkdownForRawTableCell(cell, analysisRawResults.fileLinkPrefix) |
| 222 | + ); |
| 223 | + tableRows.push(`| ${cells.join(' | ')} |`); |
| 224 | + } |
| 225 | + return tableRows; |
| 226 | +} |
| 227 | + |
| 228 | +function generateMarkdownForRawTableCell( |
| 229 | + value: CellValue, |
| 230 | + fileLinkPrefix: string |
| 231 | +) { |
| 232 | + let cellValue: string; |
| 233 | + switch (typeof value) { |
| 234 | + case 'string': |
| 235 | + case 'number': |
| 236 | + case 'boolean': |
| 237 | + cellValue = `\`${convertNonPrintableChars(value.toString())}\``; |
| 238 | + break; |
| 239 | + case 'object': |
| 240 | + { |
| 241 | + const url = tryGetRemoteLocation(value.url, fileLinkPrefix); |
| 242 | + cellValue = `[\`${convertNonPrintableChars(value.label)}\`](${url})`; |
| 243 | + } |
| 244 | + break; |
| 245 | + } |
| 246 | + // `|` characters break the table, so we need to escape them |
| 247 | + return cellValue.replace('|', '\\|'); |
| 248 | +} |
| 249 | + |
| 250 | + |
201 | 251 | /** |
202 | 252 | * Creates a markdown link to a remote file. |
203 | 253 | * If the "link text" is not provided, we use the file path. |
|
0 commit comments