Skip to content

Commit

Permalink
Initial Setup of Markdown+Mermaid (#209)
Browse files Browse the repository at this point in the history
  • Loading branch information
nikhilkalburgi authored Feb 22, 2024
1 parent c22544f commit 89335b5
Show file tree
Hide file tree
Showing 7 changed files with 338 additions and 170 deletions.
279 changes: 111 additions & 168 deletions package-lock.json

Large diffs are not rendered by default.

28 changes: 27 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
"onLanguage:yml",
"onLanguage:yaml",
"onLanguage:json",
"onCommand:asyncapi.preview"
"onCommand:asyncapi.preview",
"onCommand:asyncapi.markdown"
],
"main": "./dist/extension.js",
"contributes": {
Expand All @@ -49,6 +50,14 @@
{
"command": "asyncapi.paste",
"title": "AsyncAPI: Paste as Schema"
},
{
"command": "asyncapi.markdown",
"title": "Preview Asyncapi Markdown",
"icon": {
"light": "resources/icons/open-preview_black.svg",
"dark": "resources/icons/open-preview_white.svg"
}
}
],
"snippets": [
Expand All @@ -67,11 +76,23 @@
{
"when": "(resourceLangId == json || resourceLangId == yaml) && asyncapi.isAsyncAPI",
"command": "asyncapi.preview"
},
{
"when": "(resourceLangId == json || resourceLangId == yaml) && asyncapi.isAsyncAPI",
"command": "asyncapi.markdown",
"group": "navigation"
},
{
"when": "(resourceLangId == json || resourceLangId == yaml) && asyncapi.isAsyncAPI",
"command": "asyncapi.markdown"
}
],
"commandPalette": [
{
"command": "asyncapi.preview"
},
{
"command": "asyncapi.markdown"
}
],
"editor/context": [
Expand Down Expand Up @@ -122,5 +143,10 @@
"typescript": "^4.6.4",
"webpack": "^5.70.0",
"webpack-cli": "^4.9.2"
},
"dependencies": {
"@asyncapi/parser": "^3.0.7",
"@types/markdown-it": "^13.0.7",
"markdown-it": "^14.0.0"
}
}
121 changes: 121 additions & 0 deletions src/PreviewMarkdown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import * as vscode from 'vscode';
import * as path from 'path';
import { isAsyncAPIFile } from './PreviewWebPanel';
import * as Markdownit from 'markdown-it';
import { Parser, fromFile, AsyncAPIDocumentInterface } from '@asyncapi/parser';
import Info from './components/Info';
import MermaidDiagram from './components/MermaidDiagram';

const md = Markdownit('commonmark');
const parser = new Parser();

function buildMarkdown(document:AsyncAPIDocumentInterface | undefined){

let content = '';

if(document !== undefined){

content = `
${Info(document)}
${MermaidDiagram(document)}
`;
}

return md.render(content);
}

export function previewMarkdown(context: vscode.ExtensionContext) {
return async (uri: vscode.Uri) => {
uri = uri || (await promptForAsyncapiFile()) as vscode.Uri;
if (uri) {
console.log('Opening asyncapi markdown', uri.fsPath);
openAsyncAPIMarkdown(context, uri);
}
};
}

export const openAsyncapiMdFiles: { [id: string]: vscode.WebviewPanel } = {}; // vscode.Uri.fsPath => 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')
];
if (vscode.workspace.workspaceFolders) {
vscode.workspace.workspaceFolders.forEach(folder => {
localResourceRoots.push(folder.uri);
});
}
const panel: vscode.WebviewPanel =
openAsyncapiMdFiles[uri.fsPath] ||
vscode.window.createWebviewPanel('markdown-preview', '', vscode.ViewColumn.Two, {
enableScripts: true,
retainContextWhenHidden: true,
localResourceRoots,
});

const { document } = await fromFile(parser, uri.fsPath).parse();
let result = buildMarkdown(document);

panel.title = path.basename(uri.fsPath);
panel.webview.html = getWebviewContent(context, panel.webview, uri, result);

panel.onDidDispose(() => {
delete openAsyncapiMdFiles[uri.fsPath];
});
openAsyncapiMdFiles[uri.fsPath] = panel;
}

async function promptForAsyncapiFile() {
if (isAsyncAPIFile(vscode.window.activeTextEditor?.document)) {
return vscode.window.activeTextEditor?.document.uri;
}
const uris = await vscode.window.showOpenDialog({
canSelectFiles: true,
canSelectFolders: false,
canSelectMany: false,
openLabel: 'Open AsyncAPI file',
filters: {
asyncAPI: ['yml', 'yaml', 'json'],
},
});
return uris?.[0];
}

