You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by jt...@apache.org on 2022/08/24 07:43:10 UTC

[netbeans] branch master updated: LSP: Html4J UI modified work over LSP. (#4040)

This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new 20382955af LSP: Html4J UI modified work over LSP. (#4040)
20382955af is described below

commit 20382955afbb8c030ab711a8a003d2778b08e85e
Author: Dusan Balek <du...@oracle.com>
AuthorDate: Wed Aug 24 09:43:02 2022 +0200

    LSP: Html4J UI modified work over LSP. (#4040)
    
    * LSP: Html4J UI modified work over LSP.
    * Updating HTML4J to version 1.8.1.
---
 java/java.lsp.server/licenseinfo.xml               |   5 -
 java/java.lsp.server/nbproject/project.xml         |  60 +-
 .../modules/java/lsp/server/htmlui/Browser.java    | 741 ---------------------
 .../modules/java/lsp/server/htmlui/Buttons.java    |   5 +-
 .../modules/java/lsp/server/htmlui/HttpServer.java |  62 --
 .../java/lsp/server/htmlui/SimpleServer.java       | 712 --------------------
 .../modules/java/lsp/server/htmlui/WebView.java    | 401 +++++++++++
 .../java/lsp/server/protocol/DebugConnector.java   |   3 +
 .../java/lsp/server/protocol/HtmlPageParams.java   |  64 +-
 .../lsp/server/protocol/NbCodeClientWrapper.java   |   5 +
 .../lsp/server/protocol/NbCodeLanguageClient.java  |   9 +-
 .../modules/java/lsp/server/protocol/Server.java   |   6 +
 .../server/protocol/ShowStatusMessageParams.java   |   3 +
 .../java/lsp/server/protocol/UIContext.java        |   6 +-
 .../ChangeMethodParametersRefactoring.java         |   2 +-
 .../lsp/server/refactoring/MoveRefactoring.java    |   4 +-
 .../java/lsp/server/refactoring/ui/MoveClass.html  |   1 -
 .../lsp/server/refactoring/ui/MoveMembers.html     |   1 -
 .../java/lsp/server/refactoring/ui/codicon.css     | 485 --------------
 .../java/lsp/server/refactoring/ui/codicon.ttf     | Bin 65608 -> 0 bytes
 .../java/lsp/server/ui/AbstractLspHtmlViewer.java  |  34 +-
 .../java/lsp/server/TestCodeLanguageClient.java    |   5 +
 .../java/lsp/server/explorer/ProjectViewTest.java  |   5 +
 .../java/lsp/server/protocol/ServerTest.java       |  36 +-
 .../modules/java/lsp/server/ui/MockHtmlViewer.java |   6 +-
 java/java.lsp.server/vscode/package-lock.json      |  13 +
 java/java.lsp.server/vscode/package.json           |   1 +
 java/java.lsp.server/vscode/src/extension.ts       | 114 ++--
 java/java.lsp.server/vscode/src/protocol.ts        |  13 +-
 .../src/org/netbeans/api/htmlui/HTMLDialog.java    |  37 +-
 .../src/org/netbeans/modules/htmlui/Buttons.java   |   2 +-
 .../netbeans/modules/htmlui/ContextAccessor.java   |   2 +-
 .../netbeans/modules/htmlui/HTMLDialogBase.java    |   4 +-
 .../modules/htmlui/HTMLDialogProcessor.java        |  29 +-
 .../src/org/netbeans/modules/htmlui/Pages.java     |   2 +-
 .../src/org/netbeans/spi/htmlui/HTMLViewerSpi.java |  18 +-
 .../net.java.html.boot.fx/external/binaries-list   |   2 +-
 ...txt => net.java.html.boot.fx-1.8.1-license.txt} |   2 +-
 .../nbproject/project.properties                   |   2 +-
 .../net.java.html.boot.fx/nbproject/project.xml    |   2 +-
 .../external/binaries-list                         |   2 +-
 ...=> net.java.html.boot.script-1.8.1-license.txt} |   2 +-
 .../nbproject/project.properties                   |   2 +-
 .../nbproject/project.xml                          |   2 +-
 platform/net.java.html.boot/external/binaries-list |   2 +-
 ...se.txt => net.java.html.boot-1.8.1-license.txt} |   2 +-
 .../nbproject/project.properties                   |   2 +-
 platform/net.java.html.boot/nbproject/project.xml  |   2 +-
 platform/net.java.html.geo/external/binaries-list  |   2 +-
 ...nse.txt => net.java.html.geo-1.8.1-license.txt} |   2 +-
 .../net.java.html.geo/nbproject/project.properties |   2 +-
 platform/net.java.html.geo/nbproject/project.xml   |   2 +-
 platform/net.java.html.json/external/binaries-list |   2 +-
 ...se.txt => net.java.html.json-1.8.1-license.txt} |   2 +-
 .../nbproject/project.properties                   |   2 +-
 platform/net.java.html.json/nbproject/project.xml  |   2 +-
 .../net.java.html.sound/external/binaries-list     |   2 +-
 ...e.txt => net.java.html.sound-1.8.1-license.txt} |   2 +-
 .../nbproject/project.properties                   |   2 +-
 platform/net.java.html.sound/nbproject/project.xml |   2 +-
 platform/net.java.html/external/binaries-list      |   2 +-
 ...license.txt => net.java.html-1.8.1-license.txt} |   2 +-
 .../net.java.html/nbproject/project.properties     |   2 +-
 platform/net.java.html/nbproject/project.xml       |   2 +-
 platform/o.n.html.ko4j/external/binaries-list      |   2 +-
 .../external/ko4j-1.8.1-license.txt}               |   2 +-
 .../o.n.html.ko4j/nbproject/project.properties     |   2 +-
 platform/o.n.html.ko4j/nbproject/project.xml       |   2 +-
 .../o.n.html.presenters.spi/external/binaries-list |   2 +-
 .../external/generic-1.8.1-license.txt}            |   2 +-
 .../nbproject/project.properties                   |   2 +-
 .../o.n.html.presenters.spi/nbproject/project.xml  |   2 +-
 platform/o.n.html.xhr4j/external/binaries-list     |   2 +-
 ...j-1.7.3-license.txt => xhr4j-1.8.1-license.txt} |   2 +-
 .../o.n.html.xhr4j/nbproject/project.properties    |   2 +-
 platform/o.n.html.xhr4j/nbproject/project.xml      |   2 +-
 76 files changed, 774 insertions(+), 2202 deletions(-)

diff --git a/java/java.lsp.server/licenseinfo.xml b/java/java.lsp.server/licenseinfo.xml
index 0c93cfbd3b..05cb44d7e7 100644
--- a/java/java.lsp.server/licenseinfo.xml
+++ b/java/java.lsp.server/licenseinfo.xml
@@ -28,11 +28,6 @@
         <license ref="Apache-2.0" />
         <comment type="COMMENT_UNSUPPORTED" />
     </fileset>
-    <fileset>
-        <file>src/org/netbeans/modules/java/lsp/server/refactoring/ui/codicon.ttf</file>
-        <file>src/org/netbeans/modules/java/lsp/server/refactoring/ui/codicon.css</file>
-        <license ref="MIT" />
-    </fileset>
     <fileset>
         <file>vscode/.vscodeignore</file>
         <file>vscode/.eslintrc.json</file>
diff --git a/java/java.lsp.server/nbproject/project.xml b/java/java.lsp.server/nbproject/project.xml
index 1fe9553d73..7a11aefcb2 100644
--- a/java/java.lsp.server/nbproject/project.xml
+++ b/java/java.lsp.server/nbproject/project.xml
@@ -39,12 +39,28 @@
                     <compile-dependency/>
                     <run-dependency/>
                 </dependency>
+                <dependency>
+                    <code-name-base>net.java.html.boot</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.7.3</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     <code-name-base>net.java.html.json</code-name-base>
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency/>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.apache.commons.lang3</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.10</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     <code-name-base>org.netbeans.api.annotations.common</code-name-base>
                     <build-prerequisite/>
@@ -77,23 +93,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>1.23</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>net.java.html.boot</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>1.7.3</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.netbeans.html.presenters.spi</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>1.7.3</specification-version>
+                        <specification-version>1.25</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -166,6 +166,14 @@
                         <specification-version>1.24</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.html.presenters.spi</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.7.3</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     <code-name-base>org.netbeans.libs.flexmark</code-name-base>
                     <build-prerequisite/>
@@ -472,25 +480,23 @@
                     </run-dependency>
                 </dependency>
                 <dependency>
-                    <code-name-base>org.netbeans.modules.projectuiapi.base</code-name-base>
+                    <code-name-base>org.netbeans.modules.projectuiapi</code-name-base>
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.101</specification-version>
+                        <implementation-version/>
                     </run-dependency>
                 </dependency>
-
                 <dependency>
-                    <code-name-base>org.netbeans.modules.projectuiapi</code-name-base>
+                    <code-name-base>org.netbeans.modules.projectuiapi.base</code-name-base>
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <implementation-version/>
+                        <specification-version>1.101</specification-version>
                     </run-dependency>
                 </dependency>
-
                 <dependency>
                     <code-name-base>org.netbeans.modules.queries</code-name-base>
                     <build-prerequisite/>
@@ -657,14 +663,6 @@
                         <specification-version>9.24</specification-version>
                     </run-dependency>
                 </dependency>
