在VSCode市場上搜索一個PDF閱讀插件,找到了下載量最高的插件。在檢查了插件的源代碼之后,發(fā)現(xiàn)它直接嵌入了pdf.js的Web界面。
圖片
開發(fā)這樣的插件并不復(fù)雜,只需要一些插件開發(fā)的知識。
接下來,將在這里與大家分享這個插件是如何開發(fā)的。雖然與源代碼可能有些許不同,但基本原理是相同的。
默認(rèn)情況下,VSCode不直接支持查看某些特定類型的文件。但是,你可以通過使用自定義編輯器(customerEditors)來擴展其功能。
通過customerEditors,你可以創(chuàng)建完全可自定義的讀/寫編輯器,以替換VSCode的標(biāo)準(zhǔn)文本編輯器,用于處理特定類型的資源。
例如,在編輯Markdown文件時,可以創(chuàng)建一個自定義編輯器,從而實時預(yù)覽Markdown的渲染效果。
對于PDF文件的預(yù)覽,同樣也可以使用customerEditors功能。
首先,在插件的pacakge.json文件中定義它:
"contributes": { "customEditors": [ { "viewType": "dodo-reader.pdfEditor", "displayName": "PDF Viewer", "selector": [ { "filenamePattern": "*.pdf" } ] } ]}
創(chuàng)建一個實現(xiàn)vscode.CustomEditorProvider接口的類。該接口包含了用于管理自定義編輯器(例如打開和保存)的方法。例如:
class PdfEditorProvider implements Partial { constructor() { // 可在此處進(jìn)行初始化操作 }resolveCustomEditor(document: CustomDocument, webviewPanel: WebviewPanel, _token: CancellationToken) { // 基于URI創(chuàng)建一個自定義文檔,并返回一個自定義文檔對象 }openCustomDocument(uri: vscode.Uri, openContext: vscode.CustomDocumentOpenContext, token: vscode.CancellationToken) { // 將自定義文檔與Webview面板關(guān)聯(lián),并處理編輯器內(nèi)容與Webview之間的交互 }} // 注冊你的提供程序const myProvider = new PdfEditorProvider();const disposable = vscode.window.registerCustomEditorProvider('dodo-reader.pdfEditor', myProvider);context.subscriptions.push(disposable);
如上所述注冊自定義編輯器之后,下一步就是加強PdfEditorProvider接口,以定義視圖的顯示方式。
顯示涉及使用網(wǎng)絡(luò)視圖,而你將使用pdf.js的Web視圖程序。首先,下載預(yù)構(gòu)建的程序(現(xiàn)代瀏覽器),并將其提取到你的項目目錄中。
圖片
這個程序可以直接在瀏覽器中訪問。在目錄中啟動一個服務(wù),并打開地址:
你可以通過添加查詢參數(shù)?file=fileUrl來打開PDF文件。
當(dāng)打開PDF文件時,首先會調(diào)用openCustomDocument方法。你可以基于傳入的URI創(chuàng)建一個自定義文檔對象。該文檔對象將包含你想要編輯的內(nèi)容。在這個程序中,不進(jìn)行任何處理,而是直接返回一個包含URI的對象,該對象將傳遞給resolveCustomEditor方法的document參數(shù)。
openCustomDocument(uri: vscode.Uri, openContext: vscode.CustomDocumentOpenContext, token: vscode.CancellationToken) { return { uri, dispose: () => { } };}
在resolveCustomEditor方法中,可以定義要顯示的視圖,程序如下。
resolveCustomEditor(document: CustomDocument, webviewPanel: WebviewPanel, _token: CancellationToken) { webviewPanel.webview.html = 'Hello World!';}
要顯示PDF文件,只需將下載的PDF程序的HTML內(nèi)容替換為當(dāng)前的webviewPanel.webview.html值。最初認(rèn)為可以更改為:
// 嵌入一個iframe以查看PDFwebviewPanel.webview.html = ` `
這個方法是最簡單的,但令人意外的是,iframe沒有顯示內(nèi)容。這可能是由于VSCode的安全策略限制造成的。
因此,在這里考慮了另一種方法:讀取PDF視圖主頁的HTML內(nèi)容,并將其賦值給webviewPanel.webview.html。
然而,這種方法可能會遇到一個問題:如何向PDF視圖程序提供文件鏈接。
如前所述,PDF視圖程序?qū)⑼ㄟ^查詢參數(shù)“file.”獲取文件鏈接。如果沒有提供此參數(shù),程序?qū)⒆x取默認(rèn)鏈接。以下是一個相關(guān)的源代碼示例:
file = params.get("file") ?? _app_options.AppOptions.get("defaultUrl");
然而,直接賦值HTML文本不能通過URL提供“file”的值。這可能需要修改源代碼。盡管修改源代碼可能會帶來一些不便,但一開始似乎也沒有其他辦法,所以不得不嘗試一下。一種方法是改變獲取“file”值的方式,直接從全局變量中獲取。可以使用如下方法在HTML內(nèi)容中添加“file”值:
window.file = 'https://...'
然后將上述源代碼修改為:
file = window.file ?? _app_options.AppOptions.get("defaultUrl");
然而,就在我以為成功即將到來的時候,出現(xiàn)了一個紅色錯誤:“加載PDF時出現(xiàn)錯誤。文件來源與閱覽器不匹配”。
經(jīng)過進(jìn)一步調(diào)查,在相應(yīng)的源代碼中發(fā)現(xiàn)了一個“fileinputchange”事件監(jiān)聽處理程序,如下所示:
var webViewerFileInputChange = function (evt) { if (PDFViewerApplication.pdfViewer?.isInPresentationMode) { return; } const file = evt.fileInput.files[0]; PDFViewerApplication.open({ url: URL.createObjectURL(file), originalUrl: file.name });};
從代碼中很容易看出,一旦檢測到文件發(fā)生更改,就會立即調(diào)用open方法打開文件。重要的是要注意,該open方法并不驗證URL是否與當(dāng)前源相匹配。目前,它使用了一個blob鏈接。在這種情況下,我們是否可以在初始化后直接調(diào)用open方法來打開文件呢?經(jīng)過一些改造,最終證明是可行的。以下是修改后的代碼示例:
resolveCustomEditor(document: CustomDocument, webviewPanel: WebviewPanel, _token: CancellationToken) { webviewPanel.webview.options = { enableScripts: true, localResourceRoots: [vscode.Uri.file(path.dirname(document.uri.fsPath)), this.context.extensionUri] }; const base = vscode.Uri.joinPath(this.context.extensionUri, 'dist/web/pdf/web/') webviewPanel.webview.html = readFileSync(path.join(base.fsPath, 'viewer.html'), 'utf8').replace('', ` `)}
對上面的關(guān)鍵代碼進(jìn)行分析:
與之前提到的PDF插件實現(xiàn)相比,這種實現(xiàn)要簡單得多,但原理基本相同。
本文鏈接:http://www.www897cc.com/showinfo-26-77691-0.html手把手教你開發(fā)自己的VSCode插件
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com