227 lines
6.8 KiB
TypeScript

import * as assert from 'assert';
import * as vscode from 'vscode';
import * as fs from 'fs';
import { opeParam, MainOutput, AbsPath } from '../../global';
import { Count, MarkdownString, WavedromString } from './common';
import { getRenderList, getCurrentRenderList } from './markdown';
import { hdlPath, hdlIcon, hdlFile } from '../../hdlFs';
const _cache = {
css : ''
};
function makeFinalHTML(body: string, style: string): string {
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="wrapper">
<div id="write">
${body}
</div>
</div>
</body>
<style>
${style}
</style>
</html>`;
}
function makeExportHTML(cssHref: string, body: string): string {
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="${cssHref}"></link>
</head>
<body>
<div id="wrapper">
<div id="write">
${body}
</div>
</div>
</body>
</html>`;
}
function makeCommonElement(renderResult: string): string {
return renderResult + '<br>\n';
}
function makeSVGElement(renderResult: string, caption: string): string {
let mainHtml;
if (caption) {
mainHtml = '<div align=center>' + renderResult + `<p class="ImgCaption">${caption}</p>` + '</div>';
} else {
mainHtml = '<div align=center>' + renderResult + '</div>';
}
return '<br>' + mainHtml + '<br><br>\n';
}
function makeSVGElementByLink(link: AbsPath, caption: string): string {
let mainHtml;
if (caption) {
mainHtml = `<div align=center><img src="${link}"></img><p class="ImgCaption">${caption}</p></div>`;
} else {
mainHtml = `<div align=center><img src="${link}"></img></div>`;
}
return '<br>' + mainHtml + '<br><br>\n';
}
function getDocCssString() {
if (_cache.css) {
return _cache.css;
} else {
const cssPath = hdlPath.join(opeParam.extensionPath, 'css/documentation.css');
const cssString = fs.readFileSync(cssPath, 'utf-8');
_cache.css = cssString;
return cssString;
}
}
function makeWavedromRenderErrorHTML() {
return `<div class="error-out">
<p class="error">Error Render</p>
</div><br>`;
}
/**
* @description make the html string of a finial display style
* @param usage in whick module is used
*/
async function makeShowHTML(usage: string): Promise<string> {
const renderList = await getCurrentRenderList();
if (!renderList || renderList.length === 0) {
return '';
}
// start to render the real html
let body = '';
for (const r of renderList) {
const renderResult = r.render();
if (renderResult) {
if (r instanceof MarkdownString) {
body += makeCommonElement(renderResult);
} else if (r instanceof WavedromString) {
body += makeSVGElement(renderResult, r.desc);
}
} else {
body += makeWavedromRenderErrorHTML();
}
}
// add css
let cssString = getDocCssString();
if (usage === 'webview') { // if invoked by webview, change background image
const webviewConfig = vscode.workspace.getConfiguration("digital-ide.function.doc.webview");
const imageUrl = webviewConfig.get('backgroundImage', '');
cssString = cssString.replace("--backgroundImage", imageUrl);
} else if (usage === 'pdf') { // if invoked by pdf, transform .vscode-light to #write
cssString = cssString.replace(/\.vscode-light/g, '#write');
}
const html = makeFinalHTML(body, cssString);
return html;
}
async function showDocWebview() {
const htmlPromise = makeShowHTML("webview");
const webview = vscode.window.createWebviewPanel(
'TOOL.doc.webview.show',
'document',
vscode.ViewColumn.Two,
{
enableScripts: true, // enable JS
retainContextWhenHidden: true, // unchange webview when hidden, prevent extra refresh
}
);
webview.iconPath = hdlIcon.getIconConfig('documentation');
webview.webview.html = await htmlPromise;
}
async function exportCurrentFileDocAsHTML() {
if (vscode.window.activeColorTheme.kind !== vscode.ColorThemeKind.Light) {
vscode.window.showErrorMessage('Please export html in a light theme!');
return;
}
const editor = vscode.window.activeTextEditor;
if (!editor) {
return;
}
const currentFilePath = hdlPath.toSlash(editor.document.fileName);
const hdlFileName = hdlPath.basename(currentFilePath);
const renderList = await getRenderList(currentFilePath);
if (!renderList || renderList.length === 0) {
return;
}
const wsPath = opeParam.workspacePath;
const markdownFolderPath = hdlPath.join(wsPath, 'html');
if (!fs.existsSync(markdownFolderPath)) {
fs.mkdirSync(markdownFolderPath);
}
const currentRoot = hdlPath.join(markdownFolderPath, hdlFileName);
if (fs.existsSync(currentRoot)) {
hdlFile.rmSync(currentRoot);
}
fs.mkdirSync(currentRoot);
const figureFolder = hdlPath.join(currentRoot, 'figure');
fs.mkdirSync(figureFolder);
const cssFolder = hdlPath.join(currentRoot, 'css');
fs.mkdirSync(cssFolder);
const relateCssPath = './css/index.css';
const cssPath = hdlPath.join(cssFolder, 'index.css');
let cssString = getDocCssString();
// only support export in the ligth theme
cssString = cssString.replace(/\.vscode-light/g, '#write');
fs.writeFileSync(cssPath, cssString);
let body = '';
for (const r of renderList) {
const renderResult = r.render();
if (r instanceof MarkdownString) {
body += makeCommonElement(renderResult);
} else if (r instanceof WavedromString) {
const svgName = 'wavedrom-' + Count.svgMakeTimes + '.svg';
const svgPath = hdlPath.join(figureFolder, svgName);
fs.writeFileSync(svgPath, renderResult);
const relatePath = hdlPath.join('./figure', svgName);
body += makeSVGElementByLink(relatePath, r.desc);
}
}
const html = makeExportHTML(relateCssPath, body);
const htmlName = 'index.html';
const htmlPath = hdlPath.join(currentRoot, htmlName);
Count.svgMakeTimes = 0;
fs.writeFileSync(htmlPath, html);
}
async function exportProjectDocAsHTML() {
vscode.window.showInformationMessage('this is exportProjectDocAsHTML');
}
export {
showDocWebview,
exportCurrentFileDocAsHTML,
exportProjectDocAsHTML,
makeShowHTML,
makeSVGElementByLink
};