-                <dependency>
-                    <code-name-base>org.apache.commons.lang3</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>1.10</specification-version>
-                    </run-dependency>
-                </dependency>
             </module-dependencies>
             <test-dependencies>
                 <test-type>
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/htmlui/Browser.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/htmlui/Browser.java
deleted file mode 100644
index f9ac76e635..0000000000
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/htmlui/Browser.java
+++ /dev/null
@@ -1,741 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.netbeans.modules.java.lsp.server.htmlui;
-
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.Flushable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.Writer;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLDecoder;
-import java.nio.file.Files;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Queue;
-import java.util.Random;
-import java.util.UUID;
-import java.util.concurrent.Executor;
-import java.util.function.Consumer;
-import java.util.function.Supplier;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import org.netbeans.html.boot.spi.Fn;
-import org.netbeans.html.boot.spi.Fn.Presenter;
-import org.netbeans.html.presenters.spi.ProtoPresenter;
-import org.netbeans.html.presenters.spi.ProtoPresenterBuilder;
-
-/** Browser based {@link Presenter}. It starts local server and
- * launches browser that connects to it. Use {@link Browser.Config} to
- * configure the actual browser to be started.
- * <p>
- * To use this presenter specify following dependency:
- * <pre>
- * &lt;dependency&gt;
- *   &lt;groupId&gt;org.netbeans.html.browser&lt;/groupId&gt;
- *   &lt;artifactId&gt;browser&lt;/artifactId&gt;
- *   &lt;version&gt;<a target="blank" href="http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.dukescript.presenters%22%20AND%20a%3A%22browser%22">1.x</a>&lt;/version&gt;
- * &lt;/dependency&gt;
- * </pre>
- */
-public final class Browser implements Fn.Presenter, Fn.KeepAlive, Flushable,
-Executor, Closeable {
-    static final Logger LOG = Logger.getLogger(Browser.class.getName());
-    private final Map<String,Command> SESSIONS = new HashMap<>();
-    private final String app;
-    private HttpServer server;
-    private Runnable onPageLoad;
-    private Command current;
-    private final Config config;
-    private final Supplier<HttpServer<?, ?, ?, ?>> serverProvider;
-
-    /** Default constructor. Reads configuration from properties. The actual browser to
-     * be launched can be influenced by value of
-     * <code>com.dukescript.presenters.browser</code> property.
-     * It can have following values:
-     * <ul>
-     * <li><b>GTK</b> - use Gtk WebKit implementation. Requires presence of
-     *    appropriate native libraries</li>
-     * <li><b>AWT</b> - use {@link java.awt.Desktop#browse(java.net.URI)} to
-     *    launch a browser</li>
-     * <li><b>NONE</b> - just launches the server, useful together with
-     *    <code>com.dukescript.presenters.browserPort</code> property that
-     *    can specify a fixed port to open the server at
-     * </li>
-     * <li>any other value is interpreted as a command which is then
-     *    launched on a command line with one parameter - the URL to connect to</li>
-     * </ul>
-     * If the property is not specified the system tries <b>GTK</b> mode first,
-     * followed by <b>AWT</b> and then tries to execute <code>xdg-open</code>
-     * (default LINUX command to launch a browser from a shell script).
-     * <p>
-     * In addition to the above properties, it is possible to also enable
-     * debugging by setting <code>com.dukescript.presenters.browserDebug=true</code>.
-     *
-     * @throws Exception
-     */
-    public Browser() {
-        this(new Config());
-    }
-
-    /**
-     * Browser configured by provided config.
-     *
-     * @param config the configuration
-     */
-    public Browser(Config config) {
-        this(findCalleeClassName(), config, null);
-    }
-
-    Browser(String app, Config config, Supplier<HttpServer<?,?,?, ?>> serverProvider) {
-        this.serverProvider = serverProvider != null ? serverProvider : () -> {
-            return new SimpleServer(config.random);
-        };
-        this.app = app;
-        this.config = new Config(config);
-    }
-
-    @Override
-    public final void execute(final Runnable r) {
-        current.execute(r);
-    }
-
-    @Override
-    public void close() throws IOException {
-        if (server != null) {
-            server.shutdownNow();
-        }
-    }
-
-    HttpServer server() {
-        return server;
-    }
-
-    static HttpServer findServer(Object obj) {
-        Command c;
-        if (obj instanceof Command) {
-            c = (Command) obj;
-        } else if (obj instanceof ProtoPresenter) {
-            c = ((ProtoPresenter) obj).lookup(Command.class);
-        } else {
-            throw new IllegalArgumentException("Cannot find server for " + obj);
-        }
-        return c.browser.server();
-    }
-
-    /** Shows URL in a browser.
-     * @param page the page to display in the browser
-     * @throws IOException if something goes wrong
-     */
-    void show(URI page) throws IOException {
-        config.getBrowser().accept(page);
-    }
-    @Override
-    public Fn defineFn(String string, String... strings) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void loadScript(Reader reader) throws Exception {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public Fn defineFn(String string, String[] strings, boolean[] blns) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void flush() throws IOException {
-        throw new UnsupportedOperationException();
-    }
-
-    private static URI pageURL(String protocol, HttpServer server, final String page) {
-        int port = server.getPort();
-        try {
-            return new URI(protocol + "://localhost:" + port + page);
-        } catch (URISyntaxException ex) {
-            throw new IllegalStateException(ex);
-        }
-    }
-
-    @Override
-    public final void displayPage(URL page, Runnable onPageLoad) {
-        try {
-            this.onPageLoad = onPageLoad;
-            this.server = serverProvider.get();
-            int from = 8080;
-            int to = 65535;
-            int port = config.getPort();
-            if (port != -1) {
-                from = to = port;
-            }
-            server.init(from, to);
-
-            String prefix = "/" + new UUID(config.random.nextLong(), config.random.nextLong()).toString();
-
-            this.server.addHttpHandler(new RootPage(page, prefix), prefix);
-            server.start();
-
-            show(pageURL("http", server, prefix + "/"));
-        } catch (IOException ex) {
-            Logger.getLogger(Browser.class.getName()).log(Level.SEVERE, null, ex);
-        }
-    }
-
-    /** Parameters to configure {@link Browser}.
-     * Create an instance and pass it
-     * to {@link Browser#Browser(org.netbeans.html.presenters.browser.Browser.Config) }
-     * constructor.
-     */
-    public static final class Config implements Cloneable {
-        private Consumer<URI> browser;
-        Integer port;
-        boolean debug = Boolean.getBoolean("com.dukescript.presenters.browserDebug");
-        Random random = new Random();
-
-        /**
-         * Default constructor.
-         */
-        public Config() {
-            command(null);
-        }
-
-        private Config(Config copy) {
-            this.browser = copy.browser;
-            this.port = copy.port;
-            this.debug = copy.debug;
-            this.random = copy.random;
-        }
-
-        @Override
-        public Config clone() {
-            return new Config(this);
-        }
-
-        /** The command to use when invoking a browser. Possible values:
-         * <ul>
-         * <li>
-         *   <b>GTK</b> - use Gtk WebKit implementation. Requires presence of appropriate native libraries
-         * </li>
-         * <li>
-         *   <b>AWT</b> - use Desktop.browse(java.net.URI) to launch a browser
-         * </li>
-         * <li>
-         *   <b>NONE</b> - just launches the server, useful together with {@link #port(int)} to specify a fixed port to open the server at
-         * </li>
-         * <li>
-         * any other value is interpreted as a command which is then launched on a command line with one parameter - the URL to connect to
-         * </li>
-         * </ul>
-         *
-         * @param executable browser to execute
-         * @return this instance
-         */
-        public Config command(String executable) {
-            this.browser = (page) -> {
-                String impl = executable;
-                if (impl == null) {
-                    impl = System.getProperty("com.dukescript.presenters.browser"); // NOI18N
-                }
-                if ("none".equalsIgnoreCase(impl)) { // NOI18N
-                    return;
-                }
-                // Show.show(impl, page); TBD
-            };
-            return this;
-        }
-        public Config browser(Consumer<URI> urlOpener) {
-            this.browser = urlOpener;
-            return this;
-        }
-
-        /** The port to start the server at.
-         * By default a random port is selected.
-         * @param port the port
-         * @return this instance
-         */
-        public Config port(int port) {
-            this.port = port;
-            return this;
-        }
-
-        /** Enable or disable debugging. The default value is taken from a property
-         * {@code com.dukescript.presenters.browserDebug}. If the property is
-         * not specified, then the default value is {@code false}.
-         *
-         * @param debug true or false
-         * @return this instance
-         * @since 1.8
-         */
-        public Config debug(boolean debug) {
-            this.debug = debug;
-            return this;
-        }
-
-        final Consumer<URI> getBrowser() {
-            return browser;
-        }
-
-        final int getPort() {
-            if (port != null) {
-                return port;
-            }
-            String browserPort = System.getProperty("com.dukescript.presenters.browserPort"); // NOI18N
-            try {
-                return Integer.parseInt(browserPort);
-            } catch (NumberFormatException ex) {
-                return -1;
-            }
-        }
-    }
-
-    static <Response> void cors(HttpServer<?, Response, ?, ?> s, Response r) {
-        s.setCharacterEncoding(r, "UTF-8");
-        s.addHeader(r, "Access-Control-Allow-Origin", "*");
-        s.addHeader(r, "Access-Control-Allow-Credentials", "true");
-        s.addHeader(r, "Access-Control-Allow-Headers", "Content-Type");
-        s.addHeader(r, "Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
-    }
-
-    private final class RootPage extends HttpServer.Handler {
-        private final URL page;
-        private final String prefix;
-
-        RootPage(URL page, String prefix) {
-            this.page = page;
-            this.prefix = prefix;
-        }
-
-        @Override
-        public <Request, Response> void service(HttpServer<Request, Response, ?, ?> server, Request rqst, Response rspns) throws IOException {
-            String path = server.getRequestURI(rqst);
-            if (path.startsWith(prefix)) {
-                path = path.substring(prefix.length());
-            } else {
-                server.setStatus(rspns, 404);
-                server.shutdownNow();
-                return;
-            }
-
-            cors(server, rspns);
-            if ("OPTIONS".equals(server.getMethod(rqst))) { // NOI18N
-                server.setStatus(rspns, 204);
-                server.addHeader(rspns, "Allow", "OPTIONS, GET, HEAD, POST, PUT"); // NOI18N
-                return;
-            }
-            if ("/".equals(path) || "index.html".equals(path)) {
-                Reader is;
-                String cmdPrefix = "http://" + server.getServerName(rqst) + ":" + server.getServerPort(rqst) + this.prefix + "/";
-                Writer w = server.getWriter(rspns);
-                server.setContentType(rspns, "text/html");
-                final Command cmd = new Command(server, Browser.this, cmdPrefix);
-                try {
-                    is = new InputStreamReader(page.openStream());
-                } catch (IOException ex) {
-                    w.write("<html><body>");
-                    w.write("<h1>Browser</h1>");
-                    w.write("<pre id='cmd'></pre>");
-                    emitScript(w, cmdPrefix, cmd.id);
-                    w.write("</body></html>");
-                    w.close();
-                    return;
-                }
-                SESSIONS.put(cmd.id, cmd);
-                int state = 0;
-                for (;;) {
-                    int ch = is.read();
-                    if (ch == -1) {
-                        break;
-                    }
-                    char lower = Character.toLowerCase((char)ch);
-                    switch (state) {
-                        case 1000: break;
-                        case 0: if (lower == '<') state = 1; break;
-                        case 1: if (lower == 'b') state = 2;
-                            else if (lower != ' ' && lower != '\n') state = 0;
-                            break;
-                        case 2: if (lower == 'o') state = 3; else state = 0; break;
-                        case 3: if (lower == 'd') state = 4; else state = 0; break;
-                        case 4: if (lower == 'y') state = 5; else state = 0; break;
-                        case 5: if (lower == '>') state = 500;
-                            else if (lower != ' ' && lower != '\n') state = 0;
-                            break;
-                    }
-                    w.write((char)ch);
-                    if (state == 500) {
-                        emitScript(w, cmdPrefix, cmd.id);
-                        state = 1000;
-                    }
-                }
-                if (state != 1000) {
-                    emitScript(w, cmdPrefix, cmd.id);
-                }
-                is.close();
-                w.close();
-            } else if (path.equals("/command.js")) {
-                String id = server.getParameter(rqst, "id");
-                Command c = SESSIONS.get(id);
-                if (c == null) {
-                    server.getWriter(rspns).write("No command for " + id);
-                    server.setStatus(rspns, 404);
-                    return;
-                }
-                c.service(rqst, rspns);
-            } else {
-                if (path.startsWith("/")) {
-                    path = path.substring(1);
-                }
-                URL relative = new URL(page, path);
-                InputStream is;
-                URLConnection conn;
-                try {
-                    conn = relative.openConnection();
-                    is = conn.getInputStream();
-                } catch (FileNotFoundException ex) {
-                    server.setStatus(rspns, 404);
-                    return;
-                }
-                String found = null;
-                if (relative.getProtocol().equals("file")) {
-                    try {
-                        File file = new File(relative.toURI());
-                        found = Files.probeContentType(file.toPath());
-                    } catch (URISyntaxException | IOException ignore) {
-                    }
-                } else {
-                    found = conn.getContentType();
-                }
-                if (found == null || "content/unknown".equals(found)) {
-                    if (path.endsWith(".html")) {
-                        found = "text/html";
-                    }
-                    if (path.endsWith(".js")) {
-                        found = "text/javascript";
-                    }
-                    if (path.endsWith(".css")) {
-                        found = "text/css";
-                    }
-                }
-                if (found != null) {
-                    server.setContentType(rspns, found);
-                }
-                OutputStream out = server.getOutputStream(rspns);
-                for (;;) {
-                    int b = is.read();
-                    if (b == -1) {
-                        break;
-                    }
-                    out.write(b);
-                }
-                out.close();
-                is.close();
-            }
-        }
-
-        private void emitScript(Writer w, String prefix, String id) throws IOException {
-            w.write("  <script id='exec' type='text/javascript'>");
-            w.write("\n"
-                    + "function waitForCommand(counter) {\n"
-                    + "  try {\n"
-                    + "    if (waitForCommand.seenError) {\n"
-                    + "      console.warn('Disconnected from " + prefix + "');\n"
-                    + "      return;\n"
-                    + "    };\n"
-                    + "    var request = new XMLHttpRequest();\n");
-            if (Browser.this.config.debug) {
-                w.write(""
-                    + "    console.log('GET[' + counter + ']....');\n"
-                );
-            }
-            w.write(""
-                    + "    request.open('GET', '" + prefix + "command.js?id=" + id + "', true);\n"
-                    + "    request.setRequestHeader('Content-Type', 'text/plain; charset=utf-8');\n"
-                    + "    request.onerror = function(ev) {\n"
-                    + "      console.warn(ev);\n"
-                    + "      waitForCommand.seenError = true;\n"
-                    + "    };\n"
-                    + "    request.onreadystatechange = function() {\n"
-                    + "      if (this.readyState!==4) return;\n"
-                    + "      try {\n"
-            );
-            if (Browser.this.config.debug) {
-                w.write(""
-                    + "        console.log('...GET[' + counter + '] got something ' + this.responseText.substring(0,80));\n"
-                    + "        var cmd = document.getElementById('cmd');\n"
-                    + "        if (cmd) cmd.innerHTML = this.responseText.substring(0,80);\n"
-                );
-            }
-            w.write(""
-                    + "        (0 || eval)(this.responseText);\n"
-                    + "      } catch (e) {\n"
-                    + "        console.warn(e); \n"
-                    + "      } finally {\n"
-                    + "        waitForCommand(counter + 1);\n"
-                    + "      }\n"
-                    + "    };\n"
-                    + "    request.send();\n"
-                    + "  } catch (e) {\n"
-                    + "    console.warn(e);\n"
-                    + "    waitForCommand(counter + 1);\n"
-                    + "  }\n"
-                    + "}\n"
-                    + "waitForCommand(1);\n"
-            );
-            w.write("  </script>\n");
-        }
-    }
-
-    String createCallbackFn(String prefix, String id) {
-        StringBuilder sb = new StringBuilder();
-        sb.append("this.toBrwsrSrvr = function(name, a1, a2, a3, a4) {\n"
-            + "var url = '").append(prefix).append("command.js?id=").append(id).append("&name=' + name;\n"
-            + "var body = 'p0=' + encodeURIComponent(a1);\n"
-            + "body += '&p1=' + encodeURIComponent(a2);\n"
-            + "body += '&p2=' + encodeURIComponent(a3);\n"
-            + "body += '&p3=' + encodeURIComponent(a4);\n"
-            + "var request = new XMLHttpRequest();\n"
-        );
-        if (Browser.this.config.debug) {
-            sb.append(""
-            + "console.log('PUT ... ' + body.substring(0, 80));\n"
-            + "var now = new Date().getTime();\n"
-            );
-        }
-        sb.append(""
-            + "request.open('PUT', url, false);\n"
-            + "request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');\n"
-            + "request.send(body);\n"
-            + "var txt = request.responseText;\n"
-        );
-        if (Browser.this.config.debug) {
-            sb.append(""
-            + "var then = new Date().getTime();\n"
-            + "if (txt && txt !== 'null') {\n"
-            + "  var cmd = document.getElementById('cmd');\n"
-            + "  if (cmd) cmd.innerHTML = txt.substring(0,80);\n"
-            + "}\n"
-            + "console.log('... PUT [' + (then - now) + 'ms]: ' + txt.substring(0, 80));\n"
-            );
-        }
-        sb.append(""
-            + "return txt;\n"
-            + "};\n"
-        );
-        return sb.toString();
-    }
-
-    private static String findCalleeClassName() {
-        StackTraceElement[] frames = new Exception().getStackTrace();
-        for (StackTraceElement e : frames) {
-            String cn = e.getClassName();
-            if (cn.startsWith("com.dukescript.presenters.")) { // NOI18N
-                continue;
-            }
-            if (cn.startsWith("org.netbeans.html.")) { // NOI18N
-                continue;
-            }
-            if (cn.startsWith("net.java.html.")) { // NOI18N
-                continue;
-            }
-            if (cn.startsWith("java.")) { // NOI18N
-                continue;
-            }
-            if (cn.startsWith("javafx.")) { // NOI18N
-                continue;
-            }
-            if (cn.startsWith("com.sun.")) { // NOI18N
-                continue;
-            }
-            return cn;
-        }
-        return "org.netbeans.html"; // NOI18N
-    }
-
-    private static final class Command<Request, Response, Runner> extends Object
-    implements Executor {
-        private final HttpServer<Request, Response, ?, Runner> server;
-        private final Queue<Object> exec;
-        private final Browser browser;
-        private final String id;
-        private final String prefix;
-        private Runner RUNNER;
-        private Response suspended;
-        private boolean initialized;
-        private final ProtoPresenter presenter;
-
-        Command(HttpServer<Request, Response, ?, Runner> s, Browser browser, String prefix) {
-            this.server = s;
-            this.id = UUID.randomUUID().toString();
-            this.RUNNER = s.initializeRunner(this.id);
-            this.exec = new LinkedList<>();
-            this.prefix = prefix;
-            this.browser = browser;
-            this.presenter = ProtoPresenterBuilder.newBuilder().
-                preparator(this::callbackFn, true).
-                loadJavaScript(this::loadJS, false).
-                app(browser.app).
-                dispatcher(this, true).
-                displayer(this::displayPage).
-                logger(this::log).
-                type("Browser").
-                register(this).
-                build();
-        }
-
-        @Override
-        public final void execute(final Runnable r) {
-            server.runSafe(this.RUNNER, r, this.presenter);
-        }
-
-        final synchronized void add(Object obj) {
-            if (suspended != null) {
-                Response rqst = suspended;
-                server.resume(rqst, () -> {
-                    try (Writer w = server.getWriter(rqst)) {
-                        w.write(obj.toString());
-                    } catch (IOException ex) {
-                        LOG.log(Level.SEVERE, null, ex);
-                    }
-                });
-                suspended = null;
-                return;
-            }
-            exec.add(obj);
-        }
-
-        private synchronized Object take(Response rspns) {
-            Object o = exec.poll();
-            if (o != null) {
-                return o;
-            }
-            suspended = rspns;
-            server.suspend(rspns);
-            return null;
-        }
-
-        private synchronized boolean initialize(Response rspns) {
-            if (!initialized) {
-                initialized = true;
-                suspended = rspns;
-                server.suspend(rspns);
-                execute(browser.onPageLoad);
-                return true;
-            }
-            return false;
-        }
-
-        void service(Request rqst, Response rspns) throws IOException {
-            final String methodName = server.getParameter(rqst, "name");
-            server.setContentType(rspns, "text/javascript");
-            Writer w = server.getWriter(rspns);
-            if (methodName == null) {
-                if (initialize(rspns)) {
-                    return;
-                }
-                // send new request
-                Object obj = take(rspns);
-                if (obj == null) {
-                    LOG.log(Level.FINE, "Suspending response {0}", rspns);
-                    return;
-                }
-                final String s = obj.toString();
-                w.write(s);
-                LOG.log(Level.FINE, "Exec global: {0}", s);
-            } else {
-                List<String> args = new ArrayList<>();
-                String body = server.getBody(rqst);
-                for (String p : body.split("&")) {
-                    if (p.length() >= 3) {
-                        args.add(URLDecoder.decode(p.substring(3), "UTF-8"));
-                    }
-                }
-                String res;
-                try {
-                    LOG.log(Level.FINE, "Call {0}", methodName + " with " + args);
-                    res = presenter.js2java(methodName,
-                        args.get(0), args.get(1), args.get(2), args.get(3)
-                    );
-                    LOG.log(Level.FINE, "Result: {0}", res);
-                } catch (Exception ex) {
-                    res = "error:" + ex.getMessage();
-                }
-                if (res != null) {
-                    w.write(res);
-                } else {
-                    w.write("null");
-                }
-            }
-            w.close();
-        }
-
-        void callbackFn(ProtoPresenterBuilder.OnPrepared onReady) {
-            String sb = this.browser.createCallbackFn(prefix, id);
-            add(sb);
-            onReady.callbackIsPrepared("toBrwsrSrvr");
-        }
-
-        private static Level findLevel(int priority) {
-            if (priority >= Level.SEVERE.intValue()) {
-                return Level.SEVERE;
-            }
-            if (priority >= Level.WARNING.intValue()) {
-                return Level.WARNING;
-            }
-            if (priority >= Level.INFO.intValue()) {
-                return Level.INFO;
-            }
-            return Level.FINE;
-        }
-
-        void log(int priority, String msg, Object... args) {
-            Level level = findLevel(priority);
-
-            if (args.length == 1 && args[0] instanceof Throwable) {
-                LOG.log(level, msg, (Throwable) args[0]);
-            } else {
-                LOG.log(level, msg, args);
-            }
-        }
-
-        final void loadJS(String js) {
-            add(js);
-        }
-
-        void dispatch(Runnable r) {
-            server.runSafe(RUNNER, r, null);
-        }
-
-
-        public void displayPage(URL url, Runnable r) {
-            throw new UnsupportedOperationException(url.toString());
-        }
-    } // end of Command
-}
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/htmlui/Buttons.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/htmlui/Buttons.java
index 279650a8f6..7a205b6d13 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/htmlui/Buttons.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/htmlui/Buttons.java
@@ -29,16 +29,15 @@ public final class Buttons {
     }
 
     @JavaScriptBody(args = {}, body = "\n"
-        + "const vscode = acquireVsCodeApi();\n" // this method can be called only once per WebView existance
         + "window.close = function() {\n"
         + "  vscode.postMessage({\n"
-        + "    command: 'dispose',\n"
+        + "    command: 'dispose'\n"
         + "  });\n"
         + "};\n"
     )
     public static native void registerCloseWindow();
 
-    @JavaScriptBody(args = { "id", "callback" }, javacall = true, body = "\n"
+    @JavaScriptBody(args = { "id", "callback" }, javacall = true, wait4java=false, body = "\n"
             + "var first = false;\n"
             + "var footer = document.getElementById('dialog-buttons');\n"
             + "if (!footer) {\n"
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/htmlui/HttpServer.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/htmlui/HttpServer.java
deleted file mode 100644
index bd24cd5363..0000000000
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/htmlui/HttpServer.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.netbeans.modules.java.lsp.server.htmlui;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.Writer;
-import org.netbeans.html.boot.spi.Fn;
-
-abstract class HttpServer<Request, Response, WebSocket, Runner> {
-    abstract void init(int from, int to) throws IOException;
-    abstract void start() throws IOException;
-    abstract void shutdownNow();
-    abstract void addHttpHandler(Handler h, String path);
-    abstract int getPort();
-
-    abstract String getRequestURI(Request r);
-    abstract String getServerName(Request r);
-    abstract int getServerPort(Request r);
-    abstract String getParameter(Request r, String id);
-    abstract String getMethod(Request r);
-    abstract String getBody(Request r) throws IOException;
-    abstract String getHeader(Request r, String substring);
-
-    abstract Writer getWriter(Response r);
-    abstract void setContentType(Response r, String texthtml);
-    abstract void setStatus(Response r, int i);
-    abstract OutputStream getOutputStream(Response r);
-    abstract void suspend(Response r);
-    abstract void resume(Response r, Runnable runWhenResponseIsReady);
-    abstract void setCharacterEncoding(Response r, String utF8);
-    abstract void addHeader(Response r, String accessControlAllowOrigin, String string);
-
-    abstract <WebSocket> void send(WebSocket socket, String s);
-
-    abstract Runner initializeRunner(String id);
-    abstract void runSafe(Runner runner, Runnable code, Fn.Presenter presenter);
-
-    abstract static class Handler {
-        abstract <Request, Response> void service(HttpServer<Request, Response, ?, ?> server, Request rqst, Response rspns) throws IOException;
-    }
-
-    abstract static class WebSocketApplication {
-        abstract <WebSocket> void onMessage(HttpServer<?, ?, WebSocket, ?> server, WebSocket socket, String text);
-    }
-}
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/htmlui/SimpleServer.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/htmlui/SimpleServer.java
deleted file mode 100644
index 16387fc217..0000000000
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/htmlui/SimpleServer.java
+++ /dev/null
@@ -1,712 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.netbeans.modules.java.lsp.server.htmlui;
-
-import java.io.ByteArrayOutputStream;
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.UnsupportedEncodingException;
-import java.io.Writer;
-import java.net.InetSocketAddress;
-import java.net.URLDecoder;
-import java.nio.Buffer;
-import java.nio.ByteBuffer;
-import java.nio.channels.ClosedByInterruptException;
-import java.nio.channels.SelectionKey;
-import java.nio.channels.Selector;
-import java.nio.channels.ServerSocketChannel;
-import java.nio.channels.SocketChannel;
-import java.nio.charset.StandardCharsets;
-import java.text.DateFormat;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-import java.util.TimeZone;
-import java.util.TreeMap;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.netbeans.html.boot.spi.Fn;
-
-final class SimpleServer extends HttpServer<SimpleServer.ReqRes, SimpleServer.ReqRes, Object, SimpleServer.Context> {
-    private final Map<String, Handler> maps = new TreeMap<>((s1, s2) -> {
-        if (s1.length() != s2.length()) {
-            return s2.length() - s1.length();
-        }
-        return s2.compareTo(s1);
-    });
-    private int max;
-    private int min;
-    /**
-     * @GuardedBy("this")
-     */
-    private ServerSocketChannel server;
-    /**
-     * @GuardedBy("this")
-     */
-    private Selector connection;
-    /**
-     * @GuardedBy("this")
-     */
-    private Thread processor;
-    private final List<Runnable> pendingActions = new ArrayList<>();
-
-    private static final Pattern PATTERN_GET = Pattern.compile("(OPTIONS|HEAD|GET|POST|PUT|DELETE) */([^ \\?]*)(\\?[^ ]*)?");
-    private static final Pattern PATTERN_HOST = Pattern.compile(".*^Host: *(.*):([0-9]+)$", Pattern.MULTILINE);
-    private static final Pattern PATTERN_LENGTH = Pattern.compile(".*^Content-Length: ([0-9]+)$", Pattern.MULTILINE);
-    static final Logger LOG = Logger.getLogger(SimpleServer.class.getName());
-
-    private final Random random;
-
-    SimpleServer() {
-        this(new Random());
-    }
-
-    SimpleServer(Random random) {
-        this.random = random;
-    }
-
-    @Override
-    void addHttpHandler(Handler h, String path) {
-        if (!path.startsWith("/")) {
-            throw new IllegalStateException("Shall start with /: " + path);
-        }
-        maps.put(path.substring(1), h);
-    }
-
-    @Override
-    void init(int from, int to) throws IOException {
-        this.connection = Selector.open();
-        this.min = from;
-        this.max = to;
-    }
-
-    @Override
-    synchronized void start() throws IOException {
-        LOG.log(Level.INFO, "Listening for HTTP connections on port {0}", getServer().socket().getLocalPort());
-        processor = new Thread(this::mainLoop, "HTTP server");
-        processor.start();
-    }
-
-    private final synchronized Thread getProcessorThread() {
-        return processor;
-    }
-
-    final void assertThread() {
-        assert Thread.currentThread() == getProcessorThread();
-    }
-
-    @Override
-    String getRequestURI(ReqRes r) {
-        assertThread();
-        return "/" + r.url;
-    }
-
-    @Override
-    String getServerName(ReqRes r) {
-        assertThread();
-        return r.hostName;
-    }
-
-    @Override
-    int getServerPort(ReqRes r) {
-        assertThread();
-        return r.hostPort;
-    }
-
-    @Override
-    String getParameter(ReqRes r, String id) {
-        assertThread();
-        return (String) r.args.get(id);
-    }
-
-    @Override
-    String getMethod(ReqRes r) {
-        assertThread();
-        return r.method;
-    }
-
-    @Override
-    String getBody(ReqRes r) {
-        assertThread();
-        if (r.body == null) {
-            return "";
-        } else {
-            return new String(r.body.array(), StandardCharsets.UTF_8);
-        }
-    }
-
-    static int endOfHeader(String header) {
-        return header.indexOf("\r\n\r\n");
-    }
-
-    @Override
-    String getHeader(ReqRes r, String key) {
-        assertThread();
-        for (String l : r.header.split("\r\n")) {
-            if (l.isEmpty()) {
-                break;
-            }
-            if (l.startsWith(key + ":")) {
-                return l.substring(key.length() + 1).trim();
-            }
-        }
-        return null;
-    }
-
-    @Override
-    Writer getWriter(ReqRes r) {
-        assertThread();
-        return r.writer;
-    }
-
-    @Override
-    void setContentType(ReqRes r, String contentType) {
-        assertThread();
-        r.contentType = contentType;
-    }
-
-    @Override
-    void setStatus(ReqRes r, int status) {
-        assertThread();
-        r.status = status;
-    }
-
-    @Override
-    OutputStream getOutputStream(ReqRes r) {
-        assertThread();
-        return r.os;
-    }
-
-    @Override
-    void suspend(ReqRes r) {
-        assertThread();
-        r.suspended = true;
-        r.updateOperations();
-    }
-
-    @Override
-    void resume(ReqRes r, Runnable whenReady) {
-        connectionWakeup(() -> {
-            assertThread();
-            r.suspended = false;
-            r.updateOperations();
-            whenReady.run();
-        });
-    }
-
-    @Override
-    void setCharacterEncoding(ReqRes r, String encoding) {
-        if (!encoding.equals("UTF-8")) {
-            throw new IllegalStateException(encoding);
-        }
-    }
-
-    @Override
-    void addHeader(ReqRes r, String name, String value) {
-        assertThread();
-        r.headers.put(name, value);
-    }
-
-    @Override
-    <WebSocket> void send(WebSocket socket, String s) {
-    }
-
-    /**
-     * @return the port to listen to
-     */
-    @Override
-    public int getPort() {
-        try {
-            return getServer().socket().getLocalPort();
-        } catch (IOException ex) {
-            return -1;
-        }
-    }
-
-    synchronized void connectionWakeup(Runnable runOnMainLoop) {
-        Selector localConnection = this.connection;
-        this.pendingActions.add(runOnMainLoop);
-        if (localConnection != null) {
-            localConnection.wakeup();
-        }
-    }
-
-    private void mainLoop() {
-        ByteBuffer bb = ByteBuffer.allocate(2048);
-        while (Thread.currentThread() == getProcessorThread()) {
-            ServerSocketChannel localServer;
-            Selector localConnection;
-            Runnable[] pendings;
-
-            SocketChannel toClose = null;
-            try {
-                synchronized (this) {
-                    localServer = this.getServer();
-                    localConnection = this.connection;
-                    pendings = this.pendingActions.toArray(new Runnable[0]);
-                    this.pendingActions.clear();
-                }
-
-                LOG.log(Level.FINEST, "Before select status: open server{0}, open connection {1}, pending {2}",
-                        new Object[]{localServer.isOpen(), localConnection.isOpen(), pendings.length}
-                );
-
-                for (Runnable r : pendings) {
-                    r.run();
-                }
-
-                int amount = localConnection.select();
-
-                LOG.log(Level.FINEST, "After select: {0}", amount);
-                if (amount == 0) {
-                    LOG.log(Level.FINE, "No amount after select: {0}", amount);
-                }
-
-                Set<SelectionKey> readyKeys = localConnection.selectedKeys();
-                Iterator<SelectionKey> it = readyKeys.iterator();
-                while (it.hasNext()) {
-                    SelectionKey key = it.next();
-                    LOG.log(Level.FINEST, "Handling key {0}", key.attachment());
-                    it.remove();
-
-                    if (key.isAcceptable()) {
-                        try {
-                            SocketChannel channel = localServer.accept();
-                            channel.configureBlocking(false);
-                            SelectionKey another = channel.register(
-                                    localConnection, SelectionKey.OP_READ
-                            );
-                            another.attach(new ReadHeader());
-                        } catch (ClosedByInterruptException ex) {
-                            LOG.log(Level.WARNING, "Interrupted while accepting", ex);
-                            server.close();
-                            server = null;
-                            LOG.log(Level.INFO, "Accept server reset");
-                        }
-                    } else if (key.isReadable()) {
-                        ((Buffer) bb).clear();
-                        SocketChannel channel = (SocketChannel) key.channel();
-                        toClose = channel;
-                        channel.read(bb);
-                        ((Buffer) bb).flip();
-
-                        if (key.attachment() instanceof ReadHeader) {
-                            ReadHeader readHeader = (ReadHeader) key.attachment();
-                            ReqRes nextKey = readHeader.process(key, bb);
-                            if (nextKey != null) {
-                                key.attach(nextKey);
-                                nextKey.updateOperations();
-                            }
-                        } else if (key.attachment() instanceof ReqRes) {
-                            ReqRes req = (ReqRes) key.attachment();
-                            req.readBody(key, bb);
-                            req.updateOperations();
-                        }
-                    } else if (key.isWritable()) {
-                        SocketChannel channel = (SocketChannel) key.channel();
-                        toClose = channel;
-                        if (key.attachment() instanceof ReqRes) {
-                            ReqRes request = (ReqRes) key.attachment();
-                            WriteReply write = request.handle(channel);
-                            if (write != null) {
-                                key.attach(write);
-                                write.updateOperations();
-                            }
-                        } else if (key.attachment() instanceof WriteReply) {
-                            WriteReply write = (WriteReply) key.attachment();
-                            write.output(channel);
-                        }
-                    }
-                }
-            } catch (ThreadDeath td) {
-                throw td;
-            } catch (Throwable t) {
-                LOG.log(Level.SEVERE, "Exception while handling request", t);
-                if (toClose != null) {
-                    try {
-                        toClose.close();
-                    } catch (IOException ioEx) {
-                        LOG.log(Level.INFO, "While closing", ioEx);
-                    }
-                }
-            }
-        }
-
-        synchronized (this) {
-            try {
-                LOG.fine("Closing connection");
-                this.connection.close();
-                LOG.fine("Closing server");
-                this.getServer().close();
-            } catch (IOException ex) {
-                LOG.log(Level.WARNING, null, ex);
-            } finally {
-                notifyAll();
-            }
-        }
-        LOG.fine("All notified, exiting server");
-    }
-
-    private Handler findHandler(String url) {
-        LOG.log(Level.FINE, "Searching for handler for page {0}", url);
-        for (Map.Entry<String, Handler> entry : maps.entrySet()) {
-            if (url.startsWith(entry.getKey())) {
-                return entry.getValue();
-            }
-        }
-        throw new IllegalStateException("No mapping for " + url + " among " + maps);
-    }
-
-    private static void parseArgs(final Map<String, ? super String> context, final String args) throws UnsupportedEncodingException {
-        if (args != null) {
-            for (String arg : args.substring(1).split("&")) {
-                String[] valueAndKey = arg.split("=");
-                if (valueAndKey.length != 2) {
-                    continue;
-                }
-
-                String key = URLDecoder.decode(valueAndKey[1], "US-ASCII");
-                for (int idx = 0;;) {
-                    idx = key.indexOf("%", idx);
-                    if (idx == -1) {
-                        break;
-                    }
-                    int ch = Integer.parseInt(key.substring(idx + 1, idx + 3), 16);
-                    key = key.substring(0, idx) + (char) ch + key.substring(idx + 3);
-                    idx++;
-                }
-
-                context.put(valueAndKey[0], key);
-            }
-        }
-    }
-
-    @Override
-    public synchronized void shutdownNow() {
-        Thread inter = processor;
-        if (inter != null) {
-            processor = null;
-            LOG.fine("Processor cleaned");
-            inter.interrupt();
-            LOG.fine("Processor interrupted");
-            try {
-                wait(5000);
-            } catch (InterruptedException ex) {
-                LOG.log(Level.WARNING, null, ex);
-            }
-            LOG.fine("After waiting");
-        }
-    }
-
-    /**
-     * Computes todays's date .
-     */
-    static String date(Date date) {
-        return date("Date: ", date != null ? date : new Date());
-    }
-
-    static String date(String prefix, Date date) {
-        DateFormat f = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.US);
-        f.setTimeZone(TimeZone.getTimeZone("GMT")); // NOI18N
-        return prefix + f.format(date);
-    }
-
-    public synchronized ServerSocketChannel getServer() throws IOException {
-        if (server == null) {
-            ServerSocketChannel s = ServerSocketChannel.open();
-            s.configureBlocking(false);
-
-            for (int i = min; i <= max; i++) {
-                int at = min + random.nextInt(max - min + 1);
-                InetSocketAddress address = new InetSocketAddress(at);
-                try {
-                    s.socket().bind(address);
-                } catch (IOException ex) {
-                    LOG.log(Level.FINE, "Cannot bind to " + at, ex);
-                    continue;
-                }
-                server = s;
-                break;
-            }
-
-            server.register(this.connection, SelectionKey.OP_ACCEPT);
-        }
-        return server;
-    }
-
-    final class Context implements ThreadFactory {
-
-        private final String id;
-        Executor RUN;
-        Thread RUNNER;
-
-        Context(String id) {
-            this.id = id;
-        }
-
-        @Override
-        public Thread newThread(Runnable r) {
-            Thread t = new Thread(r, "Processor for " + id);
-            RUNNER = t;
-            return t;
-        }
-    }
-
-    @Override
-    Context initializeRunner(String id) {
-        Context c = new Context(id);
-        c.RUN = Executors.newSingleThreadExecutor(c);
-        return c;
-    }
-
-    @Override
-    void runSafe(Context c, Runnable r, Fn.Presenter presenter) {
-        class Wrap implements Runnable {
-
-            @Override
-            public void run() {
-                if (presenter != null) {
-                    try ( Closeable c = Fn.activate(presenter)) {
-                        r.run();
-                    } catch (IOException ex) {
-                        // go on
-                    }
-                } else {
-                    r.run();
-                }
-            }
-        }
-        if (c.RUNNER == Thread.currentThread()) {
-            if (presenter != null) {
-                Runnable w = new Wrap();
-                w.run();
-            } else {
-                r.run();
-            }
-        } else {
-            Runnable w = new Wrap();
-            c.RUN.execute(w);
-        }
-    }
-
-    final class ReadHeader {
-
-        private final StringBuilder buffer = new StringBuilder();
-
-        final ReqRes process(SelectionKey key, ByteBuffer chunk) throws UnsupportedEncodingException {
-            String text = new String(chunk.array(), 0, chunk.limit(), StandardCharsets.US_ASCII);
-            buffer.append(text);
-            int fullHeader = buffer.indexOf("\r\n\r\n");
-            if (fullHeader == -1) {
-                return null;
-            }
-            String header = text.substring(0, fullHeader);
-
-            Matcher m = PATTERN_GET.matcher(header);
-            String url = m.find() ? m.group(2) : null;
-            String args = url != null && m.groupCount() == 3 ? m.group(3) : null;
-            String method = m.group(1);
-
-            Map<String, String> context;
-            if (args != null) {
-                Map<String, String> c = new HashMap<>();
-                parseArgs(c, args);
-                context = Collections.unmodifiableMap(c);
-            } else {
-                context = Collections.emptyMap();
-            }
-
-            Matcher length = PATTERN_LENGTH.matcher(header);
-            ByteBuffer body = null;
-            if (length.find()) {
-                int contentLength = Integer.parseInt(length.group(1));
-                body = ByteBuffer.allocate(contentLength);
-                ((Buffer) chunk).position(fullHeader + 4);
-                body.put(chunk);
-            }
-
-            Handler h = findHandler(url);
-            Matcher hostMatch = PATTERN_HOST.matcher(header);
-            String host = null;
-            int port = -1;
-            if (hostMatch.find()) {
-                host = hostMatch.group(1);
-                port = Integer.parseInt(hostMatch.group(2));
-            }
-            if (host != null) {
-                LOG.log(Level.FINER, "Host {0}:{1}", new Object[]{host, port});
-            }
-            return new ReqRes(h, key, url, context, host, port, header, method, body);
-        }
-    }
-
-    final class ReqRes {
-
-        private final SelectionKey delegate;
-        private final Handler h;
-        final String url;
-        final String hostName;
-        final int hostPort;
-        final Map<String, String> args;
-        final String header;
-        final String method;
-        final ByteBuffer body;
-        private final ByteArrayOutputStream os = new ByteArrayOutputStream();
-        final Writer writer = new OutputStreamWriter(os, StandardCharsets.UTF_8);
-        final Map<String, String> headers = new LinkedHashMap<>();
-        String contentType;
-        int status = 200;
-        boolean computed;
-        boolean suspended;
-
-        public ReqRes(
-                Handler h, SelectionKey delegate,
-                String url, Map<String, String> args, String host,
-                int port, String header, String method, ByteBuffer body
-        ) {
-            this.h = h;
-            this.delegate = delegate;
-            this.url = url;
-            this.hostName = host;
-            this.hostPort = port;
-            this.header = header;
-            this.args = args;
-            this.method = method;
-            this.body = body;
-        }
-
-        void updateOperations() {
-            if (body != null && body.remaining() > 0) {
-                delegate.interestOps(SelectionKey.OP_READ);
-            } else if (suspended) {
-                delegate.interestOps(0);
-            } else {
-                delegate.interestOps(SelectionKey.OP_WRITE);
-            }
-        }
-
-        public WriteReply handle(SocketChannel channel) throws IOException {
-            if (!computed) {
-                computed = true;
-                h.service(SimpleServer.this, this, this);
-            }
-            if (suspended) {
-                channel.write(ByteBuffer.allocate(0));
-                return null;
-            }
-
-            if (contentType == null) {
-                contentType = "content/unknown"; // NOI18N
-            }
-
-            ByteBuffer bb = ByteBuffer.allocate(8192);
-            ((Buffer) bb).clear();
-
-            LOG.log(Level.FINE, "Serving page request {0}", url); // NOI18N
-            ((Buffer) bb).clear();
-            putString(bb, "HTTP/1.1 " + status + "\r\n");
-            putString(bb, "Connection: close\r\n");
-            putString(bb, "Server: Browser presenter\r\n");
-            putString(bb, date(null));
-            putString(bb, "\r\n");
-            putString(bb, "Content-Type: " + contentType + "\r\n");
-            for (Map.Entry<String, String> entry : headers.entrySet()) {
-                putString(bb, entry.getKey() + ":" + entry.getValue() + "\r\n");
-            }
-            putString(bb, "Pragma: no-cache\r\nCache-control: no-cache\r\n");
-            putString(bb, "\r\n");
-            ((Buffer) bb).flip();
-
-            return new WriteReply(delegate, url, bb, ByteBuffer.wrap(toByteArray()));
-        }
-
-        byte[] toByteArray() throws IOException {
-            writer.close();
-            return os.toByteArray();
-        }
-
-        void readBody(SelectionKey key, ByteBuffer chunk) {
-            body.put(chunk);
-        }
-
-        @Override
-        public String toString() {
-            return "Request[" + method + ":" + url + "]";
-        }
-    }
-
-    final class WriteReply {
-
-        private final SelectionKey delegate;
-        private final String url;
-        private final ByteBuffer header;
-        private final ByteBuffer body;
-
-        WriteReply(SelectionKey delegate, String url, ByteBuffer header, ByteBuffer body) {
-            this.delegate = delegate;
-            this.url = url;
-            this.header = header;
-            this.body = body;
-        }
-
-        void updateOperations() {
-            delegate.interestOps(SelectionKey.OP_WRITE);
-        }
-
-        void output(SocketChannel channel) throws IOException {
-            try {
-                if (header.remaining() > 0) {
-                    channel.write(header);
-                    return;
-                }
-                if (body.remaining() > 0) {
-                    channel.write(body);
-                } else {
-                    channel.close();
-                }
-            } finally {
-                if (!channel.isOpen()) {
-                    LOG.log(Level.FINE, "channel for {0} not open, closing", url);
-                    delegate.attach(null);
-                    delegate.cancel();
-                }
-            }
-
-        }
-    }
-
-    private static void putString(ByteBuffer bb, String text) throws UnsupportedEncodingException {
-        bb.put(text.getBytes(StandardCharsets.US_ASCII));
-    }
-}
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/htmlui/WebView.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/htmlui/WebView.java
new file mode 100644
index 0000000000..799fc21f98
--- /dev/null
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/htmlui/WebView.java
@@ -0,0 +1,401 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.java.lsp.server.htmlui;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.function.Consumer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.eclipse.lsp4j.CodeAction;
+import org.eclipse.lsp4j.CodeActionParams;
+import org.netbeans.html.boot.spi.Fn;
+import org.netbeans.html.presenters.spi.ProtoPresenter;
+import org.netbeans.html.presenters.spi.ProtoPresenterBuilder;
+import org.netbeans.modules.java.lsp.server.protocol.CodeActionsProvider;
+import org.netbeans.modules.java.lsp.server.protocol.HtmlPageParams;
+import org.netbeans.modules.java.lsp.server.protocol.NbCodeLanguageClient;
+import org.netbeans.modules.parsing.api.ResultIterator;
+import org.netbeans.spi.htmlui.HTMLViewerSpi;
+import org.openide.util.Exceptions;
+import org.openide.util.lookup.ServiceProvider;
+
+public class WebView implements Closeable {
+
+    private static final Logger LOG = Logger.getLogger(WebView.class.getName());
+
+    private final Consumer<Page> viewer;
+    private final String app;
+    private Runnable onPageLoad;
+    private String id;
+
+    public WebView(Consumer<Page> viewer) {
+        this.viewer = viewer;
+        this.app = findCalleeClassName();
+    }
+
+    public void displayPage(HTMLViewerSpi.Context ctx) {
+        try {
+            this.onPageLoad = () -> {
+                Buttons.registerCloseWindow();
+                try {
+                    ctx.onPageLoad();
+                } catch (Exception ex) {
+                    Exceptions.printStackTrace(ex);
+                }
+            };
+            this.id = UUID.randomUUID().toString();
+            Server.SESSIONS.put(this.id, new Command(this));
+            this.viewer.accept(new Page(this.id, getText(ctx.getPage(), this.id), getResources(ctx.getPage(), ctx.getResources())));
+        } catch (IOException ex) {
+            Logger.getLogger(WebView.class.getName()).log(Level.SEVERE, null, ex);
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        Server.SESSIONS.remove(this.id);
+    }
+
+    private String getText(URL page, String id) throws IOException {
+        StringBuilder sb = new StringBuilder();
+        try (Reader is = new InputStreamReader(page.openStream())) {
+            int state = id != null ? 0 : 1000;
+            for (;;) {
+                int ch = is.read();
+                if (ch == -1) {
+                    break;
+                }
+                char lower = Character.toLowerCase((char)ch);
+                switch (state) {
+                    case 1000: break;
+                    case 0: if (lower == '<') state = 1; break;
+                    case 1: if (lower == 'b') state = 2;
+                        else if (lower != ' ' && lower != '\n') state = 0;
+                        break;
+                    case 2: if (lower == 'o') state = 3; else state = 0; break;
+                    case 3: if (lower == 'd') state = 4; else state = 0; break;
+                    case 4: if (lower == 'y') state = 5; else state = 0; break;
+                    case 5: if (lower == '>') state = 500;
+                        else if (lower != ' ' && lower != '\n') state = 0;
+                        break;
+                }
+                sb.append((char)ch);
+                if (state == 500) {
+                    emitScript(sb, id);
+                    state = 1000;
+                }
+            }
+            if (state != 1000) {
+                emitScript(sb, id);
+            }
+        }
+        return sb.toString();
+    }
+
+    private void emitScript(StringBuilder sb, String id) throws IOException {
+        
+        sb.append("<script id='exec' type='text/javascript'>\n"
+                + "const vscode = acquireVsCodeApi();\n"
+                + "(function () {\n"
+                + "  window.addEventListener('message', new Function('event', `\n"
+                + "    const message = event.data;\n"
+                + "    if (message.pause) {\n"
+                + "      debugger;\n"
+                + "    }\n"
+                + "    if (message.execScript) {\n"
+                + "      try {\n"
+                + "        (0 || eval)(message.execScript);\n"
+                + "      } catch (e) {\n"
+                + "        console.warn(e); \n"
+                + "      }\n"
+                + "    }\n"
+                + "  `));\n"
+                + "  vscode.postMessage({\n"
+                + "    command: 'command',\n"
+                + "    data: {\n"
+                + "      id: '" + id + "'\n"
+                + "    }\n"
+                + "  });\n"
+                + "}());\n"
+                + "</script>\n");
+    }
+
+    private Map<String, String> getResources(URL page, String[] resources) throws IOException {
+        Map<String, String> ret = new HashMap<>();
+        for (String resource : resources) {
+            ret.put(resource, getText(new URL(page, resource), null));
+        }
+        return ret;
+    }
+
+    private String createCallbackFn(String id) {
+        return "this.toBrwsrSrvr = function(name, a1, a2, a3, a4) {\n"
+             + "  vscode.postMessage({\n"
+             + "    command: 'command',\n"
+             + "    data: {\n"
+             + "      id: '" + id + "',\n"
+             + "      name,\n"
+             + "      p0: encodeURIComponent(a1),\n"
+             + "      p1: encodeURIComponent(a2),\n"
+             + "      p2: encodeURIComponent(a3),\n"
+             + "      p3: encodeURIComponent(a4)\n"
+             + "    }"
+             + "  });\n"
+             + "  return '';\n"
+             + "};\n";
+    }
+
+    private static String findCalleeClassName() {
+        StackTraceElement[] frames = new Exception().getStackTrace();
+        for (StackTraceElement e : frames) {
+            String cn = e.getClassName();
+            if (cn.startsWith("com.dukescript.presenters.")) { // NOI18N
+                continue;
+            }
+            if (cn.startsWith("org.netbeans.html.")) { // NOI18N
+                continue;
+            }
+            if (cn.startsWith("net.java.html.")) { // NOI18N
+                continue;
+            }
+            if (cn.startsWith("java.")) { // NOI18N
+                continue;
+            }
+            if (cn.startsWith("javafx.")) { // NOI18N
+                continue;
+            }
+            if (cn.startsWith("com.sun.")) { // NOI18N
+                continue;
+            }
+            return cn;
+        }
+        return "org.netbeans.html"; // NOI18N
+    }
+
+    public static final class Page {
+        private final String id;
+        private final String text;
+        private final Map<String, String> resources;
+
+        private Page(String id, String text, Map<String, String> resources) {
+            this.id = id;
+            this.text = text;
+            this.resources = resources;
+        }
+
+        public String getId() {
+            return id;
+        }
+
+        public String getText() {
+            return text;
+        }
+
+        public Map<String, String> getResources() {
+            return resources;
+        }
+    }
+
+    private static final class Command implements Executor, ThreadFactory {
+        private final WebView webView;
+        private final String id;
+        private final Executor RUN;
+        private Thread RUNNER;
+        private NbCodeLanguageClient client;
+        private final ProtoPresenter presenter;
+
+        private Command(WebView webView) {
+            this.webView = webView;
+            this.id = this.webView.id;
+            this.RUN = Executors.newSingleThreadExecutor(this);
+            this.presenter = ProtoPresenterBuilder.newBuilder().
+                preparator(this::callbackFn, true).
+                loadJavaScript(this::loadJS, false).
+                app(webView.app).
+                dispatcher(this, true).
+                displayer(this::displayPage).
+                logger(this::log).
+                type("Browser").
+                register(this).
+                build();
+        }
+
+        @Override
+        public void execute(final Runnable r) {
+            runSafe(r, this.presenter);
+        }
+
+        @Override
+        public Thread newThread(Runnable r) {
+            Thread t = new Thread(r, "Processor for " + id);
+            RUNNER = t;
+            return t;
+        }
+
+        private void execScript(String obj) {
+            client.execInHtmlPage(new HtmlPageParams(id, obj));
+        }
+
+        private void initialize(NbCodeLanguageClient client) {
+            if (this.client == null) {
+                this.client = client;
+                execute(webView.onPageLoad);
+            }
+        }
+
+        private CompletableFuture<Object> service(NbCodeLanguageClient client, Map params) {
+            CompletableFuture future = new CompletableFuture();
+            final String methodName = (String) params.get("name");
+            if (methodName == null) {
+                initialize(client);
+                future.complete(null);
+            } else {
+                try {
+                    final String result = presenter.js2java(methodName,
+                            URLDecoder.decode((String) params.get("p0"), "UTF-8"),
+                            URLDecoder.decode((String) params.get("p1"), "UTF-8"),
+                            URLDecoder.decode((String) params.get("p2"), "UTF-8"),
+                            URLDecoder.decode((String) params.get("p3"), "UTF-8"));
+                    future.complete(result);
+                } catch (Exception ex) {
+                    future.complete("error:" + ex.getMessage());
+                }
+            }
+            return future;
+        }
+
+        private void callbackFn(ProtoPresenterBuilder.OnPrepared onReady) {
+            String sb = this.webView.createCallbackFn(id);
+            execScript(sb);
+            onReady.callbackIsPrepared("toBrwsrSrvr");
+        }
+
+        private void log(int priority, String msg, Object... args) {
+            Level level = findLevel(priority);
+
+            if (args.length == 1 && args[0] instanceof Throwable) {
+                LOG.log(level, msg, (Throwable) args[0]);
+            } else {
+                LOG.log(level, msg, args);
+            }
+        }
+
+        private void loadJS(String js) {
+            execScript(js);
+        }
+
+        private void displayPage(URL url, Runnable r) {
+            throw new UnsupportedOperationException(url.toString());
+        }
+
+        private void runSafe(Runnable r, Fn.Presenter p) {
+            class Wrap implements Runnable {
+
+                @Override
+                public void run() {
+                    if (p != null) {
+                        try ( Closeable c = Fn.activate(p)) {
+                            r.run();
+                        } catch (IOException ex) {
+                            // go on
+                        }
+                    } else {
+                        r.run();
+                    }
+                }
+            }
+            if (RUNNER == Thread.currentThread()) {
+                if (p != null) {
+                    Runnable w = new Wrap();
+                    w.run();
+                } else {
+                    r.run();
+                }
+            } else {
+                Runnable w = new Wrap();
+                RUN.execute(w);
+            }
+        }
+
+        private static Level findLevel(int priority) {
+            if (priority >= Level.SEVERE.intValue()) {
+                return Level.SEVERE;
+            }
+            if (priority >= Level.WARNING.intValue()) {
+                return Level.WARNING;
+            }
+            if (priority >= Level.INFO.intValue()) {
+                return Level.INFO;
+            }
+            return Level.FINE;
+        }
+    } // end of Command
+
+    @ServiceProvider(service = CodeActionsProvider.class)
+    public static final class Server extends CodeActionsProvider {
+
+        private static final Map<String, WebView.Command> SESSIONS = new HashMap<>();
+        private static final String PROCESS_COMMAND = "nb.htmlui.process.command"; // NOI18N
+        private static final String ID = "id"; // NOI18N
+        private final Gson gson = new Gson();
+
+        @Override
+        public Set<String> getCommands() {
+            return Collections.singleton(PROCESS_COMMAND);
+        }
+
+        @Override
+        public CompletableFuture<Object> processCommand(NbCodeLanguageClient client, String command, List<Object> arguments) {
+            if (PROCESS_COMMAND.equals(command) && arguments != null && !arguments.isEmpty()) {
+                final Map m = gson.fromJson((JsonObject) arguments.get(0), Map.class);
+                final String id = (String) m.get(ID);
+                if (id != null) {
+                    WebView.Command c = SESSIONS.get(id);
+                    if (c != null) {
+                        return c.service(client, m).thenApply(res -> res != null ? res : "null");
+                    }
+                }
+            }
+            return CompletableFuture.completedFuture(null);
+        }
+
+        @Override
+        public List<CodeAction> getCodeActions(ResultIterator resultIterator, CodeActionParams params) throws Exception {
+            return Collections.emptyList();
+        }
+    } // end of Server
+}
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/DebugConnector.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/DebugConnector.java
index 52cbd31201..34bd792317 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/DebugConnector.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/DebugConnector.java
@@ -67,6 +67,9 @@ public final class DebugConnector {
     @NonNull
     private List<String> descriptions;
 
+    public DebugConnector() {
+    }
+
     public DebugConnector(String id, String name, String type, List<String> arguments, List<String> defaultValues, List<String> descriptions) {
         this.id = id;
         this.name = name;
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/HtmlPageParams.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/HtmlPageParams.java
index cf037d5444..5147d20830 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/HtmlPageParams.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/HtmlPageParams.java
@@ -18,23 +18,57 @@
  */
 package org.netbeans.modules.java.lsp.server.protocol;
 
+import java.util.Map;
 import java.util.Objects;
 import org.eclipse.xtext.xbase.lib.Pure;
 
 public class HtmlPageParams  {
-    private String uri;
+    private String id;
+    private String text;
+    private boolean pause;
+    private Map<String, String> resources;
 
-    public HtmlPageParams(String uri) {
-        this.uri = uri;
+    public HtmlPageParams(String id, String text) {
+        this.id = id;
+        this.text = text;
     }
 
     @Pure
-    public String getUri() {
-        return uri;
+    public String getId() {
+        return id;
     }
 
-    public HtmlPageParams setUri(String uri) {
-        this.uri = uri;
+    public HtmlPageParams setId(String id) {
+        this.id = id;
+        return this;
+    }
+
+    @Pure
+    public boolean isPause() {
+        return pause;
+    }
+
+    public void setPause(boolean pause) {
+        this.pause = pause;
+    }
+
+    @Pure
+    public String getText() {
+        return text;
+    }
+
+    public HtmlPageParams setText(String text) {
+        this.text = text;
+        return this;
+    }
+
+    @Pure
+    public Map<String, String> getResources() {
+        return resources;
+    }
+
+    public HtmlPageParams setResources(Map<String, String> resources) {
+        this.resources = resources;
         return this;
     }
 
@@ -42,7 +76,10 @@ public class HtmlPageParams  {
     @Override
     public int hashCode() {
         int hash = 5;
-        hash = 83 * hash + Objects.hashCode(this.uri);
+        hash = 83 * hash + Objects.hashCode(this.id);
+        hash = 83 * hash + Objects.hashCode(this.text);
+        hash = 83 * hash + Objects.hashCode(this.pause);
+        hash = 83 * hash + Objects.hashCode(this.resources);
         return hash;
     }
 
@@ -59,7 +96,16 @@ public class HtmlPageParams  {
             return false;
         }
         final HtmlPageParams other = (HtmlPageParams) obj;
-        if (!Objects.equals(this.uri, other.uri)) {
+        if (!Objects.equals(this.id, other.id)) {
+            return false;
+        }
+        if (this.pause != other.pause) {
+            return false;
+        }
+        if (!Objects.equals(this.text, other.text)) {
+            return false;
+        }
+        if (!Objects.equals(this.resources, other.resources)) {
             return false;
         }
         return true;
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/NbCodeClientWrapper.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/NbCodeClientWrapper.java
index 1c9b2b11c6..a11588d2b2 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/NbCodeClientWrapper.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/NbCodeClientWrapper.java
@@ -79,6 +79,11 @@ class NbCodeClientWrapper implements NbCodeLanguageClient {
         return remote.showHtmlPage(params);
     }
 
+    @Override
+    public CompletableFuture<String> execInHtmlPage(HtmlPageParams params) {
+        return remote.execInHtmlPage(params);
+    }
+
     @Override
     public CompletableFuture<List<QuickPickItem>> showQuickPick(ShowQuickPickParams params) {
         return remote.showQuickPick(params);
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/NbCodeLanguageClient.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/NbCodeLanguageClient.java
index aac9970f41..42fd4e5328 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/NbCodeLanguageClient.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/NbCodeLanguageClient.java
@@ -52,11 +52,18 @@ public interface NbCodeLanguageClient extends LanguageClient {
     public void showStatusBarMessage(@NonNull ShowStatusMessageParams params);
     /**
      * Shows an HTML based UI.
-     * @param params the URI of the page to show
+     * @param params the page to show
      */
     @JsonRequest("window/showHtmlPage")
     public CompletableFuture<String> showHtmlPage(@NonNull HtmlPageParams params);
 
+    /**
+     * Execute script in an HTML based UI.
+     * @param params the script to execute
+     */
+    @JsonRequest("window/execInHtmlPage")
+    public CompletableFuture<String> execInHtmlPage(@NonNull HtmlPageParams params);
+
     /**
      * Shows a selection list allowing multiple selections.
      *
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/Server.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/Server.java
index 2a6da513e9..cdcf5cf636 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/Server.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/Server.java
@@ -1047,6 +1047,12 @@ public final class Server {
             return CompletableFuture.completedFuture(null);
         }
 
+        @Override
+        public CompletableFuture<String> execInHtmlPage(HtmlPageParams params) {
+            logWarning(params);
+            return CompletableFuture.completedFuture(null);
+        }
+
         @Override
         public CompletableFuture<Void> configurationUpdate(UpdateConfigParams params) {
             logWarning(params);
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ShowStatusMessageParams.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ShowStatusMessageParams.java
index 43af7366db..4a5630352e 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ShowStatusMessageParams.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ShowStatusMessageParams.java
@@ -30,6 +30,9 @@ import org.eclipse.xtext.xbase.lib.Pure;
 public class ShowStatusMessageParams extends MessageParams {
     private Integer timeout;
 
+    public ShowStatusMessageParams() {
+    }
+
     public ShowStatusMessageParams(MessageType type, String message) {
         super(type, message);
     }
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/UIContext.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/UIContext.java
index 9261a9ba1e..2502e818e9 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/UIContext.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/UIContext.java
@@ -85,7 +85,7 @@ public abstract class UIContext {
     public abstract boolean isValid();
     public abstract void showMessage(MessageParams msg);
     public CompletableFuture<String> showHtmlPage(HtmlPageParams msg) {
-        showMessage(new MessageParams(MessageType.Log, msg.getUri()));
+        showMessage(new MessageParams(MessageType.Log, msg.getText()));
         return CompletableFuture.completedFuture(null);
     }
     public abstract CompletableFuture<MessageActionItem> showMessageRequest(ShowMessageRequestParams msg);
@@ -136,7 +136,7 @@ public abstract class UIContext {
 
         @Override
         public Message showStatusMessage(ShowStatusMessageParams msg) {
-            System.out.println(msg.getType() + ": " + msg.getMessage());
+            System.err.println(msg.getType() + ": " + msg.getMessage());
             return (int timeInMillis) -> {};
         }
 
@@ -147,7 +147,7 @@ public abstract class UIContext {
 
         @Override
         public CompletableFuture<String> showHtmlPage(HtmlPageParams msg) {
-            System.out.println("Open in browser: " + msg.getUri());
+            System.err.println("Open in browser: " + msg.getText());
             return CompletableFuture.completedFuture(null);
         }
 
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/ChangeMethodParametersRefactoring.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/ChangeMethodParametersRefactoring.java
index 6abdf61bab..65b9be36c2 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/ChangeMethodParametersRefactoring.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/ChangeMethodParametersRefactoring.java
@@ -187,7 +187,7 @@ public final class ChangeMethodParametersRefactoring extends CodeRefactoring {
         return "null";
     }
 
-    @HTMLDialog(url = "ui/ChangeMethodParameters.html")
+    @HTMLDialog(url = "ui/ChangeMethodParameters.html", resources = {"refactoring.css"})
     static HTMLDialog.OnSubmit showChangeMethodParametersUI(
         CompilationController ci,
         NbCodeLanguageClient client,
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/MoveRefactoring.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/MoveRefactoring.java
index 5187f8468d..2859acbd24 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/MoveRefactoring.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/MoveRefactoring.java
@@ -183,7 +183,7 @@ public final class MoveRefactoring extends CodeRefactoring {
         return CompletableFuture.completedFuture(true);
     }
 
-    @HTMLDialog(url = "ui/MoveClass.html")
+    @HTMLDialog(url = "ui/MoveClass.html", resources = {"refactoring.css"})
     static HTMLDialog.OnSubmit showMoveClassUI(
         CompilationController ci,
         NbCodeLanguageClient client,
@@ -203,7 +203,7 @@ public final class MoveRefactoring extends CodeRefactoring {
         };
     }
 
-    @HTMLDialog(url = "ui/MoveMembers.html")
+    @HTMLDialog(url = "ui/MoveMembers.html", resources = {"refactoring.css"})
     static HTMLDialog.OnSubmit showMoveMembersUI(
         CompilationController ci,
         NbCodeLanguageClient client,
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/ui/MoveClass.html b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/ui/MoveClass.html
index c6f45c732f..64f5cd78af 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/ui/MoveClass.html
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/ui/MoveClass.html
@@ -26,7 +26,6 @@
     <meta http-equiv="Content-Security-Policy" content="default-src http: 'unsafe-inline' 'unsafe-eval'">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <link rel="stylesheet" href="refactoring.css">
-    <link rel="stylesheet" href="codicon.css">
     <title>Refactor: Move Class...</title>
 </head>
 
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/ui/MoveMembers.html b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/ui/MoveMembers.html
index ed7ab7c0a6..c69a9d9729 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/ui/MoveMembers.html
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/ui/MoveMembers.html
@@ -26,7 +26,6 @@
     <meta http-equiv="Content-Security-Policy" content="default-src http: 'unsafe-inline' 'unsafe-eval'">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <link rel="stylesheet" href="refactoring.css">
-    <link rel="stylesheet" href="codicon.css">
     <title>Refactor: Move Members...</title>
 </head>
 
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/ui/codicon.css b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/ui/codicon.css
deleted file mode 100644
index c2771b5e88..0000000000
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/ui/codicon.css
+++ /dev/null
@@ -1,485 +0,0 @@
-/*---------------------------------------------------------------------------------------------
- *  Copyright (c) Microsoft Corporation. All rights reserved.
- *  Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
-
-@font-face {
-	font-family: "codicon";
-	src: url("./codicon.ttf?9642aa1d48ab4e55aa1bf3f0b8678aa1") format("truetype");
-}
-
-.codicon[class*='codicon-'] {
-	font: normal normal normal 16px/1 codicon;
-	display: inline-block;
-	text-decoration: none;
-	text-rendering: auto;
-	text-align: center;
-	-webkit-font-smoothing: antialiased;
-	-moz-osx-font-smoothing: grayscale;
-	user-select: none;
-	-webkit-user-select: none;
-	-ms-user-select: none;
-}
-
-
-.codicon-add:before { content: "\ea60" }
-.codicon-plus:before { content: "\ea60" }
-.codicon-gist-new:before { content: "\ea60" }
-.codicon-repo-create:before { content: "\ea60" }
-.codicon-lightbulb:before { content: "\ea61" }
-.codicon-light-bulb:before { content: "\ea61" }
-.codicon-repo:before { content: "\ea62" }
-.codicon-repo-delete:before { content: "\ea62" }
-.codicon-gist-fork:before { content: "\ea63" }
-.codicon-repo-forked:before { content: "\ea63" }
-.codicon-git-pull-request:before { content: "\ea64" }
-.codicon-git-pull-request-abandoned:before { content: "\ea64" }
-.codicon-record-keys:before { content: "\ea65" }
-.codicon-keyboard:before { content: "\ea65" }
-.codicon-tag:before { content: "\ea66" }
-.codicon-tag-add:before { content: "\ea66" }
-.codicon-tag-remove:before { content: "\ea66" }
-.codicon-person:before { content: "\ea67" }
-.codicon-person-follow:before { content: "\ea67" }
-.codicon-person-outline:before { content: "\ea67" }
-.codicon-person-filled:before { content: "\ea67" }
-.codicon-git-branch:before { content: "\ea68" }
-.codicon-git-branch-create:before { content: "\ea68" }
-.codicon-git-branch-delete:before { content: "\ea68" }
-.codicon-source-control:before { content: "\ea68" }
-.codicon-mirror:before { content: "\ea69" }
-.codicon-mirror-public:before { content: "\ea69" }
-.codicon-star:before { content: "\ea6a" }
-.codicon-star-add:before { content: "\ea6a" }
-.codicon-star-delete:before { content: "\ea6a" }
-.codicon-star-empty:before { content: "\ea6a" }
-.codicon-comment:before { content: "\ea6b" }
-.codicon-comment-add:before { content: "\ea6b" }
-.codicon-alert:before { content: "\ea6c" }
-.codicon-warning:before { content: "\ea6c" }
-.codicon-search:before { content: "\ea6d" }
-.codicon-search-save:before { content: "\ea6d" }
-.codicon-log-out:before { content: "\ea6e" }
-.codicon-sign-out:before { content: "\ea6e" }
-.codicon-log-in:before { content: "\ea6f" }
-.codicon-sign-in:before { content: "\ea6f" }
-.codicon-eye:before { content: "\ea70" }
-.codicon-eye-unwatch:before { content: "\ea70" }
-.codicon-eye-watch:before { content: "\ea70" }
-.codicon-circle-filled:before { content: "\ea71" }
-.codicon-primitive-dot:before { content: "\ea71" }
-.codicon-close-dirty:before { content: "\ea71" }
-.codicon-debug-breakpoint:before { content: "\ea71" }
-.codicon-debug-breakpoint-disabled:before { content: "\ea71" }
-.codicon-debug-hint:before { content: "\ea71" }
-.codicon-primitive-square:before { content: "\ea72" }
-.codicon-edit:before { content: "\ea73" }
-.codicon-pencil:before { content: "\ea73" }
-.codicon-info:before { content: "\ea74" }
-.codicon-issue-opened:before { content: "\ea74" }
-.codicon-gist-private:before { content: "\ea75" }
-.codicon-git-fork-private:before { content: "\ea75" }
-.codicon-lock:before { content: "\ea75" }
-.codicon-mirror-private:before { content: "\ea75" }
-.codicon-close:before { content: "\ea76" }
-.codicon-remove-close:before { content: "\ea76" }
-.codicon-x:before { content: "\ea76" }
-.codicon-repo-sync:before { content: "\ea77" }
-.codicon-sync:before { content: "\ea77" }
-.codicon-clone:before { content: "\ea78" }
-.codicon-desktop-download:before { content: "\ea78" }
-.codicon-beaker:before { content: "\ea79" }
-.codicon-microscope:before { content: "\ea79" }
-.codicon-vm:before { content: "\ea7a" }
-.codicon-device-desktop:before { content: "\ea7a" }
-.codicon-file:before { content: "\ea7b" }
-.codicon-file-text:before { content: "\ea7b" }
-.codicon-more:before { content: "\ea7c" }
-.codicon-ellipsis:before { content: "\ea7c" }
-.codicon-kebab-horizontal:before { content: "\ea7c" }
-.codicon-mail-reply:before { content: "\ea7d" }
-.codicon-reply:before { content: "\ea7d" }
-.codicon-organization:before { content: "\ea7e" }
-.codicon-organization-filled:before { content: "\ea7e" }
-.codicon-organization-outline:before { content: "\ea7e" }
-.codicon-new-file:before { content: "\ea7f" }
-.codicon-file-add:before { content: "\ea7f" }
-.codicon-new-folder:before { content: "\ea80" }
-.codicon-file-directory-create:before { content: "\ea80" }
-.codicon-trash:before { content: "\ea81" }
-.codicon-trashcan:before { content: "\ea81" }
-.codicon-history:before { content: "\ea82" }
-.codicon-clock:before { content: "\ea82" }
-.codicon-folder:before { content: "\ea83" }
-.codicon-file-directory:before { content: "\ea83" }
-.codicon-symbol-folder:before { content: "\ea83" }
-.codicon-logo-github:before { content: "\ea84" }
-.codicon-mark-github:before { content: "\ea84" }
-.codicon-github:before { content: "\ea84" }
-.codicon-terminal:before { content: "\ea85" }
-.codicon-console:before { content: "\ea85" }
-.codicon-repl:before { content: "\ea85" }
-.codicon-zap:before { content: "\ea86" }
-.codicon-symbol-event:before { content: "\ea86" }
-.codicon-error:before { content: "\ea87" }
-.codicon-stop:before { content: "\ea87" }
-.codicon-variable:before { content: "\ea88" }
-.codicon-symbol-variable:before { content: "\ea88" }
-.codicon-array:before { content: "\ea8a" }
-.codicon-symbol-array:before { content: "\ea8a" }
-.codicon-symbol-module:before { content: "\ea8b" }
-.codicon-symbol-package:before { content: "\ea8b" }
-.codicon-symbol-namespace:before { content: "\ea8b" }
-.codicon-symbol-object:before { content: "\ea8b" }
-.codicon-symbol-method:before { content: "\ea8c" }
-.codicon-symbol-function:before { content: "\ea8c" }
-.codicon-symbol-constructor:before { content: "\ea8c" }
-.codicon-symbol-boolean:before { content: "\ea8f" }
-.codicon-symbol-null:before { content: "\ea8f" }
-.codicon-symbol-numeric:before { content: "\ea90" }
-.codicon-symbol-number:before { content: "\ea90" }
-.codicon-symbol-structure:before { content: "\ea91" }
-.codicon-symbol-struct:before { content: "\ea91" }
-.codicon-symbol-parameter:before { content: "\ea92" }
-.codicon-symbol-type-parameter:before { content: "\ea92" }
-.codicon-symbol-key:before { content: "\ea93" }
-.codicon-symbol-text:before { content: "\ea93" }
-.codicon-symbol-reference:before { content: "\ea94" }
-.codicon-go-to-file:before { content: "\ea94" }
-.codicon-symbol-enum:before { content: "\ea95" }
-.codicon-symbol-value:before { content: "\ea95" }
-.codicon-symbol-ruler:before { content: "\ea96" }
-.codicon-symbol-unit:before { content: "\ea96" }
-.codicon-activate-breakpoints:before { content: "\ea97" }
-.codicon-archive:before { content: "\ea98" }
-.codicon-arrow-both:before { content: "\ea99" }
-.codicon-arrow-down:before { content: "\ea9a" }
-.codicon-arrow-left:before { content: "\ea9b" }
-.codicon-arrow-right:before { content: "\ea9c" }
-.codicon-arrow-small-down:before { content: "\ea9d" }
-.codicon-arrow-small-left:before { content: "\ea9e" }
-.codicon-arrow-small-right:before { content: "\ea9f" }
-.codicon-arrow-small-up:before { content: "\eaa0" }
-.codicon-arrow-up:before { content: "\eaa1" }
-.codicon-bell:before { content: "\eaa2" }
-.codicon-bold:before { content: "\eaa3" }
-.codicon-book:before { content: "\eaa4" }
-.codicon-bookmark:before { content: "\eaa5" }
-.codicon-debug-breakpoint-conditional-unverified:before { content: "\eaa6" }
-.codicon-debug-breakpoint-conditional:before { content: "\eaa7" }
-.codicon-debug-breakpoint-conditional-disabled:before { content: "\eaa7" }
-.codicon-debug-breakpoint-data-unverified:before { content: "\eaa8" }
-.codicon-debug-breakpoint-data:before { content: "\eaa9" }
-.codicon-debug-breakpoint-data-disabled:before { content: "\eaa9" }
-.codicon-debug-breakpoint-log-unverified:before { content: "\eaaa" }
-.codicon-debug-breakpoint-log:before { content: "\eaab" }
-.codicon-debug-breakpoint-log-disabled:before { content: "\eaab" }
-.codicon-briefcase:before { content: "\eaac" }
-.codicon-broadcast:before { content: "\eaad" }
-.codicon-browser:before { content: "\eaae" }
-.codicon-bug:before { content: "\eaaf" }
-.codicon-calendar:before { content: "\eab0" }
-.codicon-case-sensitive:before { content: "\eab1" }
-.codicon-check:before { content: "\eab2" }
-.codicon-checklist:before { content: "\eab3" }
-.codicon-chevron-down:before { content: "\eab4" }
-.codicon-chevron-left:before { content: "\eab5" }
-.codicon-chevron-right:before { content: "\eab6" }
-.codicon-chevron-up:before { content: "\eab7" }
-.codicon-chrome-close:before { content: "\eab8" }
-.codicon-chrome-maximize:before { content: "\eab9" }
-.codicon-chrome-minimize:before { content: "\eaba" }
-.codicon-chrome-restore:before { content: "\eabb" }
-.codicon-circle-outline:before { content: "\eabc" }
-.codicon-debug-breakpoint-unverified:before { content: "\eabc" }
-.codicon-circle-slash:before { content: "\eabd" }
-.codicon-circuit-board:before { content: "\eabe" }
-.codicon-clear-all:before { content: "\eabf" }
-.codicon-clippy:before { content: "\eac0" }
-.codicon-close-all:before { content: "\eac1" }
-.codicon-cloud-download:before { content: "\eac2" }
-.codicon-cloud-upload:before { content: "\eac3" }
-.codicon-code:before { content: "\eac4" }
-.codicon-collapse-all:before { content: "\eac5" }
-.codicon-color-mode:before { content: "\eac6" }
-.codicon-comment-discussion:before { content: "\eac7" }
-.codicon-credit-card:before { content: "\eac9" }
-.codicon-dash:before { content: "\eacc" }
-.codicon-dashboard:before { content: "\eacd" }
-.codicon-database:before { content: "\eace" }
-.codicon-debug-continue:before { content: "\eacf" }
-.codicon-debug-disconnect:before { content: "\ead0" }
-.codicon-debug-pause:before { content: "\ead1" }
-.codicon-debug-restart:before { content: "\ead2" }
-.codicon-debug-start:before { content: "\ead3" }
-.codicon-debug-step-into:before { content: "\ead4" }
-.codicon-debug-step-out:before { content: "\ead5" }
-.codicon-debug-step-over:before { content: "\ead6" }
-.codicon-debug-stop:before { content: "\ead7" }
-.codicon-debug:before { content: "\ead8" }
-.codicon-device-camera-video:before { content: "\ead9" }
-.codicon-device-camera:before { content: "\eada" }
-.codicon-device-mobile:before { content: "\eadb" }
-.codicon-diff-added:before { content: "\eadc" }
-.codicon-diff-ignored:before { content: "\eadd" }
-.codicon-diff-modified:before { content: "\eade" }
-.codicon-diff-removed:before { content: "\eadf" }
-.codicon-diff-renamed:before { content: "\eae0" }
-.codicon-diff:before { content: "\eae1" }
-.codicon-discard:before { content: "\eae2" }
-.codicon-editor-layout:before { content: "\eae3" }
-.codicon-empty-window:before { content: "\eae4" }
-.codicon-exclude:before { content: "\eae5" }
-.codicon-extensions:before { content: "\eae6" }
-.codicon-eye-closed:before { content: "\eae7" }
-.codicon-file-binary:before { content: "\eae8" }
-.codicon-file-code:before { content: "\eae9" }
-.codicon-file-media:before { content: "\eaea" }
-.codicon-file-pdf:before { content: "\eaeb" }
-.codicon-file-submodule:before { content: "\eaec" }
-.codicon-file-symlink-directory:before { content: "\eaed" }
-.codicon-file-symlink-file:before { content: "\eaee" }
-.codicon-file-zip:before { content: "\eaef" }
-.codicon-files:before { content: "\eaf0" }
-.codicon-filter:before { content: "\eaf1" }
-.codicon-flame:before { content: "\eaf2" }
-.codicon-fold-down:before { content: "\eaf3" }
-.codicon-fold-up:before { content: "\eaf4" }
-.codicon-fold:before { content: "\eaf5" }
-.codicon-folder-active:before { content: "\eaf6" }
-.codicon-folder-opened:before { content: "\eaf7" }
-.codicon-gear:before { content: "\eaf8" }
-.codicon-gift:before { content: "\eaf9" }
-.codicon-gist-secret:before { content: "\eafa" }
-.codicon-gist:before { content: "\eafb" }
-.codicon-git-commit:before { content: "\eafc" }
-.codicon-git-compare:before { content: "\eafd" }
-.codicon-compare-changes:before { content: "\eafd" }
-.codicon-git-merge:before { content: "\eafe" }
-.codicon-github-action:before { content: "\eaff" }
-.codicon-github-alt:before { content: "\eb00" }
-.codicon-globe:before { content: "\eb01" }
-.codicon-grabber:before { content: "\eb02" }
-.codicon-graph:before { content: "\eb03" }
-.codicon-gripper:before { content: "\eb04" }
-.codicon-heart:before { content: "\eb05" }
-.codicon-home:before { content: "\eb06" }
-.codicon-horizontal-rule:before { content: "\eb07" }
-.codicon-hubot:before { content: "\eb08" }
-.codicon-inbox:before { content: "\eb09" }
-.codicon-issue-reopened:before { content: "\eb0b" }
-.codicon-issues:before { content: "\eb0c" }
-.codicon-italic:before { content: "\eb0d" }
-.codicon-jersey:before { content: "\eb0e" }
-.codicon-json:before { content: "\eb0f" }
-.codicon-kebab-vertical:before { content: "\eb10" }
-.codicon-key:before { content: "\eb11" }
-.codicon-law:before { content: "\eb12" }
-.codicon-lightbulb-autofix:before { content: "\eb13" }
-.codicon-link-external:before { content: "\eb14" }
-.codicon-link:before { content: "\eb15" }
-.codicon-list-ordered:before { content: "\eb16" }
-.codicon-list-unordered:before { content: "\eb17" }
-.codicon-live-share:before { content: "\eb18" }
-.codicon-loading:before { content: "\eb19" }
-.codicon-location:before { content: "\eb1a" }
-.codicon-mail-read:before { content: "\eb1b" }
-.codicon-mail:before { content: "\eb1c" }
-.codicon-markdown:before { content: "\eb1d" }
-.codicon-megaphone:before { content: "\eb1e" }
-.codicon-mention:before { content: "\eb1f" }
-.codicon-milestone:before { content: "\eb20" }
-.codicon-mortar-board:before { content: "\eb21" }
-.codicon-move:before { content: "\eb22" }
-.codicon-multiple-windows:before { content: "\eb23" }
-.codicon-mute:before { content: "\eb24" }
-.codicon-no-newline:before { content: "\eb25" }
-.codicon-note:before { content: "\eb26" }
-.codicon-octoface:before { content: "\eb27" }
-.codicon-open-preview:before { content: "\eb28" }
-.codicon-package:before { content: "\eb29" }
-.codicon-paintcan:before { content: "\eb2a" }
-.codicon-pin:before { content: "\eb2b" }
-.codicon-play:before { content: "\eb2c" }
-.codicon-run:before { content: "\eb2c" }
-.codicon-plug:before { content: "\eb2d" }
-.codicon-preserve-case:before { content: "\eb2e" }
-.codicon-preview:before { content: "\eb2f" }
-.codicon-project:before { content: "\eb30" }
-.codicon-pulse:before { content: "\eb31" }
-.codicon-question:before { content: "\eb32" }
-.codicon-quote:before { content: "\eb33" }
-.codicon-radio-tower:before { content: "\eb34" }
-.codicon-reactions:before { content: "\eb35" }
-.codicon-references:before { content: "\eb36" }
-.codicon-refresh:before { content: "\eb37" }
-.codicon-regex:before { content: "\eb38" }
-.codicon-remote-explorer:before { content: "\eb39" }
-.codicon-remote:before { content: "\eb3a" }
-.codicon-remove:before { content: "\eb3b" }
-.codicon-replace-all:before { content: "\eb3c" }
-.codicon-replace:before { content: "\eb3d" }
-.codicon-repo-clone:before { content: "\eb3e" }
-.codicon-repo-force-push:before { content: "\eb3f" }
-.codicon-repo-pull:before { content: "\eb40" }
-.codicon-repo-push:before { content: "\eb41" }
-.codicon-report:before { content: "\eb42" }
-.codicon-request-changes:before { content: "\eb43" }
-.codicon-rocket:before { content: "\eb44" }
-.codicon-root-folder-opened:before { content: "\eb45" }
-.codicon-root-folder:before { content: "\eb46" }
-.codicon-rss:before { content: "\eb47" }
-.codicon-ruby:before { content: "\eb48" }
-.codicon-save-all:before { content: "\eb49" }
-.codicon-save-as:before { content: "\eb4a" }
-.codicon-save:before { content: "\eb4b" }
-.codicon-screen-full:before { content: "\eb4c" }
-.codicon-screen-normal:before { content: "\eb4d" }
-.codicon-search-stop:before { content: "\eb4e" }
-.codicon-server:before { content: "\eb50" }
-.codicon-settings-gear:before { content: "\eb51" }
-.codicon-settings:before { content: "\eb52" }
-.codicon-shield:before { content: "\eb53" }
-.codicon-smiley:before { content: "\eb54" }
-.codicon-sort-precedence:before { content: "\eb55" }
-.codicon-split-horizontal:before { content: "\eb56" }
-.codicon-split-vertical:before { content: "\eb57" }
-.codicon-squirrel:before { content: "\eb58" }
-.codicon-star-full:before { content: "\eb59" }
-.codicon-star-half:before { content: "\eb5a" }
-.codicon-symbol-class:before { content: "\eb5b" }
-.codicon-symbol-color:before { content: "\eb5c" }
-.codicon-symbol-constant:before { content: "\eb5d" }
-.codicon-symbol-enum-member:before { content: "\eb5e" }
-.codicon-symbol-field:before { content: "\eb5f" }
-.codicon-symbol-file:before { content: "\eb60" }
-.codicon-symbol-interface:before { content: "\eb61" }
-.codicon-symbol-keyword:before { content: "\eb62" }
-.codicon-symbol-misc:before { content: "\eb63" }
-.codicon-symbol-operator:before { content: "\eb64" }
-.codicon-symbol-property:before { content: "\eb65" }
-.codicon-wrench:before { content: "\eb65" }
-.codicon-wrench-subaction:before { content: "\eb65" }
-.codicon-symbol-snippet:before { content: "\eb66" }
-.codicon-tasklist:before { content: "\eb67" }
-.codicon-telescope:before { content: "\eb68" }
-.codicon-text-size:before { content: "\eb69" }
-.codicon-three-bars:before { content: "\eb6a" }
-.codicon-thumbsdown:before { content: "\eb6b" }
-.codicon-thumbsup:before { content: "\eb6c" }
-.codicon-tools:before { content: "\eb6d" }
-.codicon-triangle-down:before { content: "\eb6e" }
-.codicon-triangle-left:before { content: "\eb6f" }
-.codicon-triangle-right:before { content: "\eb70" }
-.codicon-triangle-up:before { content: "\eb71" }
-.codicon-twitter:before { content: "\eb72" }
-.codicon-unfold:before { content: "\eb73" }
-.codicon-unlock:before { content: "\eb74" }
-.codicon-unmute:before { content: "\eb75" }
-.codicon-unverified:before { content: "\eb76" }
-.codicon-verified:before { content: "\eb77" }
-.codicon-versions:before { content: "\eb78" }
-.codicon-vm-active:before { content: "\eb79" }
-.codicon-vm-outline:before { content: "\eb7a" }
-.codicon-vm-running:before { content: "\eb7b" }
-.codicon-watch:before { content: "\eb7c" }
-.codicon-whitespace:before { content: "\eb7d" }
-.codicon-whole-word:before { content: "\eb7e" }
-.codicon-window:before { content: "\eb7f" }
-.codicon-word-wrap:before { content: "\eb80" }
-.codicon-zoom-in:before { content: "\eb81" }
-.codicon-zoom-out:before { content: "\eb82" }
-.codicon-list-filter:before { content: "\eb83" }
-.codicon-list-flat:before { content: "\eb84" }
-.codicon-list-selection:before { content: "\eb85" }
-.codicon-selection:before { content: "\eb85" }
-.codicon-list-tree:before { content: "\eb86" }
-.codicon-debug-breakpoint-function-unverified:before { content: "\eb87" }
-.codicon-debug-breakpoint-function:before { content: "\eb88" }
-.codicon-debug-breakpoint-function-disabled:before { content: "\eb88" }
-.codicon-debug-stackframe-active:before { content: "\eb89" }
-.codicon-debug-stackframe-dot:before { content: "\eb8a" }
-.codicon-debug-stackframe:before { content: "\eb8b" }
-.codicon-debug-stackframe-focused:before { content: "\eb8b" }
-.codicon-debug-breakpoint-unsupported:before { content: "\eb8c" }
-.codicon-symbol-string:before { content: "\eb8d" }
-.codicon-debug-reverse-continue:before { content: "\eb8e" }
-.codicon-debug-step-back:before { content: "\eb8f" }
-.codicon-debug-restart-frame:before { content: "\eb90" }
-.codicon-debug-alt:before { content: "\eb91" }
-.codicon-call-incoming:before { content: "\eb92" }
-.codicon-call-outgoing:before { content: "\eb93" }
-.codicon-menu:before { content: "\eb94" }
-.codicon-expand-all:before { content: "\eb95" }
-.codicon-feedback:before { content: "\eb96" }
-.codicon-group-by-ref-type:before { content: "\eb97" }
-.codicon-ungroup-by-ref-type:before { content: "\eb98" }
-.codicon-account:before { content: "\eb99" }
-.codicon-bell-dot:before { content: "\eb9a" }
-.codicon-debug-console:before { content: "\eb9b" }
-.codicon-library:before { content: "\eb9c" }
-.codicon-output:before { content: "\eb9d" }
-.codicon-run-all:before { content: "\eb9e" }
-.codicon-sync-ignored:before { content: "\eb9f" }
-.codicon-pinned:before { content: "\eba0" }
-.codicon-github-inverted:before { content: "\eba1" }
-.codicon-server-process:before { content: "\eba2" }
-.codicon-server-environment:before { content: "\eba3" }
-.codicon-pass:before { content: "\eba4" }
-.codicon-issue-closed:before { content: "\eba4" }
-.codicon-stop-circle:before { content: "\eba5" }
-.codicon-play-circle:before { content: "\eba6" }
-.codicon-record:before { content: "\eba7" }
-.codicon-debug-alt-small:before { content: "\eba8" }
-.codicon-vm-connect:before { content: "\eba9" }
-.codicon-cloud:before { content: "\ebaa" }
-.codicon-merge:before { content: "\ebab" }
-.codicon-export:before { content: "\ebac" }
-.codicon-graph-left:before { content: "\ebad" }
-.codicon-magnet:before { content: "\ebae" }
-.codicon-notebook:before { content: "\ebaf" }
-.codicon-redo:before { content: "\ebb0" }
-.codicon-check-all:before { content: "\ebb1" }
-.codicon-pinned-dirty:before { content: "\ebb2" }
-.codicon-pass-filled:before { content: "\ebb3" }
-.codicon-circle-large-filled:before { content: "\ebb4" }
-.codicon-circle-large-outline:before { content: "\ebb5" }
-.codicon-combine:before { content: "\ebb6" }
-.codicon-gather:before { content: "\ebb6" }
-.codicon-table:before { content: "\ebb7" }
-.codicon-variable-group:before { content: "\ebb8" }
-.codicon-type-hierarchy:before { content: "\ebb9" }
-.codicon-type-hierarchy-sub:before { content: "\ebba" }
-.codicon-type-hierarchy-super:before { content: "\ebbb" }
-.codicon-git-pull-request-create:before { content: "\ebbc" }
-.codicon-run-above:before { content: "\ebbd" }
-.codicon-run-below:before { content: "\ebbe" }
-.codicon-notebook-template:before { content: "\ebbf" }
-.codicon-debug-rerun:before { content: "\ebc0" }
-.codicon-workspace-trusted:before { content: "\ebc1" }
-.codicon-workspace-untrusted:before { content: "\ebc2" }
-.codicon-workspace-unknown:before { content: "\ebc3" }
-.codicon-terminal-cmd:before { content: "\ebc4" }
-.codicon-terminal-debian:before { content: "\ebc5" }
-.codicon-terminal-linux:before { content: "\ebc6" }
-.codicon-terminal-powershell:before { content: "\ebc7" }
-.codicon-terminal-tmux:before { content: "\ebc8" }
-.codicon-terminal-ubuntu:before { content: "\ebc9" }
-.codicon-terminal-bash:before { content: "\ebca" }
-.codicon-arrow-swap:before { content: "\ebcb" }
-.codicon-copy:before { content: "\ebcc" }
-.codicon-person-add:before { content: "\ebcd" }
-.codicon-filter-filled:before { content: "\ebce" }
-.codicon-wand:before { content: "\ebcf" }
-.codicon-debug-line-by-line:before { content: "\ebd0" }
-.codicon-inspect:before { content: "\ebd1" }
-.codicon-layers:before { content: "\ebd2" }
-.codicon-layers-dot:before { content: "\ebd3" }
-.codicon-layers-active:before { content: "\ebd4" }
-.codicon-compass:before { content: "\ebd5" }
-.codicon-compass-dot:before { content: "\ebd6" }
-.codicon-compass-active:before { content: "\ebd7" }
-.codicon-azure:before { content: "\ebd8" }
-.codicon-issue-draft:before { content: "\ebd9" }
-.codicon-git-pull-request-closed:before { content: "\ebda" }
-.codicon-git-pull-request-draft:before { content: "\ebdb" }
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/ui/codicon.ttf b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/ui/codicon.ttf
deleted file mode 100644
index 8d844c9279..0000000000
Binary files a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/ui/codicon.ttf and /dev/null differ
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/ui/AbstractLspHtmlViewer.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/ui/AbstractLspHtmlViewer.java
index 8745989599..acba4f87c5 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/ui/AbstractLspHtmlViewer.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/ui/AbstractLspHtmlViewer.java
@@ -18,15 +18,13 @@
  */
 package org.netbeans.modules.java.lsp.server.ui;
 
-import java.net.URL;
-import net.java.html.js.JavaScriptBody;
+import java.io.IOException;
 import org.eclipse.lsp4j.MessageParams;
 import org.eclipse.lsp4j.MessageType;
-import org.netbeans.modules.java.lsp.server.htmlui.Browser;
-import org.netbeans.modules.java.lsp.server.htmlui.Browser.Config;
 import org.netbeans.modules.java.lsp.server.htmlui.Buttons;
 import static org.netbeans.modules.java.lsp.server.htmlui.Buttons.buttonName0;
 import static org.netbeans.modules.java.lsp.server.htmlui.Buttons.buttonText0;
+import org.netbeans.modules.java.lsp.server.htmlui.WebView;
 import org.netbeans.modules.java.lsp.server.protocol.HtmlPageParams;
 import org.netbeans.modules.java.lsp.server.protocol.NbCodeClientCapabilities;
 import org.netbeans.modules.java.lsp.server.protocol.UIContext;
@@ -41,7 +39,6 @@ import org.openide.util.NbBundle;
  * @since 1.14
  */
 public class AbstractLspHtmlViewer implements HTMLViewerSpi<AbstractLspHtmlViewer.View, Object> {
-    private final Config initial = new Config();
 
     protected AbstractLspHtmlViewer() {
     }
@@ -95,7 +92,7 @@ public class AbstractLspHtmlViewer implements HTMLViewerSpi<AbstractLspHtmlViewe
     protected final class View {
         final Context ctx;
         private final UIContext ui;
-        private Browser presenter;
+        private WebView presenter;
 
         private View(UIContext ui, Context ctx) {
             this.ui = ui;
@@ -121,12 +118,14 @@ public class AbstractLspHtmlViewer implements HTMLViewerSpi<AbstractLspHtmlViewe
                 notifyClose();
                 return;
             }
-            URL pageUrl = ctx.getPage();
-            Browser.Config c = initial.clone();
-            c.browser((page) -> {
+            presenter = new WebView((page) -> {
                 try {
-                    ui.showHtmlPage(new HtmlPageParams(page.toASCIIString())).thenAccept((t) -> {
-                        final Browser p = presenter;
+                    HtmlPageParams params = new HtmlPageParams(page.getId(), page.getText());
+                    if (!page.getResources().isEmpty()) {
+                        params = params.setResources(page.getResources());
+                    }
+                    ui.showHtmlPage(params).thenAccept((t) -> {
+                        final WebView p = presenter;
                         if (p == null) {
                             return;
                         }
@@ -137,7 +136,7 @@ public class AbstractLspHtmlViewer implements HTMLViewerSpi<AbstractLspHtmlViewe
                         }
                         try {
                             p.close();
-                        } catch (Exception ex) {
+                        } catch (IOException ex) {
                             Exceptions.printStackTrace(ex);
                         } finally {
                             presenter = null;
@@ -151,16 +150,7 @@ public class AbstractLspHtmlViewer implements HTMLViewerSpi<AbstractLspHtmlViewe
                     Exceptions.printStackTrace(ex);
                 }
             });
-            presenter = new Browser(c);
-            presenter.displayPage(pageUrl, () -> {
-                Buttons.registerCloseWindow();
-                try {
-                    ctx.onPageLoad();
-                } catch (Exception ex) {
-                    Exceptions.printStackTrace(ex);
-                }
-            });
-
+            presenter.displayPage(ctx);
         }
     }
 }
diff --git a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/TestCodeLanguageClient.java b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/TestCodeLanguageClient.java
index 1ac6dfe66d..33523b8041 100644
--- a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/TestCodeLanguageClient.java
+++ b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/TestCodeLanguageClient.java
@@ -78,6 +78,11 @@ public abstract class TestCodeLanguageClient implements NbCodeLanguageClient {
         throw new UnsupportedOperationException();
     }
 
+    @Override
+    public CompletableFuture<String> execInHtmlPage(HtmlPageParams params) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public CompletableFuture<List<QuickPickItem>> showQuickPick(ShowQuickPickParams params) {
         return CompletableFuture.completedFuture(params.getItems().stream().filter(item -> item.isPicked()).collect(Collectors.toList()));
diff --git a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/explorer/ProjectViewTest.java b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/explorer/ProjectViewTest.java
index 391fba10d9..033b9594ed 100644
--- a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/explorer/ProjectViewTest.java
+++ b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/explorer/ProjectViewTest.java
@@ -187,6 +187,11 @@ public class ProjectViewTest extends NbTestCase {
             return CompletableFuture.completedFuture(null);
         }
 
+        @Override
+        public CompletableFuture<String> execInHtmlPage(HtmlPageParams params) {
+            return CompletableFuture.completedFuture(null);
+        }
+
         @Override
         public CompletableFuture<List<QuickPickItem>> showQuickPick(ShowQuickPickParams params) {
             return CompletableFuture.completedFuture(null);
diff --git a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java
index 8bf4eab55d..3677181919 100644
--- a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java
+++ b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java
@@ -1613,13 +1613,33 @@ public class ServerTest extends NbTestCase {
         initParams.setRootUri(toURI(getWorkDir()));
         InitializeResult result = server.initialize(initParams).get();
         indexingComplete.await();
-        server.getTextDocumentService().didOpen(new DidOpenTextDocumentParams(new TextDocumentItem(toURI(src), "java", 0, code)));
+        String uri = toURI(src);
+        server.getTextDocumentService().didOpen(new DidOpenTextDocumentParams(new TextDocumentItem(uri, "java", 0, code)));
 
         Diagnostic unresolvable = assertDiags(diags, "Error:2:8-2:12").get(0);
-        List<Either<Command, CodeAction>> codeActions = server.getTextDocumentService().codeAction(new CodeActionParams(new TextDocumentIdentifier(toURI(src)), unresolvable.getRange(), new CodeActionContext(Arrays.asList(unresolvable)))).get();
-        if (jdk9Plus()) {
-            assertEquals(2, codeActions.size());
-        }
+        Position pos = unresolvable.getRange().getStart();
+        List<Either<Command, CodeAction>> codeActions = server.getTextDocumentService().codeAction(new CodeActionParams(new TextDocumentIdentifier(toURI(src)), new Range(pos, pos), new CodeActionContext(Arrays.asList(unresolvable)))).get();
+        Optional<CodeAction> addImport =
+                codeActions.stream()
+                           .filter(Either::isRight)
+                           .map(Either::getRight)
+                           .filter(a -> "Add import for java.util.List".equals(a.getTitle()))
+                           .findAny();
+        assertTrue(addImport.isPresent());
+        assertEquals(addImport.get().getKind(), CodeActionKind.QuickFix);
+        List<Either<TextDocumentEdit, ResourceOperation>> changes = addImport.get().getEdit().getDocumentChanges();
+        assertEquals(1, changes.size());
+        assertTrue(changes.get(0).isLeft());
+        TextDocumentEdit edit = changes.get(0).getLeft();
+        assertEquals(edit.getTextDocument().getUri(), uri);
+        List<TextEdit> fileChanges = edit.getEdits();
+        assertNotNull(fileChanges);
+        assertEquals(1, fileChanges.size());
+        assertEquals(new Range(new Position(0, 0),
+                               new Position(0, 0)),
+                     fileChanges.get(0).getRange());
+        assertEquals("\nimport java.util.List;\n\n",
+                     fileChanges.get(0).getNewText());
     }
 
     public void testFindUsages() throws Exception {
@@ -3680,7 +3700,7 @@ public class ServerTest extends NbTestCase {
 
             @Override
             public CompletableFuture<String> showHtmlPage(HtmlPageParams params) {
-                MoveElementUI ui = MockHtmlViewer.assertDialogShown(params.getUri(), MoveElementUI.class);
+                MoveElementUI ui = MockHtmlViewer.assertDialogShown(params.getId(), MoveElementUI.class);
                 ui.setSelectedProject(ui.getAvailableProjects().get(0));
                 ui.setSelectedRoot(ui.getAvailableRoots().get(0));
                 ui.setSelectedPackage(ui.getAvailablePackages().get(2));
@@ -3795,7 +3815,7 @@ public class ServerTest extends NbTestCase {
 
             @Override
             public CompletableFuture<String> showHtmlPage(HtmlPageParams params) {
-                MoveElementUI ui = MockHtmlViewer.assertDialogShown(params.getUri(), MoveElementUI.class);
+                MoveElementUI ui = MockHtmlViewer.assertDialogShown(params.getId(), MoveElementUI.class);
                 ui.setSelectedProject(ui.getAvailableProjects().get(0));
                 ui.setSelectedRoot(ui.getAvailableRoots().get(0));
                 ui.setSelectedPackage(ui.getAvailablePackages().get(1));
@@ -4369,7 +4389,7 @@ public class ServerTest extends NbTestCase {
 
             @Override
             public CompletableFuture<String> showHtmlPage(HtmlPageParams params) {
-                ChangeMethodParameterUI ui = MockHtmlViewer.assertDialogShown(params.getUri(), ChangeMethodParameterUI.class);
+                ChangeMethodParameterUI ui = MockHtmlViewer.assertDialogShown(params.getId(), ChangeMethodParameterUI.class);
                 ui.getParameters().add(1, new ParameterUI("int", "cnt"));
                 ui.doRefactoring();
                 return CompletableFuture.completedFuture(null);
diff --git a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/ui/MockHtmlViewer.java b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/ui/MockHtmlViewer.java
index 80a3da43da..21664ee9cb 100644
--- a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/ui/MockHtmlViewer.java
+++ b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/ui/MockHtmlViewer.java
@@ -54,12 +54,12 @@ public final class MockHtmlViewer extends AbstractLspHtmlViewer {
                 MockTech.exception(ctx, ex);
             }
             data.put(key, ctx);
-            ui.showHtmlPage(new HtmlPageParams(key));
+            ui.showHtmlPage(new HtmlPageParams(key, null));
         });
     }
 
-    public static <T> T assertDialogShown(String uri, Class<T> clazz) {
-        Object v = MockTech.applied(data.get(uri));
+    public static <T> T assertDialogShown(String id, Class<T> clazz) {
+        Object v = MockTech.applied(data.get(id));
         if (v instanceof Exception) {
             throw new AssertionError((Exception)v);
         }
diff --git a/java/java.lsp.server/vscode/package-lock.json b/java/java.lsp.server/vscode/package-lock.json
index ed049ec05e..99c5d0a6ae 100644
--- a/java/java.lsp.server/vscode/package-lock.json
+++ b/java/java.lsp.server/vscode/package-lock.json
@@ -19,6 +19,7 @@
 				"@types/node": "^13.11.0",
 				"@types/ps-node": "^0.1.0",
 				"@types/vscode": "^1.67.0",
+				"@vscode/codicons": "0.0.29",
 				"glob": "^7.1.6",
 				"mocha": "^9.1.2",
 				"ps-node": "^0.1.6",
@@ -69,6 +70,12 @@
 			"dev": true,
 			"license": "ISC"
 		},
+		"node_modules/@vscode/codicons": {
+			"version": "0.0.29",
+			"resolved": "https://registry.npmjs.org/@vscode/codicons/-/codicons-0.0.29.tgz",
+			"integrity": "sha512-AXhTv1nl3r4W5DqAfXXKiawQNW+tLBNlXn/GcsnFCL0j17sQ2AY+az9oB9K6wjkibq1fndNJvmT8RYN712Fdww==",
+			"dev": true
+		},
 		"node_modules/@vscode/debugadapter": {
 			"version": "1.55.1",
 			"resolved": "https://registry.npmjs.org/@vscode/debugadapter/-/debugadapter-1.55.1.tgz",
@@ -1142,6 +1149,12 @@
 			"version": "1.1.2",
 			"dev": true
 		},
+		"@vscode/codicons": {
+			"version": "0.0.29",
+			"resolved": "https://registry.npmjs.org/@vscode/codicons/-/codicons-0.0.29.tgz",
+			"integrity": "sha512-AXhTv1nl3r4W5DqAfXXKiawQNW+tLBNlXn/GcsnFCL0j17sQ2AY+az9oB9K6wjkibq1fndNJvmT8RYN712Fdww==",
+			"dev": true
+		},
 		"@vscode/debugadapter": {
 			"version": "1.55.1",
 			"resolved": "https://registry.npmjs.org/@vscode/debugadapter/-/debugadapter-1.55.1.tgz",
diff --git a/java/java.lsp.server/vscode/package.json b/java/java.lsp.server/vscode/package.json
index 7658d06858..6769543fa4 100644
--- a/java/java.lsp.server/vscode/package.json
+++ b/java/java.lsp.server/vscode/package.json
@@ -1001,6 +1001,7 @@
 		"apisupport": "node ./out/nbcode.js -J-Dnetbeans.close=true --modules --install '(org.netbeans.libs.xerces|org.netbeans.modules.editor.structure|org.netbeans.modules.xml|org.netbeans.modules.xml.axi|org.netbeans.modules.xml.retriever|org.netbeans.modules.xml.schema.model|org.netbeans.modules.xml.tax|org.netbeans.modules.xml.text|org.netbeans.modules.ant.browsetask|.*apisupport.*|org.netbeans.modules.debugger.jpda.ant)' && node ./out/nbcode.js -J-Dnetbeans.close=true --modules --enable  [...]
 	},
 	"devDependencies": {
+		"@vscode/codicons": "0.0.29",
 		"@types/glob": "^7.1.1",
 		"@types/mocha": "^9.0.0",
 		"@types/node": "^13.11.0",
diff --git a/java/java.lsp.server/vscode/src/extension.ts b/java/java.lsp.server/vscode/src/extension.ts
index 0bbe6daf70..4198f424a0 100644
--- a/java/java.lsp.server/vscode/src/extension.ts
+++ b/java/java.lsp.server/vscode/src/extension.ts
@@ -48,7 +48,7 @@ import * as launcher from './nbcode';
 import {NbTestAdapter} from './testAdapter';
 import { asRanges, StatusMessageRequest, ShowStatusMessageParams, QuickPickRequest, InputBoxRequest, MutliStepInputRequest, TestProgressNotification, DebugConnector,
          TextEditorDecorationCreateRequest, TextEditorDecorationSetNotification, TextEditorDecorationDisposeNotification, HtmlPageRequest, HtmlPageParams,
-         SetTextEditorDecorationParams, ProjectActionParams, UpdateConfigurationRequest, QuickPickStep, InputBoxStep
+         ExecInHtmlPageRequest, SetTextEditorDecorationParams, ProjectActionParams, UpdateConfigurationRequest, QuickPickStep, InputBoxStep
 } from './protocol';
 import * as launchConfigurations from './launchConfigurations';
 import { createTreeViewService, TreeViewService, TreeItemDecorator, Visualizer, CustomizableTreeDataProvider } from './explorer';
@@ -83,7 +83,7 @@ export class NbLanguageClient extends LanguageClient {
         this._treeViewService.dispose();
         return r;
     }
-    
+
 }
 
 function handleLog(log: vscode.OutputChannel, msg: string): void {
@@ -232,7 +232,7 @@ function contextUri(ctx : any) : vscode.Uri | undefined {
 /**
  * Executes a project action. It is possible to provide an explicit configuration to use (or undefined), display output from the action etc.
  * Arguments are attempted to parse as file or editor references or Nodes; otherwise they are attempted to be passed to the action as objects.
- * 
+ *
  * @param action ID of the project action to run
  * @param configuration configuration to use or undefined - use default/active one.
  * @param title Title for the progress displayed in vscode
@@ -267,7 +267,7 @@ function wrapCommandWithProgress(lsCommand : string, title : string, log? : vsco
             const commands = await vscode.commands.getCommands();
             if (commands.includes(lsCommand)) {
                 p.report({ message: title });
-                c.outputChannel.show(true); 
+                c.outputChannel.show(true);
                 const start = new Date().getTime();
                 if (log) {
                     handleLog(log, `starting ${lsCommand}`);
@@ -326,7 +326,7 @@ export function activate(context: ExtensionContext): VSNetBeansAPI {
                 activateWithJDK(specifiedJDK, context, log, true);
             }
         }));
-        activateWithJDK(specifiedJDK, context, log, true);  
+        activateWithJDK(specifiedJDK, context, log, true);
     });
 
     //register debugger:
@@ -855,6 +855,7 @@ function doActivateWithJDK(specifiedJDK: string | null, context: ExtensionContex
             }
             c.onNotification(StatusMessageRequest.type, showStatusBarMessage);
             c.onRequest(HtmlPageRequest.type, showHtmlPage);
+            c.onRequest(ExecInHtmlPageRequest.type, execInHtmlPage);
             c.onNotification(LogMessageNotification.type, (param) => handleLog(log, param.message));
             c.onRequest(QuickPickRequest.type, async param => {
                 const selected = await window.showQuickPick(param.items, { title: param.title, placeHolder: param.placeHolder, canPickMany: param.canPickMany });
@@ -1012,13 +1013,13 @@ function doActivateWithJDK(specifiedJDK: string | null, context: ExtensionContex
 
     function createDatabaseView(c : NbLanguageClient) {
         let decoRegister : CustomizableTreeDataProvider<Visualizer>;
-        c.findTreeViewService().createView('database.connections', undefined , { 
-            canSelectMany : true,  
-            
-            providerInitializer : (customizable) => 
+        c.findTreeViewService().createView('database.connections', undefined , {
+            canSelectMany : true,
+
+            providerInitializer : (customizable) =>
                 customizable.addItemDecorator(new Decorator(customizable, c))
         });
-        
+
     }
 
     async function createProjectView(ctx : ExtensionContext, client : NbLanguageClient) {
@@ -1050,50 +1051,61 @@ function doActivateWithJDK(specifiedJDK: string | null, context: ExtensionContex
         }
     }
 
-    async function showHtmlPage(params : HtmlPageParams): Promise<string> {
-        function showUri(url: string, ok: any, err: any) {
-            let uri = vscode.Uri.parse(url);
-            var http = require('http');
-
-            let host = uri.authority.split(":")[0];
-            let port = uri.authority.split(":")[1];
-
-            var options = {
-                host: host,
-                port: port,
-                path: uri.path
+    const webviews = new Map<string, vscode.Webview>();
+
+    async function showHtmlPage(params : HtmlPageParams): Promise<void> {
+        return new Promise(resolve => {
+            let data = params.text;
+            const match = /<title>(.*)<\/title>/i.exec(data);
+            const name = match && match.length > 1 ? match[1] : '';
+            const resourceDir = vscode.Uri.joinPath(context.globalStorageUri, params.id);
+            workspace.fs.createDirectory(resourceDir);
+            let view = vscode.window.createWebviewPanel('htmlView', name, vscode.ViewColumn.Beside, {
+                enableScripts: true,
+                localResourceRoots: [resourceDir, vscode.Uri.joinPath(context.extensionUri, 'node_modules', '@vscode/codicons', 'dist')]
+            });
+            webviews.set(params.id, view.webview);
+            const resources = params.resources;
+            if (resources) {
+                for (const resourceName in resources) {
+                    const resourceText = resources[resourceName];
+                    const resourceUri = vscode.Uri.joinPath(resourceDir, resourceName);
+                    workspace.fs.writeFile(resourceUri, Buffer.from(resourceText, 'utf8'));
+                    data = data.replace('href="' + resourceName + '"', 'href="' + view.webview.asWebviewUri(resourceUri) + '"');
+                }
             }
-            var request = http.request(options, function(res: any) {
-                var data = '';
-                res.on('data', function(chunk: any) {
-                    data += chunk;
-                });
-                res.on('end', function() {
-                    const match = /<title>(.*)<\/title>/i.exec(data);
-                    const name = match && match.length > 1 ? match[1] : ''
-                    let view = vscode.window.createWebviewPanel('htmlView', name, vscode.ViewColumn.Beside, {
-                        enableScripts: true,
-                    });
-                    view.webview.html = data.replace("<head>", `<head><base href="${url}">`);
-                    view.webview.onDidReceiveMessage(message => {
-                        switch (message.command) {
-                            case 'dispose':
-                                view.dispose();
-                                break;
-                        }
-                    });
-                    view.onDidDispose(() => {
-                        ok(null);
-                    });
-                });
+            const codiconsUri = view.webview.asWebviewUri(vscode.Uri.joinPath(context.extensionUri, 'node_modules', '@vscode/codicons', 'dist', 'codicon.css'));
+            view.webview.html = data.replace('href="codicon.css"', 'href="' + codiconsUri + '"');
+            view.webview.onDidReceiveMessage(message => {
+                switch (message.command) {
+                    case 'dispose':
+                        webviews.delete(params.id);
+                        view.dispose();
+                        break;
+                    case 'command':
+                        vscode.commands.executeCommand('nb.htmlui.process.command', message.data);
+                        break;
+                }
             });
-            request.on('error', function(e: any) {
-                err(e);
+            view.onDidDispose(() => {
+                resolve();
+                workspace.fs.delete(resourceDir, {recursive: true});
             });
-            request.end();
-        }
-        return new Promise((ok, err) => {
-            showUri(params.uri, ok, err);
+        });
+    }
+
+    async function execInHtmlPage(params : HtmlPageParams): Promise<boolean> {
+        return new Promise(resolve => {
+            const webview = webviews.get(params.id);
+            if (webview) {
+                webview.postMessage({
+                    execScript: params.text,
+                    pause: params.pause
+                }).then(ret => {
+                    resolve(ret);
+                });
+            }
+            resolve(false);
         });
     }
 
diff --git a/java/java.lsp.server/vscode/src/protocol.ts b/java/java.lsp.server/vscode/src/protocol.ts
index bf72ffa1e2..0e867b3fed 100644
--- a/java/java.lsp.server/vscode/src/protocol.ts
+++ b/java/java.lsp.server/vscode/src/protocol.ts
@@ -33,11 +33,20 @@ import {
 } from 'vscode-languageserver-protocol';
 
 export interface HtmlPageParams {
-    uri: string;
+    id: string;
+    text: string;
+    pause: boolean;
+    resources?: {
+        [name: string]: string;
+    };
 }
 
 export namespace HtmlPageRequest {
-    export const type = new ProtocolRequestType<HtmlPageParams, string, never, void, void>('window/showHtmlPage');
+    export const type = new ProtocolRequestType<HtmlPageParams, void, never, void, void>('window/showHtmlPage');
+};
+
+export namespace ExecInHtmlPageRequest {
+    export const type = new ProtocolRequestType<HtmlPageParams, boolean, never, void, void>('window/execInHtmlPage');
 };
 
 export interface ShowStatusMessageParams extends ShowMessageParams {
diff --git a/platform/api.htmlui/src/org/netbeans/api/htmlui/HTMLDialog.java b/platform/api.htmlui/src/org/netbeans/api/htmlui/HTMLDialog.java
index cc353e2832..767e23c72f 100644
--- a/platform/api.htmlui/src/org/netbeans/api/htmlui/HTMLDialog.java
+++ b/platform/api.htmlui/src/org/netbeans/api/htmlui/HTMLDialog.java
@@ -53,7 +53,7 @@ import org.netbeans.modules.htmlui.HTMLDialogBase;
  * into it. When the page is
  * loaded, it calls back the method {@code AskQuestion.showHelloWorld}
  * and passes it
- * its own arguments. The method is supposed to make the page live, preferrably
+ * its own arguments. The method is supposed to make the page live, preferably
  * by using {@link net.java.html.json.Model} generated class and calling
  * <code>applyBindings()</code> on it. The method is suggested to return
  * an instance of {@link OnSubmit} callback to be notified about user pressing
@@ -83,13 +83,23 @@ public @interface HTMLDialog {
      * Will be resolved by the annotation processor and converted into
      * <code>nbresloc</code> protocol - as such the HTML page can be L10Ned
      * later by adding classical L10N suffixes. E.g. <code>index_cs.html</code>
-     * will take preceedence over <code>index.html</code> if the user is
+     * will take precedence over <code>index.html</code> if the user is
      * running in Czech {@link Locale}.
      *
-     * @return relative path the HTML page
+     * @return relative path to the HTML page
      */
     String url();
 
+    /** List of resources to make available for the {@link #url()} page.
+     * The rendering system shall make sure these resources are available when
+     * the {@link #url() main page} is loaded and are at the same relative
+     * locations like the page.
+     *
+     * @return list of resources
+     * @since 1.25
+     */
+    String[] resources() default {};
+
     /** Name of the file to generate the method that opens the dialog
      * into. Class of such name will be generated into the same
      * package.
@@ -138,6 +148,7 @@ public @interface HTMLDialog {
      */
     public static final class Builder {
         private final String url;
+        private List<String> resources = new ArrayList<>();
         private List<String> techIds = new ArrayList<>();
         private Runnable onPageLoad;
 
@@ -168,6 +179,20 @@ public @interface HTMLDialog {
             return this;
         }
 
+        /** Registers resources to be available for the {@link #url()} page.
+         * The rendering system shall make sure these resources are available when
+         * the {@link #url() main page} is loaded and are at the same relative
+         * locations like the page.
+         *
+         * @param res list of resources to add to the builder
+         * @return instance of the builder
+         * @since 1.25
+         */
+        public Builder addResources(String... res) {
+            resources.addAll(Arrays.asList(res));
+            return this;
+        }
+
         /** Requests some of provided technologies. The HTML/Java API @ version 1.1
          * supports {@link Id technology ids}. One can specify the preferred ones
          * to use in this NetBeans component by using calling this method.
@@ -188,7 +213,7 @@ public @interface HTMLDialog {
          *   if the dialog was closed without selecting a button
          */
         public String showAndWait() {
-            HTMLDialogBase impl = HTMLDialogBase.create(url, onPageLoad, null, techIds.toArray(new String[0]), null);
+            HTMLDialogBase impl = HTMLDialogBase.create(url, resources.toArray(new String[0]), onPageLoad, null, techIds.toArray(new String[0]), null);
             return impl.showAndWait();
         }
 
@@ -199,7 +224,7 @@ public @interface HTMLDialog {
          * @since 1.23
          */
         public void show(OnSubmit s) {
-            HTMLDialogBase impl = HTMLDialogBase.create(url, onPageLoad, s, techIds.toArray(new String[0]), null);
+            HTMLDialogBase impl = HTMLDialogBase.create(url, resources.toArray(new String[0]), onPageLoad, s, techIds.toArray(new String[0]), null);
             impl.show(s);
         }
 
@@ -213,7 +238,7 @@ public @interface HTMLDialog {
          * @return instance of the requested component
          */
         public <C> C component(Class<C> type) {
-            HTMLDialogBase impl = HTMLDialogBase.create(url, onPageLoad, null, techIds.toArray(new String[0]), type);
+            HTMLDialogBase impl = HTMLDialogBase.create(url, resources.toArray(new String[0]), onPageLoad, null, techIds.toArray(new String[0]), type);
             return impl.component(type);
         }
     }
diff --git a/platform/api.htmlui/src/org/netbeans/modules/htmlui/Buttons.java b/platform/api.htmlui/src/org/netbeans/modules/htmlui/Buttons.java
index 50a7408ba2..f1f132da40 100644
--- a/platform/api.htmlui/src/org/netbeans/modules/htmlui/Buttons.java
+++ b/platform/api.htmlui/src/org/netbeans/modules/htmlui/Buttons.java
@@ -158,7 +158,7 @@ class Buttons<View, Button> {
         return null;
     }
 
-    @JavaScriptBody(args = {}, body = "window.close();")
+    @JavaScriptBody(args = {}, wait4js = false, body = "window.close();")
     private static void closeWindow0() {
     }
 
diff --git a/platform/api.htmlui/src/org/netbeans/modules/htmlui/ContextAccessor.java b/platform/api.htmlui/src/org/netbeans/modules/htmlui/ContextAccessor.java
index 9cda57f334..59ca7383da 100644
--- a/platform/api.htmlui/src/org/netbeans/modules/htmlui/ContextAccessor.java
+++ b/platform/api.htmlui/src/org/netbeans/modules/htmlui/ContextAccessor.java
@@ -50,7 +50,7 @@ public abstract class ContextAccessor {
     }
 
     public abstract HTMLViewerSpi.Context newContext(
-        ClassLoader loader, URL url, String[] techIds,
+        ClassLoader loader, URL url, String[] resources, String[] techIds,
         OnSubmit onSubmit, Consumer<String> lifeCycleCallback, Callable<Lookup> onPageLoad,
         Class<?> component
     );
diff --git a/platform/api.htmlui/src/org/netbeans/modules/htmlui/HTMLDialogBase.java b/platform/api.htmlui/src/org/netbeans/modules/htmlui/HTMLDialogBase.java
index c0b91832aa..174135fbf5 100644
--- a/platform/api.htmlui/src/org/netbeans/modules/htmlui/HTMLDialogBase.java
+++ b/platform/api.htmlui/src/org/netbeans/modules/htmlui/HTMLDialogBase.java
@@ -35,7 +35,7 @@ public final class HTMLDialogBase {
         this.view = view;
     }
 
-    public static HTMLDialogBase create(String url, Runnable onPageLoad, HTMLDialog.OnSubmit onSubmit, String[] techIds, Class<?> component) {
+    public static HTMLDialogBase create(String url, String[] resources, Runnable onPageLoad, HTMLDialog.OnSubmit onSubmit, String[] techIds, Class<?> component) {
         ClassLoader loader = onPageLoad.getClass().getClassLoader();
         final URL u;
         try {
@@ -88,7 +88,7 @@ public final class HTMLDialogBase {
         }
         AcceptAndInit init = new AcceptAndInit();
         HTMLViewerSpi.Context c = ContextAccessor.getDefault().newContext(
-            loader, u, techIds, onSubmit, init, init, component
+            loader, u, resources, techIds, onSubmit, init, init, component
         );
         HtmlPair<?, ?> view = HtmlPair.newView(c);
         final Buttons<?, ?> buttons = component == null ? new Buttons<>(view, onSubmit) : null;
diff --git a/platform/api.htmlui/src/org/netbeans/modules/htmlui/HTMLDialogProcessor.java b/platform/api.htmlui/src/org/netbeans/modules/htmlui/HTMLDialogProcessor.java
index db989f3554..4867ab8c70 100644
--- a/platform/api.htmlui/src/org/netbeans/modules/htmlui/HTMLDialogProcessor.java
+++ b/platform/api.htmlui/src/org/netbeans/modules/htmlui/HTMLDialogProcessor.java
@@ -166,7 +166,7 @@ implements Comparator<ExecutableElement> {
                         if (url == null) {
                             continue;
                         }
-                        generateDialog(w, ee, url, reg.techIds());
+                        generateDialog(w, ee, url, reg.resources(), reg.techIds());
                     }
                     if (comp != null) {
                         String url = findURL(comp.url(), ee);
@@ -218,7 +218,7 @@ implements Comparator<ExecutableElement> {
         return url;
     }
 
-    private void generateDialog(Writer w, ExecutableElement ee, String url, String[] techIds) throws IOException {
+    private void generateDialog(Writer w, ExecutableElement ee, String url, String[] resources, String[] techIds) throws IOException {
         TypeElement onSubmit = processingEnv.getElementUtils().getTypeElement(HTMLDialog.OnSubmit.class.getCanonicalName());
         final TypeMirror retType = ee.getReturnType();
         boolean returnsOnSubmit = retType.getKind() != TypeKind.ERROR && processingEnv.getTypeUtils().isSubtype(retType, onSubmit.asType());
@@ -277,7 +277,8 @@ implements Comparator<ExecutableElement> {
             w.append("    return ");
         }
         w.append("Builder.newDialog(\"").append(url).append("\").\n");
-        generateTechIds(w, techIds);
+        generateResources(w, "      ", resources);
+        generateTechIds(w, "      ", techIds);
         w.append("      loadFinished(impl).\n");
         if (returnsOnSubmit) {
             w.append("      show(impl);\n");
@@ -301,7 +302,7 @@ implements Comparator<ExecutableElement> {
 
         w.append(") {\n");
         w.append("    return Builder.newDialog(\"").append(url).append("\").\n");
-        generateTechIds(w, techIds);
+        generateTechIds(w, "      ", techIds);
         w.append("      loadFinished(new Runnable() {\n");
         w.append("        public void run() {\n");
         w.append("          ").append(ee.getEnclosingElement().getSimpleName())
@@ -432,10 +433,28 @@ implements Comparator<ExecutableElement> {
         }
     }
 
-    private void generateTechIds(Writer w, String[] techIds) throws IOException {
+    private void generateResources(Writer w, String prefix, String[] resources) throws IOException {
+        if (resources.length == 0) {
+            return;
+        }
+        w.append(prefix);
+        w.append("addResources(");
+        String sep = "";
+        for (String res : resources) {
+            w.append(sep);
+            w.append('"');
+            w.append(res);
+            w.append('"');
+            sep = ", ";
+        }
+        w.append(").\n");
+    }
+
+    private void generateTechIds(Writer w, String prefix, String[] techIds) throws IOException {
         if (techIds.length == 0) {
             return;
         }
+        w.append(prefix);
         w.append("addTechIds(");
         String sep = "";
         for (String id : techIds) {
diff --git a/platform/api.htmlui/src/org/netbeans/modules/htmlui/Pages.java b/platform/api.htmlui/src/org/netbeans/modules/htmlui/Pages.java
index 7bc6f8c432..132d9553d4 100644
--- a/platform/api.htmlui/src/org/netbeans/modules/htmlui/Pages.java
+++ b/platform/api.htmlui/src/org/netbeans/modules/htmlui/Pages.java
@@ -71,7 +71,7 @@ public final class Pages {
                 pageUrl = new URL("nbresloc:/" + u);
 
                 ClassLoader loader = findClassLoader();
-                HTMLViewerSpi.Context ctx = ContextAccessor.getDefault().newContext(loader, pageUrl, getTechIds(), null, null, () -> {
+                HTMLViewerSpi.Context ctx = ContextAccessor.getDefault().newContext(loader, pageUrl, new String[0], getTechIds(), null, null, () -> {
                     Method method = clazz.getMethod(methodName);
                     Object value = method.invoke(null);
                     return new PagesLookup(loader, value);
diff --git a/platform/api.htmlui/src/org/netbeans/spi/htmlui/HTMLViewerSpi.java b/platform/api.htmlui/src/org/netbeans/spi/htmlui/HTMLViewerSpi.java
index f191602080..a0d7aedb13 100644
--- a/platform/api.htmlui/src/org/netbeans/spi/htmlui/HTMLViewerSpi.java
+++ b/platform/api.htmlui/src/org/netbeans/spi/htmlui/HTMLViewerSpi.java
@@ -64,16 +64,17 @@ public interface HTMLViewerSpi<HtmlView, HtmlButton> {
             new ContextAccessor() {
                 @Override
                 public Context newContext(
-                    ClassLoader loader, URL url, String[] techIds,
+                    ClassLoader loader, URL url, String[] resources, String[] techIds,
                     OnSubmit onSubmit, Consumer<String> lifeCycleCallback, Callable<Lookup> onPageLoad,
                     Class<?> component
                 ) {
-                    return new Context(loader, url, techIds, onSubmit, lifeCycleCallback, onPageLoad, component);
+                    return new Context(loader, url, resources, techIds, onSubmit, lifeCycleCallback, onPageLoad, component);
                 }
             };
         }
         private final ClassLoader loader;
         private final URL url;
+        private final String[] resources;
         private final String[] techIds;
         private final OnSubmit onSubmit;
         private final Consumer<String> lifeCycleCallback;
@@ -81,12 +82,13 @@ public interface HTMLViewerSpi<HtmlView, HtmlButton> {
         private final Class<?> component;
 
         private Context(
-            ClassLoader loader, URL url, String[] techIds,
+            ClassLoader loader, URL url, String[] resources, String[] techIds,
             OnSubmit onSubmit, Consumer<String> lifeCycleCallback,
             Callable<Lookup> onPageLoad, Class<?> component
         ) {
             this.loader = loader;
             this.url = url;
+            this.resources = resources;
             this.techIds = techIds;
             this.onSubmit = onSubmit;
             this.lifeCycleCallback = lifeCycleCallback;
@@ -190,6 +192,16 @@ public interface HTMLViewerSpi<HtmlView, HtmlButton> {
             return loader;
         }
 
+        /** List of resources available to the page. Resources are at the same relative
+         * locations like the page.
+         *
+         * @return resources used in the page displayed by the HTML user interface
+         * @since 1.25
+         */
+        public String[] getResources() {
+            return resources.clone();
+        }
+
         /** Set of technologies to prefer.
          *
          * @return IDs of technologies to prefer in the HTML user interface
diff --git a/platform/net.java.html.boot.fx/external/binaries-list b/platform/net.java.html.boot.fx/external/binaries-list
index 75db770f1e..930c2ef89e 100644
--- a/platform/net.java.html.boot.fx/external/binaries-list
+++ b/platform/net.java.html.boot.fx/external/binaries-list
@@ -14,4 +14,4 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-10F1724D618C0F0BA57D0CB849A0C6463A8C3F03 org.netbeans.html:net.java.html.boot.fx:1.7.3
+C9F572D958D575A30B9D3905CD8D0BE27C4C8424 org.netbeans.html:net.java.html.boot.fx:1.8.1
diff --git a/platform/net.java.html.boot.fx/external/net.java.html.boot.fx-1.7.3-license.txt b/platform/net.java.html.boot.fx/external/net.java.html.boot.fx-1.8.1-license.txt
similarity index 99%
rename from platform/net.java.html.boot.fx/external/net.java.html.boot.fx-1.7.3-license.txt
rename to platform/net.java.html.boot.fx/external/net.java.html.boot.fx-1.8.1-license.txt
index 76cb5d13c4..4ff309299f 100644
--- a/platform/net.java.html.boot.fx/external/net.java.html.boot.fx-1.7.3-license.txt
+++ b/platform/net.java.html.boot.fx/external/net.java.html.boot.fx-1.8.1-license.txt
@@ -1,5 +1,5 @@
 Name: Html4J
-Version: 1.7.3
+Version: 1.8.1
 Description: Html4j Boot FX
 License: Apache-2.0
 Origin: Apache Software Foundation
diff --git a/platform/net.java.html.boot.fx/nbproject/project.properties b/platform/net.java.html.boot.fx/nbproject/project.properties
index 4eaf3930d9..3c7810ed10 100644
--- a/platform/net.java.html.boot.fx/nbproject/project.properties
+++ b/platform/net.java.html.boot.fx/nbproject/project.properties
@@ -14,6 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-release.external/net.java.html.boot.fx-1.7.3.jar=modules/net-java-html-boot-fx.jar
+release.external/net.java.html.boot.fx-1.8.1.jar=modules/net-java-html-boot-fx.jar
 is.autoload=true
 nbm.module.author=Jaroslav Tulach
diff --git a/platform/net.java.html.boot.fx/nbproject/project.xml b/platform/net.java.html.boot.fx/nbproject/project.xml
index efebe1f6c8..626c2de618 100644
--- a/platform/net.java.html.boot.fx/nbproject/project.xml
+++ b/platform/net.java.html.boot.fx/nbproject/project.xml
@@ -28,7 +28,7 @@
            <public-packages/>
            <class-path-extension>
                <runtime-relative-path>net-java-html-boot-fx.jar</runtime-relative-path>
-               <binary-origin>external/net.java.html.boot.fx-1.7.3.jar</binary-origin>
+               <binary-origin>external/net.java.html.boot.fx-1.8.1.jar</binary-origin>
             </class-path-extension>
         </data>
     </configuration>
diff --git a/platform/net.java.html.boot.script/external/binaries-list b/platform/net.java.html.boot.script/external/binaries-list
index 1c9a9ff8c0..5cec73cfa4 100644
--- a/platform/net.java.html.boot.script/external/binaries-list
+++ b/platform/net.java.html.boot.script/external/binaries-list
@@ -14,4 +14,4 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-30B5376222E678298714053EDEA38AD13AEF1DB8 org.netbeans.html:net.java.html.boot.script:1.7.3
+5C2BDFE7060771991975C7E316365D93BC3FCBF6 org.netbeans.html:net.java.html.boot.script:1.8.1
diff --git a/platform/net.java.html.boot.script/external/net.java.html.boot.script-1.7.3-license.txt b/platform/net.java.html.boot.script/external/net.java.html.boot.script-1.8.1-license.txt
similarity index 99%
rename from platform/net.java.html.boot.script/external/net.java.html.boot.script-1.7.3-license.txt
rename to platform/net.java.html.boot.script/external/net.java.html.boot.script-1.8.1-license.txt
index cb1a4f8d98..8a15a5ef2b 100644
--- a/platform/net.java.html.boot.script/external/net.java.html.boot.script-1.7.3-license.txt
+++ b/platform/net.java.html.boot.script/external/net.java.html.boot.script-1.8.1-license.txt
@@ -1,5 +1,5 @@
 Name: Html4J
-Version: 1.7.3
+Version: 1.8.1
 Description: Html4j Boot Script
 License: Apache-2.0
 Origin: Apache Software Foundation
diff --git a/platform/net.java.html.boot.script/nbproject/project.properties b/platform/net.java.html.boot.script/nbproject/project.properties
index ed6576acc9..465722e555 100644
--- a/platform/net.java.html.boot.script/nbproject/project.properties
+++ b/platform/net.java.html.boot.script/nbproject/project.properties
@@ -14,6 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-release.external/net.java.html.boot.script-1.7.3.jar=modules/net-java-html-boot-script.jar
+release.external/net.java.html.boot.script-1.8.1.jar=modules/net-java-html-boot-script.jar
 is.autoload=true
 nbm.module.author=Jaroslav Tulach
diff --git a/platform/net.java.html.boot.script/nbproject/project.xml b/platform/net.java.html.boot.script/nbproject/project.xml
index 398605b5fc..395069fde6 100644
--- a/platform/net.java.html.boot.script/nbproject/project.xml
+++ b/platform/net.java.html.boot.script/nbproject/project.xml
@@ -28,7 +28,7 @@
            <public-packages/>
            <class-path-extension>
                <runtime-relative-path>net-java-html-boot-script.jar</runtime-relative-path>
-               <binary-origin>external/net.java.html.boot.script-1.7.3.jar</binary-origin>
+               <binary-origin>external/net.java.html.boot.script-1.8.1.jar</binary-origin>
             </class-path-extension>
         </data>
     </configuration>
diff --git a/platform/net.java.html.boot/external/binaries-list b/platform/net.java.html.boot/external/binaries-list
index 6864fdee2d..7805860dc9 100644
--- a/platform/net.java.html.boot/external/binaries-list
+++ b/platform/net.java.html.boot/external/binaries-list
@@ -14,4 +14,4 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-F4320C98E15B3DB8C6F7468FF23B1CA929087471 org.netbeans.html:net.java.html.boot:1.7.3
+9AC46A04EA250DEE9771414D85BC2D5946B4DD6B org.netbeans.html:net.java.html.boot:1.8.1
diff --git a/platform/net.java.html.boot/external/net.java.html.boot-1.7.3-license.txt b/platform/net.java.html.boot/external/net.java.html.boot-1.8.1-license.txt
similarity index 99%
rename from platform/net.java.html.boot/external/net.java.html.boot-1.7.3-license.txt
rename to platform/net.java.html.boot/external/net.java.html.boot-1.8.1-license.txt
index dbc1573f29..97757d4172 100644
--- a/platform/net.java.html.boot/external/net.java.html.boot-1.7.3-license.txt
+++ b/platform/net.java.html.boot/external/net.java.html.boot-1.8.1-license.txt
@@ -1,5 +1,5 @@
 Name: Html4J
-Version: 1.7.3
+Version: 1.8.1
 Description: Html4j Boot
 License: Apache-2.0
 Origin: Apache Software Foundation
diff --git a/platform/net.java.html.boot/nbproject/project.properties b/platform/net.java.html.boot/nbproject/project.properties
index 0d7e770527..6e091f2bf9 100644
--- a/platform/net.java.html.boot/nbproject/project.properties
+++ b/platform/net.java.html.boot/nbproject/project.properties
@@ -14,6 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-release.external/net.java.html.boot-1.7.3.jar=modules/net-java-html-boot.jar
+release.external/net.java.html.boot-1.8.1.jar=modules/net-java-html-boot.jar
 is.autoload=true
 nbm.module.author=Jaroslav Tulach
diff --git a/platform/net.java.html.boot/nbproject/project.xml b/platform/net.java.html.boot/nbproject/project.xml
index a8222f32fb..032b450e2f 100644
--- a/platform/net.java.html.boot/nbproject/project.xml
+++ b/platform/net.java.html.boot/nbproject/project.xml
@@ -28,7 +28,7 @@
            <public-packages/>
            <class-path-extension>
                <runtime-relative-path>net-java-html-boot.jar</runtime-relative-path>
-               <binary-origin>external/net.java.html.boot-1.7.3.jar</binary-origin>
+               <binary-origin>external/net.java.html.boot-1.8.1.jar</binary-origin>
             </class-path-extension>
         </data>
     </configuration>
diff --git a/platform/net.java.html.geo/external/binaries-list b/platform/net.java.html.geo/external/binaries-list
index d457c67283..a164e88f61 100644
--- a/platform/net.java.html.geo/external/binaries-list
+++ b/platform/net.java.html.geo/external/binaries-list
@@ -14,4 +14,4 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-7AE5571DACE8CAD67E894A1EAB92F0B295587992 org.netbeans.html:net.java.html.geo:1.7.3
+D5D0DE122EAA3E2882AFCAA3614A697EDEFE7230 org.netbeans.html:net.java.html.geo:1.8.1
diff --git a/platform/net.java.html.geo/external/net.java.html.geo-1.7.3-license.txt b/platform/net.java.html.geo/external/net.java.html.geo-1.8.1-license.txt
similarity index 99%
rename from platform/net.java.html.geo/external/net.java.html.geo-1.7.3-license.txt
rename to platform/net.java.html.geo/external/net.java.html.geo-1.8.1-license.txt
index 549582c0d5..99de38dd48 100644
--- a/platform/net.java.html.geo/external/net.java.html.geo-1.7.3-license.txt
+++ b/platform/net.java.html.geo/external/net.java.html.geo-1.8.1-license.txt
@@ -1,5 +1,5 @@
 Name: Html4J Geolocation API
-Version: 1.7.3
+Version: 1.8.1
 Description: Html4j Geolocation API
 License: Apache-2.0
 Origin: Apache Software Foundation
diff --git a/platform/net.java.html.geo/nbproject/project.properties b/platform/net.java.html.geo/nbproject/project.properties
index 1141f732e1..30f01f6b6b 100644
--- a/platform/net.java.html.geo/nbproject/project.properties
+++ b/platform/net.java.html.geo/nbproject/project.properties
@@ -14,6 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-release.external/net.java.html.geo-1.7.3.jar=modules/net-java-html-geo.jar
+release.external/net.java.html.geo-1.8.1.jar=modules/net-java-html-geo.jar
 is.autoload=true
 nbm.module.author=Jaroslav Tulach
diff --git a/platform/net.java.html.geo/nbproject/project.xml b/platform/net.java.html.geo/nbproject/project.xml
index 412ad4896e..e06a72e6ba 100644
--- a/platform/net.java.html.geo/nbproject/project.xml
+++ b/platform/net.java.html.geo/nbproject/project.xml
@@ -28,7 +28,7 @@
            <public-packages/>
            <class-path-extension>
                <runtime-relative-path>net-java-html-geo.jar</runtime-relative-path>
-               <binary-origin>external/net.java.html.geo-1.7.3.jar</binary-origin>
+               <binary-origin>external/net.java.html.geo-1.8.1.jar</binary-origin>
             </class-path-extension>
         </data>
     </configuration>
diff --git a/platform/net.java.html.json/external/binaries-list b/platform/net.java.html.json/external/binaries-list
index a385952a4a..71474e013d 100644
--- a/platform/net.java.html.json/external/binaries-list
+++ b/platform/net.java.html.json/external/binaries-list
@@ -14,4 +14,4 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-F52F8CFEA7C7A74CB9DB31BB12B4FF4075A94811 org.netbeans.html:net.java.html.json:1.7.3
+FE22FD2285C100120EC0A0CD0D47B2296BD39604 org.netbeans.html:net.java.html.json:1.8.1
diff --git a/platform/net.java.html.json/external/net.java.html.json-1.7.3-license.txt b/platform/net.java.html.json/external/net.java.html.json-1.8.1-license.txt
similarity index 99%
rename from platform/net.java.html.json/external/net.java.html.json-1.7.3-license.txt
rename to platform/net.java.html.json/external/net.java.html.json-1.8.1-license.txt
index 9066601d29..b92dfa4bdd 100644
--- a/platform/net.java.html.json/external/net.java.html.json-1.7.3-license.txt
+++ b/platform/net.java.html.json/external/net.java.html.json-1.8.1-license.txt
@@ -1,5 +1,5 @@
 Name: Html4J JSON Model in Java
-Version: 1.7.3
+Version: 1.8.1
 Description: Html4j JSON Model in Java
 License: Apache-2.0
 Origin: Apache Software Foundation
diff --git a/platform/net.java.html.json/nbproject/project.properties b/platform/net.java.html.json/nbproject/project.properties
index e313fd9120..f3a66f26aa 100644
--- a/platform/net.java.html.json/nbproject/project.properties
+++ b/platform/net.java.html.json/nbproject/project.properties
@@ -14,6 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-release.external/net.java.html.json-1.7.3.jar=modules/net-java-html-json.jar
+release.external/net.java.html.json-1.8.1.jar=modules/net-java-html-json.jar
 is.autoload=true
 nbm.module.author=Jaroslav Tulach
diff --git a/platform/net.java.html.json/nbproject/project.xml b/platform/net.java.html.json/nbproject/project.xml
index 83e912c8dc..024a84a365 100644
--- a/platform/net.java.html.json/nbproject/project.xml
+++ b/platform/net.java.html.json/nbproject/project.xml
@@ -28,7 +28,7 @@
            <public-packages/>
            <class-path-extension>
                <runtime-relative-path>net-java-html-json.jar</runtime-relative-path>
-               <binary-origin>external/net.java.html.json-1.7.3.jar</binary-origin>
+               <binary-origin>external/net.java.html.json-1.8.1.jar</binary-origin>
             </class-path-extension>
         </data>
     </configuration>
diff --git a/platform/net.java.html.sound/external/binaries-list b/platform/net.java.html.sound/external/binaries-list
index c26f9dc7a3..0a0f624b7e 100644
--- a/platform/net.java.html.sound/external/binaries-list
+++ b/platform/net.java.html.sound/external/binaries-list
@@ -14,4 +14,4 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-AFBA69B9F15BC582FC0D888C1154C52D45557DFF org.netbeans.html:net.java.html.sound:1.7.3
+52EF597617DC398FEA5B894F2BB64025254820F0 org.netbeans.html:net.java.html.sound:1.8.1
diff --git a/platform/net.java.html.sound/external/net.java.html.sound-1.7.3-license.txt b/platform/net.java.html.sound/external/net.java.html.sound-1.8.1-license.txt
similarity index 99%
rename from platform/net.java.html.sound/external/net.java.html.sound-1.7.3-license.txt
rename to platform/net.java.html.sound/external/net.java.html.sound-1.8.1-license.txt
index 45351b508b..d4ab83e07b 100644
--- a/platform/net.java.html.sound/external/net.java.html.sound-1.7.3-license.txt
+++ b/platform/net.java.html.sound/external/net.java.html.sound-1.8.1-license.txt
@@ -1,5 +1,5 @@
 Name: Html4J Sound API via HTML
-Version: 1.7.3
+Version: 1.8.1
 Description: Html4j Sound API via HTML
 License: Apache-2.0
 Origin: Apache Software Foundation
diff --git a/platform/net.java.html.sound/nbproject/project.properties b/platform/net.java.html.sound/nbproject/project.properties
index 7063616ac5..3d429c5da8 100644
--- a/platform/net.java.html.sound/nbproject/project.properties
+++ b/platform/net.java.html.sound/nbproject/project.properties
@@ -14,6 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-release.external/net.java.html.sound-1.7.3.jar=modules/net-java-html-sound.jar
+release.external/net.java.html.sound-1.8.1.jar=modules/net-java-html-sound.jar
 is.autoload=true
 nbm.module.author=Jaroslav Tulach
diff --git a/platform/net.java.html.sound/nbproject/project.xml b/platform/net.java.html.sound/nbproject/project.xml
index 4f614c6caa..c900e043a8 100644
--- a/platform/net.java.html.sound/nbproject/project.xml
+++ b/platform/net.java.html.sound/nbproject/project.xml
@@ -28,7 +28,7 @@
            <public-packages/>
            <class-path-extension>
                <runtime-relative-path>net-java-html-sound.jar</runtime-relative-path>
-               <binary-origin>external/net.java.html.sound-1.7.3.jar</binary-origin>
+               <binary-origin>external/net.java.html.sound-1.8.1.jar</binary-origin>
             </class-path-extension>
         </data>
     </configuration>
diff --git a/platform/net.java.html/external/binaries-list b/platform/net.java.html/external/binaries-list
index 5eecc12aaa..a8e357452c 100644
--- a/platform/net.java.html/external/binaries-list
+++ b/platform/net.java.html/external/binaries-list
@@ -14,4 +14,4 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-8D34C9BF1D1A898E5E6A618B220DB3FC00C2F936 org.netbeans.html:net.java.html:1.7.3
+402FB32346582BAAD7CA568898092F3544416582 org.netbeans.html:net.java.html:1.8.1
diff --git a/platform/net.java.html/external/net.java.html-1.7.3-license.txt b/platform/net.java.html/external/net.java.html-1.8.1-license.txt
similarity index 99%
rename from platform/net.java.html/external/net.java.html-1.7.3-license.txt
rename to platform/net.java.html/external/net.java.html-1.8.1-license.txt
index 20b4bd0a75..6fd8d98bf8 100644
--- a/platform/net.java.html/external/net.java.html-1.7.3-license.txt
+++ b/platform/net.java.html/external/net.java.html-1.8.1-license.txt
@@ -1,5 +1,5 @@
 Name: Html4J
-Version: 1.7.3
+Version: 1.8.1
 Description: Html4j
 License: Apache-2.0
 Origin: Apache Software Foundation
diff --git a/platform/net.java.html/nbproject/project.properties b/platform/net.java.html/nbproject/project.properties
index ceffa53aa5..136eba6b15 100644
--- a/platform/net.java.html/nbproject/project.properties
+++ b/platform/net.java.html/nbproject/project.properties
@@ -14,6 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-release.external/net.java.html-1.7.3.jar=modules/net-java-html.jar
+release.external/net.java.html-1.8.1.jar=modules/net-java-html.jar
 is.autoload=true
 nbm.module.author=Jaroslav Tulach
diff --git a/platform/net.java.html/nbproject/project.xml b/platform/net.java.html/nbproject/project.xml
index b2490eb8b4..8b96a0a7f3 100644
--- a/platform/net.java.html/nbproject/project.xml
+++ b/platform/net.java.html/nbproject/project.xml
@@ -28,7 +28,7 @@
            <public-packages/>
            <class-path-extension>
                <runtime-relative-path>net-java-html.jar</runtime-relative-path>
-               <binary-origin>external/net.java.html-1.7.3.jar</binary-origin>
+               <binary-origin>external/net.java.html-1.8.1.jar</binary-origin>
             </class-path-extension>
         </data>
     </configuration>
diff --git a/platform/o.n.html.ko4j/external/binaries-list b/platform/o.n.html.ko4j/external/binaries-list
index 1950c13bf6..e1646454bb 100644
--- a/platform/o.n.html.ko4j/external/binaries-list
+++ b/platform/o.n.html.ko4j/external/binaries-list
@@ -14,4 +14,4 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-F63214CFA9BDFCBD48E3A0BDEEEF379999AB4AD2 org.netbeans.html:ko4j:1.7.3
+7732CF65F3E0D422B4352653B52068E978C78D38 org.netbeans.html:ko4j:1.8.1
diff --git a/platform/o.n.html.presenters.spi/external/generic-1.7.3-license.txt b/platform/o.n.html.ko4j/external/ko4j-1.8.1-license.txt
similarity index 99%
rename from platform/o.n.html.presenters.spi/external/generic-1.7.3-license.txt
rename to platform/o.n.html.ko4j/external/ko4j-1.8.1-license.txt
index d136fb3d98..8b95fa1d1e 100644
--- a/platform/o.n.html.presenters.spi/external/generic-1.7.3-license.txt
+++ b/platform/o.n.html.ko4j/external/ko4j-1.8.1-license.txt
@@ -1,5 +1,5 @@
 Name: Knockout4J
-Version: 1.7.3
+Version: 1.8.1
 Description: Knockout4J
 License: Apache-2.0
 Origin: Apache Software Foundation
diff --git a/platform/o.n.html.ko4j/nbproject/project.properties b/platform/o.n.html.ko4j/nbproject/project.properties
index 951cccc681..348ecdd324 100644
--- a/platform/o.n.html.ko4j/nbproject/project.properties
+++ b/platform/o.n.html.ko4j/nbproject/project.properties
@@ -14,6 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-release.external/ko4j-1.7.3.jar=modules/org-netbeans-html-ko4j.jar
+release.external/ko4j-1.8.1.jar=modules/org-netbeans-html-ko4j.jar
 nbm.module.author=Jaroslav Tulach
 is.autoload=true
diff --git a/platform/o.n.html.ko4j/nbproject/project.xml b/platform/o.n.html.ko4j/nbproject/project.xml
index 7138aa83c1..732b509d05 100644
--- a/platform/o.n.html.ko4j/nbproject/project.xml
+++ b/platform/o.n.html.ko4j/nbproject/project.xml
@@ -28,7 +28,7 @@
            <public-packages/>
            <class-path-extension>
                <runtime-relative-path>org-netbeans-html-ko4j.jar</runtime-relative-path>
-               <binary-origin>external/ko4j-1.7.3.jar</binary-origin>
+               <binary-origin>external/ko4j-1.8.1.jar</binary-origin>
             </class-path-extension>
         </data>
     </configuration>
diff --git a/platform/o.n.html.presenters.spi/external/binaries-list b/platform/o.n.html.presenters.spi/external/binaries-list
index a2968acd38..6ad3211b3c 100644
--- a/platform/o.n.html.presenters.spi/external/binaries-list
+++ b/platform/o.n.html.presenters.spi/external/binaries-list
@@ -14,4 +14,4 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-7621B0AFE4260212C6632FE74E6F5CCDBB61EEB8 org.netbeans.html:generic:1.7.3
+5FA8D6802AF597CF1B6D7788248AA3AADE615768 org.netbeans.html:generic:1.8.1
diff --git a/platform/o.n.html.ko4j/external/ko4j-1.7.3-license.txt b/platform/o.n.html.presenters.spi/external/generic-1.8.1-license.txt
similarity index 99%
rename from platform/o.n.html.ko4j/external/ko4j-1.7.3-license.txt
rename to platform/o.n.html.presenters.spi/external/generic-1.8.1-license.txt
index d136fb3d98..8b95fa1d1e 100644
--- a/platform/o.n.html.ko4j/external/ko4j-1.7.3-license.txt
+++ b/platform/o.n.html.presenters.spi/external/generic-1.8.1-license.txt
@@ -1,5 +1,5 @@
 Name: Knockout4J
-Version: 1.7.3
+Version: 1.8.1
 Description: Knockout4J
 License: Apache-2.0
 Origin: Apache Software Foundation
diff --git a/platform/o.n.html.presenters.spi/nbproject/project.properties b/platform/o.n.html.presenters.spi/nbproject/project.properties
index 6a152d3766..6f51de2176 100644
--- a/platform/o.n.html.presenters.spi/nbproject/project.properties
+++ b/platform/o.n.html.presenters.spi/nbproject/project.properties
@@ -14,6 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-release.external/generic-1.7.3.jar=modules/org-netbeans-html-presenters-spi.jar
+release.external/generic-1.8.1.jar=modules/org-netbeans-html-presenters-spi.jar
 nbm.module.author=Jaroslav Tulach
 is.autoload=true
diff --git a/platform/o.n.html.presenters.spi/nbproject/project.xml b/platform/o.n.html.presenters.spi/nbproject/project.xml
index c3d09afc33..f06bdb7c8c 100644
--- a/platform/o.n.html.presenters.spi/nbproject/project.xml
+++ b/platform/o.n.html.presenters.spi/nbproject/project.xml
@@ -28,7 +28,7 @@
            <public-packages/>
            <class-path-extension>
                <runtime-relative-path>org-netbeans-html-presenters-spi.jar</runtime-relative-path>
-               <binary-origin>external/generic-1.7.3.jar</binary-origin>
+               <binary-origin>external/generic-1.8.1.jar</binary-origin>
             </class-path-extension>
         </data>
     </configuration>
diff --git a/platform/o.n.html.xhr4j/external/binaries-list b/platform/o.n.html.xhr4j/external/binaries-list
index e62f628ff4..1feaad6b2d 100644
--- a/platform/o.n.html.xhr4j/external/binaries-list
+++ b/platform/o.n.html.xhr4j/external/binaries-list
@@ -14,4 +14,4 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-2756D001008576536B68C1B43D96053E82723D65 org.netbeans.html:xhr4j:1.7.3
+5F4867E9E25B7B09F11A37E42ABD81D5D57040CD org.netbeans.html:xhr4j:1.8.1
diff --git a/platform/o.n.html.xhr4j/external/xhr4j-1.7.3-license.txt b/platform/o.n.html.xhr4j/external/xhr4j-1.8.1-license.txt
similarity index 99%
rename from platform/o.n.html.xhr4j/external/xhr4j-1.7.3-license.txt
rename to platform/o.n.html.xhr4j/external/xhr4j-1.8.1-license.txt
index 534c1e8d11..1a9624b7d6 100644
--- a/platform/o.n.html.xhr4j/external/xhr4j-1.7.3-license.txt
+++ b/platform/o.n.html.xhr4j/external/xhr4j-1.8.1-license.txt
@@ -1,5 +1,5 @@
 Name: XHR via Java
-Version: 1.7.3
+Version: 1.8.1
 Description: XHR via Java
 License: Apache-2.0
 Origin: Apache Software Foundation
diff --git a/platform/o.n.html.xhr4j/nbproject/project.properties b/platform/o.n.html.xhr4j/nbproject/project.properties
index 2e125b716b..25c6d696ce 100644
--- a/platform/o.n.html.xhr4j/nbproject/project.properties
+++ b/platform/o.n.html.xhr4j/nbproject/project.properties
@@ -14,6 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-release.external/xhr4j-1.7.3.jar=modules/org-netbeans-html-xhr4j.jar
+release.external/xhr4j-1.8.1.jar=modules/org-netbeans-html-xhr4j.jar
 nbm.module.author=Jaroslav Tulach
 is.autoload=true
diff --git a/platform/o.n.html.xhr4j/nbproject/project.xml b/platform/o.n.html.xhr4j/nbproject/project.xml
index c1a875a049..329a41f395 100644
--- a/platform/o.n.html.xhr4j/nbproject/project.xml
+++ b/platform/o.n.html.xhr4j/nbproject/project.xml
@@ -28,7 +28,7 @@
            <public-packages/>
            <class-path-extension>
                <runtime-relative-path>org-netbeans-html-xhr4j.jar</runtime-relative-path>
-               <binary-origin>external/xhr4j-1.7.3.jar</binary-origin>
+               <binary-origin>external/xhr4j-1.8.1.jar</binary-origin>
             </class-path-extension>
         </data>
     </configuration>


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists