简体   繁体   中英

VSCode extension: Custom Editor with Webview both on typescript

I need to create VSCode extension. There should be Custom Editor with Webview. Also I need to use shared code in Custom Editor and Webview. Plus I need to use some libs so I plan to use webpack. yo code can generate extension skeleton with typescript and webpack. But I can't generate file for Webview.

First create a production build with webpack. This serves as the content for your webview. But because it is not possible to load the webview from an URL directly, you have to insert an iframe and load that from the URL instead.

    protected createPanel(caption: string, url: URL, placement?: string): Promise<boolean> {
        return new Promise((resolve) => {
            const viewColumn = (!placement || placement === "Active") ? ViewColumn.Active : ViewColumn.Beside;
            if (placement === "Beside Bottom") {
                void commands.executeCommand("workbench.action.editorLayoutTwoRows");
            }

            this.panel = window.createWebviewPanel(
                "the-webview", caption, viewColumn, {
                    enableScripts: true,
                    retainContextWhenHidden: true,
                },
            );

            this.panel.onDidDispose(() => { this.handleDispose(); });

            this.panel.webview.onDidReceiveMessage((message: IEmbeddedMessage) => {
                if (message.source === "app") {
                    // Handle webview messages here.
                }
            });

            // Insert an iframe to load the external URL.
            this.panel.webview.html = `
    <!doctype html><html lang="en">
    <head>
    <meta http-equiv="Content-Security-Policy" content="default-src *; img-src http: https:;
        script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'unsafe-inline' http: https: data: *;">
    </head>
    <body style="margin:0px;padding:0px;overflow:hidden;">
    <iframe id="frame:${caption}"
        src="${url.toString()}"
        frameborder="0" style="overflow: hidden; overflow-x: hidden; overflow-y: hidden; height:100%;
        width:100%; position: absolute; top: 0px; left: 0px; right: 0px; bottom: 0px" height="100%"
        width="100%">
    </iframe>
    <script>
        let frame;
        let vscode;

        window.addEventListener('message', (event) => {
            if (!frame) {
                vscode = acquireVsCodeApi();
                frame = document.getElementById("frame:${caption}");
            }

            if (event.data.source === "host") {
                // Forward message from the extension to the iframe.
                frame.contentWindow.postMessage(event.data, "*");
            } else if (event.data.source === "app") {
                // Forward messages from the iframe to the extension.
                vscode.postMessage(event.data);
            } else {
                // Forward certain messages to our parent window, which will further forward to vscode.
                switch (event.data.type) {
                    case "keydown": {
                        window.dispatchEvent(new KeyboardEvent("keydown", event.data));
                        break;
                    }
                    case "keyup": {
                        window.dispatchEvent(new KeyboardEvent("keyup", event.data));
                        break;
                    }
                }
            }
        });
    </script>

    </body></html>
    `;

        });
    }

The webview itself is also an iframe, but message handling between that and vscode is already in place. However for that additional iframe you have to do something similar to forward message either from your app code to vscode or the other direction. In my code I use a field in the sent data to decide which direction I have to take.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM