Enhance your VSCode experience with a unique Custom Editor featuring a Webview built entirely in TypeScript

In order to develop a VSCode extension, I am looking to implement a Custom Editor with Webview. Additionally, I will need to utilize shared code in both the Custom Editor and Webview components. To streamline the process and incorporate necessary libraries, I have decided to leverage webpack. While yo code can aid in generating the initial extension framework with TypeScript and webpack, it does not include support for creating files specifically tailored for the Webview component.

Answer №1

To begin, generate a production build using webpack to serve as the content for your webview. Since loading the webview directly from a URL is not feasible, you will need to insert an iframe and load it 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 functions as an iframe, with message handling already established between it and vscode. However, for any additional iframe, a similar approach must be taken to forward messages either from your app code to vscode or vice versa. In my implementation, I use a field in the transmitted data to determine the direction of forwarding.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

TypeScript types for d3 version 4

I am currently working on a d3 project and to simplify the development process and reduce errors, I decided to implement TypeScript. Using d3 v4, I initially faced issues with incorrect type definitions which led to errors like d3 not having a definition ...

Can you retrieve the Angular Service Instance beyond the scope of an angular component?

Is it possible to obtain the reference of an Injectable Angular service within a generic class without including it in the constructor? I am exploring different methods to access the Service reference. For example: export class Utils { getData(): string ...

Angular 2 event emitter falling behind schedule

I am currently utilizing Angular 2 beta 6. The custom event I created is not being captured import {Component, OnInit, EventEmitter} from 'angular2/core'; import {NgForm} from 'angular2/common'; import {Output} from "angular2/core" ...

Is it possible for Webpack to compile a Vue template using the coffee-loader?

Every time I attempt to execute the command npm run dev, it crashes when running npm run build. I suspect that a parameter needs to be passed to uglifyjs or vue-loader. Adding a Babel preset for es2015 did not solve the issue. Error in build.js from Ugli ...

Setting the useState hook to a User type in React - the ultimate guide!

As someone new to hooks, I'm unsure about what the initial value for useState should be set to. Currently, an empty object is set as the default value for useState with const [user, setUser] = useState({}); This is causing ${crafter.id} to throw an e ...

Encountering a VUE error during unit testing operations

Upon adding a test unit and running it using npm run unit, I encountered an error causing the test to fail. However, everything appears to be working fine when I run npm run dev. It seems that when running with npm run unit, the sass-loader is unable to re ...

Transitioning menus in Ionic 2

I followed the instructions in the Ionic 2 menu documentation and tried to display the menu in a specific way: https://i.sstatic.net/zzm8f.png My intention was to have the menu displayed below the content page while keeping the menu button visible. Howe ...

Unusual function call patterns observed in generic classes

After compiling the code below, it runs without any issues interface A { x: string; } interface B { x: string; } type C<D extends A> = D | B; declare function funcA<D extends A, E extends C<D> = C<D>>(): E | E[] | undefined; d ...

The entire DOM in Angular2+ flickers upon loading a component using ngFor

I am facing an issue where, after a user clicks on an item to add it to a list and then renders the list using ngFor, there is a flickering effect on the screen/DOM. The strange thing is that this flicker only happens after adding the first item; subsequen ...

What is the method to retrieve a child element from an API response in Angular using Typescript?

My REST API is designed to return json data structured with the actual content contained within a "data" node. This setup allows for additional meta information to be included in the request, such as pagination details. { "data": [ { ...

What is causing the error message to appear even though the element has been correctly defined? - TypeError: Unable to access the value property of null

Objective: Obtain the value of an HTML element in TypeScript (Angular) Issue: Error: Uncaught (in promise): TypeError: Cannot read property 'value' of null Error Message: TypeError: Cannot read property 'value' of null at UserRegi ...

I have attempted to execute my seed script in Prisma using Next.js and TypeScript, but I keep encountering the following error. Is there a solution to resolve this issue?

Within my package.json file, I have included the following code: "prisma": { "seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts" } Upon running the comman ...

Trouble with Nested Routing in React Router Version 6: Route not Rendering

I'm facing issues nesting a path within another path in react-router-dom version 6. When I try to visit the nested argument's page (/blog/1), it shows up as a blank non-styled HTML page. However, when I add a child path to the root like /blog, it ...

The function was operational before, but currently it is indicating that it is no longer functioning as a

I encountered an issue with my code where a service that was previously working has suddenly stopped functioning and is now displaying an error message stating that it's not a function. Thanks to Sajeetharan for helping me out initially. constructo ...

What are some ways to control providers in targeted tests using ng-mocks?

I recently started utilizing ng-mocks to streamline my testing process. However, I am struggling to figure out how to modify the value of mock providers in nested describes/tests after MockBuilder/MockRender have already been defined. Specifically, my que ...

The search functionality in Angular 2 using Typescript is not working properly, as the button is not triggering the

I've been working on developing a search feature that utilizes text input to look up information about corporations through a government API (https://github.com/usagov/Corporate-Consumer-Contact-API-Documentation). Within my project, I have an HTML p ...

How to integrate angular-ui-bootstrap with webpack

I'm attempting to integrate https://github.com/angular-ui/bootstrap with Webpack: import angular from 'angular'; import uiRouter from 'angular-ui-router'; import createComponent from './create.component'; import tabs fro ...

The values of the data members remain static within the Typescript environment

In my Ionic 2 project, I have a class structured like the one below. Instead of using the Ionic Native geolocation plugin, I am working with the locationServices plugin. export class LocationManager{ locationAcquiring:boolean; locationAvailable:b ...

Nestjs struggles with resolving dependencies

Having trouble finding the issue in my code. (I'm still new to nestjs and trying to learn by working on some apps). The console log is showing the following error: Nest can't resolve dependencies of the UrlsAfipService (?). Please ensure tha ...

Why does Angular throw a length-related error, while I am able to retrieve the length using console log if needed?

It appears that Angular is not receiving the correct data type it expects, yet the lack of errors in the terminal is puzzling. However, the console output states: https://i.stack.imgur.com/1xPsg.jpg If the length property can be detected (highlighted in ...