diff --git a/src/Diagnostics.ts b/src/Diagnostics.ts new file mode 100644 index 0000000..5d24ec1 --- /dev/null +++ b/src/Diagnostics.ts @@ -0,0 +1,35 @@ +import { ISpectralDiagnostic } from '@stoplight/spectral-core'; +import * as vscode from 'vscode'; +import * as ejs from 'ejs'; +import * as path from 'path'; + +export default async function diagnosticsMarkdown(diagnostics: ISpectralDiagnostic[], context: vscode.ExtensionContext){ + const templatePath = path.join(context.extensionPath,'dist', 'components','Diagnostics.ejs'); + let data: object[] = []; + let recentErrorPath: string = ""; + let joinedPath: string = ""; + diagnostics.forEach(diagnostic =>{ + joinedPath = diagnostic.path.join(' / '); + console.log(joinedPath, recentErrorPath, data.length); + if(joinedPath.indexOf(recentErrorPath) === -1 || !recentErrorPath){ + recentErrorPath = joinedPath; + data.push({ + code: diagnostic.code, + message: diagnostic.message, + path: recentErrorPath, + severity: diagnostic.severity, + source: diagnostic.source + }); + }else{ + recentErrorPath = joinedPath; + data[data.length - 1] = { + code: diagnostic.code, + message: diagnostic.message, + path: recentErrorPath, + severity: diagnostic.severity, + source: diagnostic.source + }; + } + }); + return await ejs.renderFile(templatePath, {data}); +} \ No newline at end of file diff --git a/src/PreviewMarkdown.ts b/src/PreviewMarkdown.ts index fbf2805..21ced34 100644 --- a/src/PreviewMarkdown.ts +++ b/src/PreviewMarkdown.ts @@ -1,22 +1,24 @@ import * as vscode from 'vscode'; import * as path from 'path'; import { isAsyncAPIFile } from './PreviewWebPanel'; - +import Diagnostics from './Diagnostics'; import { Parser, fromFile, AsyncAPIDocumentInterface } from '@asyncapi/parser'; import Asyncapi from './Asyncapi'; +import { ISpectralDiagnostic } from '@stoplight/spectral-core'; const parser = new Parser(); -async function buildMarkdown(document:AsyncAPIDocumentInterface | undefined, context: vscode.ExtensionContext){ +async function buildMarkdown(document:AsyncAPIDocumentInterface | undefined, diagnostics: ISpectralDiagnostic[], context: vscode.ExtensionContext){ let content = ''; if(document !== undefined){ - content = await Asyncapi(document, context); + }else{ + content = await Diagnostics(diagnostics, context); } return content; @@ -39,7 +41,8 @@ export const openAsyncapiMdFiles: { [id: string]: vscode.WebviewPanel } = {}; // export async function openAsyncAPIMarkdown(context: vscode.ExtensionContext, uri: vscode.Uri) { const localResourceRoots = [ vscode.Uri.file(path.dirname(uri.fsPath)), - vscode.Uri.joinPath(context.extensionUri, 'dist/node_modules/mermaid/dist/mermaid.min.js') + vscode.Uri.joinPath(context.extensionUri, 'dist/node_modules/mermaid/dist/mermaid.min.js'), + vscode.Uri.joinPath(context.extensionUri, 'dist/globals.css') ]; if (vscode.workspace.workspaceFolders) { vscode.workspace.workspaceFolders.forEach(folder => { @@ -54,8 +57,8 @@ export async function openAsyncAPIMarkdown(context: vscode.ExtensionContext, uri localResourceRoots, }); - const { document } = await fromFile(parser, uri.fsPath).parse(); - let result = await buildMarkdown(document, context); + const { document, diagnostics } = await fromFile(parser, uri.fsPath).parse(); + let result = await buildMarkdown(document, diagnostics, context); panel.title = path.basename(uri.fsPath); @@ -87,164 +90,15 @@ function getWebviewContent(context: vscode.ExtensionContext, webview: vscode.Web const mermaidJs = webview.asWebviewUri( vscode.Uri.joinPath(context.extensionUri, 'dist/node_modules/mermaid/dist/mermaid.min.js') ); + const globalsCSS = webview.asWebviewUri( + vscode.Uri.joinPath(context.extensionUri, 'dist/globals.css') + ); const html = ` - + diff --git a/src/components/Diagnostics.ejs b/src/components/Diagnostics.ejs new file mode 100644 index 0000000..8f47733 --- /dev/null +++ b/src/components/Diagnostics.ejs @@ -0,0 +1,21 @@ +

Error Loading Preview

+<% data.forEach(diagnostic => { %> +
+ <% if(diagnostic.severity == 0) { %> +
+ <% } else if(diagnostic.severity == 1) { %> +
+ <% }else if(diagnostic.severity == 2) { %> +
+ <% }else if(diagnostic.severity == 3) { %> +
+ <% } %> +
+

⚠️<%= diagnostic.message %>

+

<%= diagnostic.path %>

+
<%= diagnostic.code %>
+

Source: <%= diagnostic.source %>

+

Severity: <%= diagnostic.severity %>

+
+
+<% }) %> \ No newline at end of file diff --git a/src/globals.css b/src/globals.css new file mode 100644 index 0000000..564602a --- /dev/null +++ b/src/globals.css @@ -0,0 +1,227 @@ +html{ + scroll-behavior: smooth; +} +body { + color: #121212; + background-color: #efefef; + word-wrap: break-word; + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + height: 100vh; +} +h1 { + color: #121212; +} +.container { + display: flex; + overflow-x: hidden; +} +.section { + flex: 0 0 100%; + box-sizing: border-box; + padding: 20px; + aspect-ratio: 1; + overflow-y: auto; + height:calc(100vh - 60px);; +} +.button-container { + display: flex; + justify-content: center; + margin: 10px; +} +.button { + padding: 10px 20px; + margin: 0px 10px; + border-radius: .5rem; + color: #444; + font-size: 1rem; + font-weight: 700; + letter-spacing: .1rem; + cursor: pointer; + flex:1; + border: none; + outline: none; + transition: .2s ease-in-out; + box-shadow: -6px -6px 14px rgba(255, 255, 255, .7), + -6px -6px 10px rgba(255, 255, 255, .5), + 6px 6px 8px rgba(255, 255, 255, .075), + 6px 6px 10px rgba(0, 0, 0, .15); +} +button:hover { + box-shadow: -2px -2px 6px rgba(255, 255, 255, .6), + -2px -2px 4px rgba(255, 255, 255, .4), + 2px 2px 2px rgba(255, 255, 255, .05), + 2px 2px 4px rgba(0, 0, 0, .1); +} +button:active { + box-shadow: inset -2px -2px 6px rgba(255, 255, 255, .7), + inset -2px -2px 4px rgba(255, 255, 255, .5), + inset 2px 2px 2px rgba(255, 255, 255, .075), + inset 2px 2px 4px rgba(0, 0, 0, .15); +} +.table-container{ + overflow-x:auto; +} +table { + width: 100%; + border-collapse: collapse; + margin-top: 20px; +} +th, td { + padding: 12px; + text-align: left; + border-bottom: 1px solid #ddd; +} +th { + background-color: black; + color: white; +} +tr:nth-child(even) { + background-color: #fefefe; +} +code { + display: block; + padding: 10px; + background-color: #282c34; + color: #abb2bf; + border-radius: 5px; + margin-bottom: 20px; + margin-top: 20px; + white-space: pre-wrap; +} +blockquote { + border-left: 4px solid #61dafb; + margin: 0; + margin-top: 20px; + padding: 10px 20px; + background-color: #fff; + color: #333; +} +a { + text-decoration: none; + color: #3498db; + font-weight: bold; + transition: color 0.3s ease-in-out; +} +a:hover { + color: #1abc9c; +} + +@media screen and (max-width: 600px) { + table { + display: block; + } + + thead, tbody, th, td, tr { + display: block; + } + + th { + position: absolute; + top: -9999px; + left: -9999px; + } + + td { + border: none; + position: relative; + padding-left: 50%; + white-space: nowrap; + } + + td:before { + position: absolute; + top: 12px; + left: 6px; + width: 45%; + padding-right: 10px; + white-space: nowrap; + content: attr(data-th) ": "; + font-weight: bold; + } + code { + font-size: 14px; + } + + blockquote { + font-size: 16px; + } +} + +.diagnostic { + display: flex; + border: 1px solid #ccc; + border-radius: 10px; + padding: 20px; + margin-bottom: 20px; + background-color: #fff; + box-shadow: 5px 5px 15px #bcbcbc, -5px -5px 15px #ffffff; + transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out; + overflow: hidden; +} + +.diagnostic:hover { + transform: translate(2px, 2px); + box-shadow: 7px 7px 20px #bcbcbc, -7px -7px 20px #ffffff; +} + +.left-bar { + width: 10px; + border-radius: 10px 0 0 10px; + display: inline-block; + vertical-align: top; + margin-right: 20px; +} + +.high { + background-color: #e74c3c; +} +.medium { + background-color: #d9720b; +} +.low { + background-color: #ebe80a; +} +.hint{ + background-color: #119adf; +} + +.content-box { + flex-grow: 1; +} + +.message { + font-size: 18px; + font-weight: bold; + margin-bottom: 10px; +} + +.secondary-text { + color: #666; + font-size: 14px; + margin-bottom: 10px; +} + +.icon { + font-size: 24px; + color: #e74c3c; + margin-right: 10px; + vertical-align: middle; +} + +.code { + font-family: monospace; + white-space: pre-wrap; + background-color: #f9f9f9; + padding: 10px; + border-radius: 5px; + margin-top: 10px; +} + +.source { + font-style: italic; + color: #999; + margin-top: 10px; +} \ No newline at end of file