From 0d7b5acf03d60a08f3d6015db708c8773ce516c1 Mon Sep 17 00:00:00 2001 From: Kirigaya <1193466151@qq.com> Date: Sat, 4 Jan 2025 00:10:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=20netlist=20=E4=BF=9D?= =?UTF-8?q?=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- l10n/bundle.l10n.de.json | 4 +- l10n/bundle.l10n.en.json | 4 +- l10n/bundle.l10n.ja.json | 4 +- l10n/bundle.l10n.zh-cn.json | 4 +- l10n/bundle.l10n.zh-tw.json | 4 +- package-lock.json | 26 +++- package.json | 14 +- src/function/{hdlDoc => dide-doc}/common.ts | 0 src/function/{hdlDoc => dide-doc}/diagram.ts | 0 src/function/{hdlDoc => dide-doc}/html.ts | 2 +- src/function/{hdlDoc => dide-doc}/index.ts | 0 src/function/{hdlDoc => dide-doc}/markdown.ts | 2 +- src/function/{hdlDoc => dide-doc}/pdf.ts | 6 +- src/function/dide-netlist/api.ts | 132 ++++++++++++++++++ src/function/dide-viewer/api.ts | 2 +- src/function/index.ts | 2 +- 16 files changed, 184 insertions(+), 22 deletions(-) rename src/function/{hdlDoc => dide-doc}/common.ts (100%) rename src/function/{hdlDoc => dide-doc}/diagram.ts (100%) rename src/function/{hdlDoc => dide-doc}/html.ts (99%) rename src/function/{hdlDoc => dide-doc}/index.ts (100%) rename src/function/{hdlDoc => dide-doc}/markdown.ts (99%) rename src/function/{hdlDoc => dide-doc}/pdf.ts (93%) create mode 100644 src/function/dide-netlist/api.ts diff --git a/l10n/bundle.l10n.de.json b/l10n/bundle.l10n.de.json index 6414d43..051ef8c 100644 --- a/l10n/bundle.l10n.de.json +++ b/l10n/bundle.l10n.de.json @@ -104,5 +104,7 @@ "error.cannot-gen-netlist": "Netlist-Datei konnte nicht generiert werden!", "info.common.confirm": "Bestätigen", "info.command.structure.reload-vscode": "Vscode neu starten", - "error.look-up-log": "Fehlerprotokoll anzeigen" + "error.look-up-log": "Fehlerprotokoll anzeigen", + "netlist.save-as-svg": "Als SVG speichern", + "svg-file": "SVG-Datei" } \ No newline at end of file diff --git a/l10n/bundle.l10n.en.json b/l10n/bundle.l10n.en.json index 95e7c19..96ad49a 100644 --- a/l10n/bundle.l10n.en.json +++ b/l10n/bundle.l10n.en.json @@ -104,5 +104,7 @@ "error.cannot-gen-netlist": "Unable to generate Netlist file!", "info.common.confirm": "Confirm", "info.command.structure.reload-vscode": "Restart Vscode", - "error.look-up-log": "View error log" + "error.look-up-log": "View error log", + "netlist.save-as-svg": "Save as SVG", + "svg-file": "SVG file" } \ No newline at end of file diff --git a/l10n/bundle.l10n.ja.json b/l10n/bundle.l10n.ja.json index a3b9a9a..8766455 100644 --- a/l10n/bundle.l10n.ja.json +++ b/l10n/bundle.l10n.ja.json @@ -104,5 +104,7 @@ "error.cannot-gen-netlist": "ネットリストファイルを生成できません!", "info.common.confirm": "確認", "info.command.structure.reload-vscode": "Vscodeを再起動", - "error.look-up-log": "エラーログを表示" + "error.look-up-log": "エラーログを表示", + "netlist.save-as-svg": "SVGとして保存", + "svg-file": "SVGファイル" } \ No newline at end of file diff --git a/l10n/bundle.l10n.zh-cn.json b/l10n/bundle.l10n.zh-cn.json index 81e7538..322ae11 100644 --- a/l10n/bundle.l10n.zh-cn.json +++ b/l10n/bundle.l10n.zh-cn.json @@ -104,5 +104,7 @@ "error.cannot-gen-netlist": "无法生成 Netlist 文件!", "info.common.confirm": "确认", "info.command.structure.reload-vscode": "重启 Vscode", - "error.look-up-log": "查看错误日志" + "error.look-up-log": "查看错误日志", + "netlist.save-as-svg": "保存为 Svg", + "svg-file": "svg 文件" } \ No newline at end of file diff --git a/l10n/bundle.l10n.zh-tw.json b/l10n/bundle.l10n.zh-tw.json index 0b1209d..2dcb2e8 100644 --- a/l10n/bundle.l10n.zh-tw.json +++ b/l10n/bundle.l10n.zh-tw.json @@ -104,5 +104,7 @@ "error.cannot-gen-netlist": "無法生成Netlist檔案!", "info.common.confirm": "確認", "info.command.structure.reload-vscode": "重啟 Vscode", - "error.look-up-log": "查看錯誤日誌" + "error.look-up-log": "查看錯誤日誌", + "netlist.save-as-svg": "保存為Svg", + "svg-file": "SVG 檔案" } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0867dbe..4831cf4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "bson": "^6.8.0", "chokidar": "^4.0.1", "minimatch": "^10.0.1", + "pako": "^2.1.0", "puppeteer-core": "^19.4.1", "showdown": "^2.1.0", "state-machine-cat": "^9.2.5", @@ -26,6 +27,7 @@ "devDependencies": { "@types/mocha": "^10.0.0", "@types/node": "16.x", + "@types/pako": "^2.0.3", "@types/showdown": "^2.0.0", "@types/vscode": "^1.72.0", "@typescript-eslint/eslint-plugin": "^5.42.0", @@ -37,7 +39,7 @@ "webpack-cli": "^5.1.4" }, "engines": { - "vscode": "^1.95.0" + "vscode": "^1.94.0" } }, "node_modules/@discoveryjs/json-ext": { @@ -386,6 +388,12 @@ "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==", "devOptional": true }, + "node_modules/@types/pako": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.3.tgz", + "integrity": "sha512-bq0hMV9opAcrmE0Byyo0fY3Ew4tgOevJmQ9grUhpXQhYfyLJ1Kqg3P33JT5fdbT2AjeAjR51zqqVjAL/HMkx7Q==", + "dev": true + }, "node_modules/@types/semver": { "version": "7.3.13", "resolved": "https://registry.npmmirror.com/@types/semver/-/semver-7.3.13.tgz", @@ -3092,6 +3100,11 @@ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz", @@ -4961,6 +4974,12 @@ "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==", "devOptional": true }, + "@types/pako": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.3.tgz", + "integrity": "sha512-bq0hMV9opAcrmE0Byyo0fY3Ew4tgOevJmQ9grUhpXQhYfyLJ1Kqg3P33JT5fdbT2AjeAjR51zqqVjAL/HMkx7Q==", + "dev": true + }, "@types/semver": { "version": "7.3.13", "resolved": "https://registry.npmmirror.com/@types/semver/-/semver-7.3.13.tgz", @@ -7049,6 +7068,11 @@ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" }, + "pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz", diff --git a/package.json b/package.json index fa6b3c4..830ea60 100644 --- a/package.json +++ b/package.json @@ -755,11 +755,6 @@ "command": "digital-ide.tool.instance", "group": "navigation@3" }, - { - "when": "editorLangId == verilog || editorLangId == systemverilog || editorLangId == vhdl", - "command": "digital-ide.tool.testbench", - "group": "navigation@4" - }, { "when": "editorLangId == verilog || editorLangId == systemverilog || editorLangId == vhdl", "command": "digital-ide.tool.icarus.simulateFile", @@ -792,11 +787,6 @@ "command": "digital-ide.pl.setSimTop", "group": "navigation@6" }, - { - "when": "editorLangId == verilog || editorLangId == systemverilog || editorLangId == vhdl", - "command": "digital-ide.tool.testbench", - "group": "navigation@7" - }, { "when": "resourceLangId == verilog || resourceLangId == systemverilog || resourceLangId == vhdl", "command": "digital-ide.tool.instance", @@ -1248,6 +1238,7 @@ "devDependencies": { "@types/mocha": "^10.0.0", "@types/node": "16.x", + "@types/pako": "^2.0.3", "@types/showdown": "^2.0.0", "@types/vscode": "^1.72.0", "@typescript-eslint/eslint-plugin": "^5.42.0", @@ -1263,6 +1254,7 @@ "bson": "^6.8.0", "chokidar": "^4.0.1", "minimatch": "^10.0.1", + "pako": "^2.1.0", "puppeteer-core": "^19.4.1", "showdown": "^2.1.0", "state-machine-cat": "^9.2.5", @@ -1274,4 +1266,4 @@ "wavedrom": "^2.9.1", "zlib": "^1.0.5" } -} \ No newline at end of file +} diff --git a/src/function/hdlDoc/common.ts b/src/function/dide-doc/common.ts similarity index 100% rename from src/function/hdlDoc/common.ts rename to src/function/dide-doc/common.ts diff --git a/src/function/hdlDoc/diagram.ts b/src/function/dide-doc/diagram.ts similarity index 100% rename from src/function/hdlDoc/diagram.ts rename to src/function/dide-doc/diagram.ts diff --git a/src/function/hdlDoc/html.ts b/src/function/dide-doc/html.ts similarity index 99% rename from src/function/hdlDoc/html.ts rename to src/function/dide-doc/html.ts index 08cf36e..b17cd7c 100644 --- a/src/function/hdlDoc/html.ts +++ b/src/function/dide-doc/html.ts @@ -276,7 +276,7 @@ async function exportCurrentFileDocAsHTML() { } const wsPath = opeParam.workspacePath; - const markdownFolderPath = hdlPath.join(wsPath, 'html'); + const markdownFolderPath = hdlPath.join(wsPath, 'doc'); if (!fs.existsSync(markdownFolderPath)) { fs.mkdirSync(markdownFolderPath); } diff --git a/src/function/hdlDoc/index.ts b/src/function/dide-doc/index.ts similarity index 100% rename from src/function/hdlDoc/index.ts rename to src/function/dide-doc/index.ts diff --git a/src/function/hdlDoc/markdown.ts b/src/function/dide-doc/markdown.ts similarity index 99% rename from src/function/hdlDoc/markdown.ts rename to src/function/dide-doc/markdown.ts index 3a414d8..1ccf555 100644 --- a/src/function/hdlDoc/markdown.ts +++ b/src/function/dide-doc/markdown.ts @@ -364,7 +364,7 @@ async function exportCurrentFileDocAsMarkdown() { } const wsPath = opeParam.workspacePath; - const markdownFolderPath = hdlPath.join(wsPath, 'markdown'); + const markdownFolderPath = hdlPath.join(wsPath, 'doc'); if (!fs.existsSync(markdownFolderPath)) { fs.mkdirSync(markdownFolderPath); } diff --git a/src/function/hdlDoc/pdf.ts b/src/function/dide-doc/pdf.ts similarity index 93% rename from src/function/hdlDoc/pdf.ts rename to src/function/dide-doc/pdf.ts index e027119..6130b33 100644 --- a/src/function/hdlDoc/pdf.ts +++ b/src/function/dide-doc/pdf.ts @@ -8,6 +8,10 @@ import { AbsPath, MainOutput, opeParam, ReportType } from '../../global'; // TODO : finish it in each platform function getDefaultBrowerPath(): AbsPath { + const browserPath = vscode.workspace.getConfiguration().get('digital-ide.function.doc.pdf.browserPath.title'); + if (browserPath && fs.existsSync(browserPath)) { + return browserPath; + } switch (opeParam.os) { case 'win32': return 'C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe'; case 'linux': return ''; @@ -79,7 +83,7 @@ async function exportCurrentFileDocAsPDF(uri: vscode.Uri) { return; } - const pdfFolderPath = hdlPath.join(wsPath, 'pdf'); + const pdfFolderPath = hdlPath.join(wsPath, 'doc'); if (!fs.existsSync(pdfFolderPath)) { fs.mkdirSync(pdfFolderPath); } diff --git a/src/function/dide-netlist/api.ts b/src/function/dide-netlist/api.ts new file mode 100644 index 0000000..3f8730f --- /dev/null +++ b/src/function/dide-netlist/api.ts @@ -0,0 +1,132 @@ +import * as vscode from 'vscode'; +import * as path from 'path'; +import * as fs from 'fs'; + +import pako from 'pako'; +import puppeteer, { LowerCasePaperFormat, PDFOptions } from 'puppeteer-core'; +import { AbsPath, opeParam } from '../../global'; +import { hdlPath } from '../../hdlFs'; +import { t } from '../../i18n'; + +// TODO : finish it in each platform +function getDefaultBrowerPath(): AbsPath { + const browserPath = vscode.workspace.getConfiguration().get('digital-ide.function.doc.pdf.browserPath.title'); + if (browserPath && fs.existsSync(browserPath)) { + return browserPath; + } + switch (opeParam.os) { + case 'win32': return 'C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe'; + case 'linux': return ''; + default: return ''; + } +} + +export async function saveAsSvg(data: any, panel: vscode.WebviewPanel) { + try { + const { svgBuffer, moduleName } = data; + const svgString = pako.ungzip(svgBuffer, { to: 'string' }); + // 询问新的路径 + const defaultFilename = moduleName + '.svg'; + const defaultPath = hdlPath.join(opeParam.workspacePath, defaultFilename); + const vcdFilters: Record = {}; + vcdFilters[""] = ['svg']; + vcdFilters[t('info.vcd-viewer.all-file')] = ['*']; + + const saveUri = await vscode.window.showSaveDialog({ + title: t('info.vcd-viewer.save-as-view'), + defaultUri: vscode.Uri.file(defaultPath), + saveLabel: t('info.vcd-viewer.save'), + filters: { + [t('svg-file')]: ['svg'], + [t("info.vcd-viewer.all-file")]: ['*'] + } + }); + + if (saveUri) { + const savePath = saveUri.fsPath; + fs.writeFileSync(savePath, svgString); + + panel.webview.postMessage({ + command: 'save-as-svg', + arguments: [{ success: true }] + }); + + } else { + panel.webview.postMessage({ + command: 'save-as-svg', + arguments: [{ success: false }] + }); + } + } catch (error) { + console.log('error happen in /save-as-svg, ' + error); + panel.webview.postMessage({ + command: 'save-as-svg', + arguments: [{ success: false }] + }); + } +} + +export async function saveAsPdf(req: Request, res: Response) { + try { + const { svgBuffer, moduleName, width, height } = req.body; + const svgString = pako.ungzip(svgBuffer, { to: 'string' }); + // 询问新的路径 + const defaultFilename = moduleName + '.pdf'; + const savePath = await showSaveViewDialog({ + title: 'Save As pdf', + defaultPath: path.resolve(__dirname, '../test', defaultFilename), + buttonLabel: 'Save', + filters: [ + { name: 'pdf', extensions: ['pdf'] }, + { name: 'All Files', extensions: ['*'] }, + ], + }); + + if (savePath) { + // 先保存 html + const htmlPath = savePath.slice(0, -4) + '.html'; + fs.writeFileSync(htmlPath, svgString); + + await html2pdf(htmlPath, savePath, moduleName, width, height); + // removeBlankPages(savePath); + + res.send({ + savePath, + success: true + }); + } else { + res.send({ + success: false + }); + } + } catch (error) { + console.log('error happen in /save-as-pdf, ' + error); + res.send({ + success: false + }); + } +} + +async function html2pdf(htmlPath: string, pdfPath: string, moduleName: string, width: number, height: number) { + const browser = await puppeteer.launch({ + executablePath: browserPath, + args: ['--lang=en-US', '--no-sandbox', '--disable-setuid-sandbox'] + }); + + const page = await browser.newPage(); + const uriFilePath = 'file:///' + path.resolve(htmlPath).replace(/\\/g, "/"); + await page.goto(uriFilePath, { waitUntil: 'networkidle0' }); + + const options: PDFOptions = { + path: pdfPath, + scale: 1, + displayHeaderFooter: true, + // headerTemplate: `
module ${moduleName}
`, + footerTemplate: `
Netlist for ${moduleName} - 由 Digital IDE 生成
`, + printBackground: true, + landscape: true, + width: width + }; + await page.pdf(options); + await browser.close(); +} \ No newline at end of file diff --git a/src/function/dide-viewer/api.ts b/src/function/dide-viewer/api.ts index 22c8db0..171dec2 100644 --- a/src/function/dide-viewer/api.ts +++ b/src/function/dide-viewer/api.ts @@ -163,7 +163,7 @@ export async function loadView(data: any, uri: vscode.Uri, panel: vscode.Webview panel.title = path.basename(viewPath); panel.iconPath = getIconConfig('view'); - const recoverJson = BSON.deserialize(buffer); + const recoverJson = BSON.deserialize(new Uint8Array(buffer)); panel.webview.postMessage({ command: 'load-view', recoverJson, diff --git a/src/function/index.ts b/src/function/index.ts index ea17fbb..6701e21 100644 --- a/src/function/index.ts +++ b/src/function/index.ts @@ -1,7 +1,7 @@ import * as vscode from 'vscode'; import * as path from 'path'; -import * as hdlDoc from './hdlDoc'; +import * as hdlDoc from './dide-doc'; import * as sim from './sim'; import * as treeView from './treeView';