vscode插件开发,使用CustomEditor进行OFD文件预览

发布时间 2023-12-08 09:30:46作者: 乌拉小考

使用js开发,对ofd预览使用的三方库是 ofd.js ,通过将 ofd.js 继承到插件里面对点击ofd文件进行预览的效果

要实现的效果大致如下:

  • 识别*.ofd结尾的文件
  • 打开OfdViewer窗口,实现预览ofd文件
    那么开始了,这里就不详细讲解如何创建vscode插件开发,直接看几个重要的代码,也就是实现的逻辑。
    首先注册自定义预览窗口,这里定义了一个 OFD Viewer 的 CustomEditor ,实现一个webview来进行预览操作,他只对 ofd 结尾的文件有效
"contributes": {
		"customEditors": [
			{
				"viewType": "com.xxss0903.ofdviewer",
				"displayName": "OFD Viewer",
				"selector": [
					{
						"filenamePattern": "*.ofd"
					}
				]
			}
		],
	},

有了上面的注册我们再src文件夹下面创建一个ofdEditor.ts文件,这个是OFD Viewer的插件入口,用于插件的一般操作以及与webview进行互动。

有了ofdEditor之后我们需要在extensions里对预览插件进行注册

完成上面几步就创建了一个基本的插件了,接下来就是对插件进行功能开发了。
首先是获取一个webview对应的html内容,webview将加载下面部分的html文件,可以看到引用了media文件夹下面的ofdViewer.js和ofdviewer.css
两个前端需要的js和css文件。并且我们也把ofd的打包文件ofd.umd.js放到了media文件夹下面用于加载ofd.js插件。

  private getHtmlForWebview(webview: vscode.Webview): string {
    // Local path to script and css for the webview
    const scriptUri = webview.asWebviewUri(
      vscode.Uri.joinPath(this._context.extensionUri, "media", "ofdViewer.js")
    );  
    const scriptOfdUri = webview.asWebviewUri(
      vscode.Uri.joinPath(this._context.extensionUri, "media", "ofd.umd.js")
    );
    const scriptUri3 = webview.asWebviewUri(
      vscode.Uri.joinPath(this._context.extensionUri, "media", "ofdViewerVue.js")
    ); 
    const styleResetUri = webview.asWebviewUri(
      vscode.Uri.joinPath(this._context.extensionUri, "media", "reset.css")
    );

    const styleVSCodeUri = webview.asWebviewUri(
      vscode.Uri.joinPath(this._context.extensionUri, "media", "vscode.css")
    );

    const styleMainUri = webview.asWebviewUri(
      vscode.Uri.joinPath(this._context.extensionUri, "media", "ofdViewer.css")
    );

    // Use a nonce to whitelist which scripts can be run
    const nonce = getNonce();
    const nonce2 = getNonce();
    console.log("get nonce", nonce, nonce2);

    return /* html */ `
				<!DOCTYPE html>
				<html lang="en">
				<head>
					<meta charset="UTF-8">
	
					<!--
					Use a content security policy to only allow loading images from https or from our extension directory,
					and only allow scripts that have a specific nonce.
					-->
					<meta http-equiv="Content-Security-Policy" content="default-src * 'self' 'unsafe-inline' 'unsafe-eval' data: gap: content: https://xxx.com;media-src * blob: 'self' http://* 'unsafe-inline' 'unsafe-eval';style-src * 'self' 'unsafe-inline';img-src * 'self' data: content:;connect-src * blob:;">

					<meta name="viewport" content="width=device-width, initial-scale=1.0">
	
					<link href="${styleResetUri}" rel="stylesheet" />
					<link href="${styleVSCodeUri}" rel="stylesheet" />
					<link href="${styleMainUri}" rel="stylesheet" />
					<title>Paw Draw</title>

          <script src="https://cdn.staticfile.org/vue/3.2.36/vue.global.min.js"></script>
				</head>
				<body>
					<div id="app">
            <div ref="ofdContainerRef" id="ofd-container"></div>
            <div display="gone" ref="ofdDataRef" id="ofd-data">
              <textarea ref="codeMirrorRef" id="code-mirror"></textarea>
            </div>
          </div>

          
					<script type="module" src="${scriptOfdUri}"></script>
					<script type="module" src="${scriptUri}"></script>
					<script type="module" src="${scriptUri3}"></script>
				</body>
				</html>`;
  }

接下来就是ofdViewer.js的内容,用于解析和预览ofd文件了

(function () {
  const vscode = acquireVsCodeApi();
  const screenWidth = document.body.clientWidth;

  function displayOfdElementToPage(views) {
    let ofdContainer = document.querySelector(".ofd-container");
    ofdContainer.innerHTML = "";
    for (const div of views) {
      ofdContainer.appendChild(div);
    }
  }

  window.addEventListener("message", async (e) => {
    const { type, body, requestId } = e.data;
    // console.log("ofdeditor listen message", e.data);
    switch (type) {
      case "init":
        // console.log("ofeditor html init");
      case "update":  
        // console.log("ofeditor html update");
      case "getFileData":
        // console.log("ofeditor html getFileData", body);
        // var abBody = body.value.buffer;
        ofd.parseOfdDocument({
          ofd: body.value,
          success(res) {
            // console.log("ofdeditor success", res);
            // 渲染ofd
            const ofdView = ofd.renderOfd(screenWidth, res[0]);
            //将ofd添加到html上面
            displayOfdElementToPage(ofdView);
          },
          fail(error) {
            // console.log("ofdeditor parse error", error);
            vscode.postMessage({
              type: 'openOfdError',
              error: error.message
            });
          },
        });
    }
  });
  // Signal to VS Code that the webview is initialized.
  // 先通知vs插件js代码准备好了,然后vscode插件会返回init方法来通知js进行自己的初始化
  vscode.postMessage({ type: "ready" });
})();

主要是添加了一个window.addEventListener的方法,用于插件和webview进行通信,比如插件点击文件之后传输文件路径给webview,webview将解析错误发生时传输错误给插件用于消息提示。