function getWebviewContent(context: vscode.ExtensionContext, webview: vscode.Webview, asyncapiFile: vscode.Uri, result:any) {
const mermaidJs = webview.asWebviewUri(
vscode.Uri.joinPath(context.extensionUri, 'dist/node_modules/mermaid/dist/mermaid.min.js')
);

const html = `
<!DOCTYPE html>
<html>
<head>
<style>
html{
scroll-behavior: smooth;
}
body {
color: #121212;
background-color: #fff;
word-wrap: break-word;
}
h1 {
color: #121212;
}
</style>
</head>
<body x-timestamp="${Date.now()}">
${result}
<script src="${mermaidJs}"></script>
<script>
mermaid.initialize({ startOnLoad: true });
</script>
</body>
</html>
`;
return html;
}
61 changes: 61 additions & 0 deletions src/components/Info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import {AsyncAPIDocumentInterface } from '@asyncapi/parser';

export default function info(asyncapi:AsyncAPIDocumentInterface) {

const info = asyncapi.info();
const defaultContentType = asyncapi.defaultContentType();
const specId = info.id();
const termsOfService = info.termsOfService();
const license = info.license();
const contact = info.contact();
const externalDocs = info.externalDocs();
const extensions: any = info.extensions();

const infoList = [];
if (specId) {
infoList.push(`Specification ID: \`${specId}\``);
}
if (license) {
infoList.push(license.url() ? (
`License: [${license.name()}](${license.url()})`
) : `License: ${license.name()}`);
}
if (termsOfService) {
infoList.push(
`[${termsOfService}](${termsOfService})`
);
}
if (defaultContentType) {
infoList.push(
`Default content type: [${defaultContentType}](https://www.iana.org/assignments/media-types/${defaultContentType})`
);
}
if (contact) {
if (contact.url()) {
infoList.push(
`Support: [${contact.url()}](${contact.name() || 'Link'})`
);
}
if (contact.email()) {
infoList.push(
`Email support: [${`mailto:${contact.email()}`}](${contact.email()})`
);
}
}

return (
`
# ${info.title()} ${info.version()} documentation
${
infoList.map((value)=>{
return '\n* '+ value;
})
}
![${info.title()}](${(extensions.get('x-logo'))?extensions.get('x-logo').value():null})
#### ${info.description()}
`);
}
7 changes: 7 additions & 0 deletions src/components/MermaidDiagram.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {AsyncAPIDocumentInterface } from '@asyncapi/parser';

export default function mermaidDiagram(asyncapi:AsyncAPIDocumentInterface){


return ``;
}
8 changes: 7 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as vscode from 'vscode';
import { isAsyncAPIFile, openAsyncAPI, openAsyncapiFiles, previewAsyncAPI } from './PreviewWebPanel';
import { isAsyncAPIFile, openAsyncAPI, openAsyncapiFiles, previewAsyncAPI} from './PreviewWebPanel';
import { openAsyncAPIMarkdown, openAsyncapiMdFiles, previewMarkdown} from './PreviewMarkdown';
import { asyncapiSmartPaste } from './SmartPasteCommand';


Expand Down Expand Up @@ -28,6 +29,9 @@ export function activate(context: vscode.ExtensionContext) {
console.log('Reloading asyncapi file', document.uri.fsPath);
openAsyncAPI(context, document.uri);
}
if(openAsyncapiMdFiles[document.uri.fsPath]){
openAsyncAPIMarkdown(context, document.uri);
}
if (vscode.window.activeTextEditor?.document) {
setAsyncAPIPreviewContext(vscode.window.activeTextEditor.document);
}
Expand All @@ -37,6 +41,8 @@ export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.commands.registerCommand('asyncapi.preview', previewAsyncAPI(context)));

context.subscriptions.push(vscode.commands.registerCommand("asyncapi.paste", asyncapiSmartPaste));

context.subscriptions.push(vscode.commands.registerCommand("asyncapi.markdown", previewMarkdown(context)));
}

export function deactivate() {}
4 changes: 4 additions & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ const extensionConfig = {
from: 'node_modules/@asyncapi/react-component/styles/default.min.css',
to: 'node_modules/@asyncapi/react-component/styles/default.min.css',
},
{
from: '/node_modules/mermaid/dist/mermaid.min.js',
to: '/node_modules/mermaid/dist/mermaid.min.js',
},
],
}),
],
Expand Down

0 comments on commit 89335b5

Please sign in to comment.