diff --git a/d2cli/static/favicon-err.ico b/d2cli/static/favicon-err.ico new file mode 100644 index 000000000..5619a4ebd Binary files /dev/null and b/d2cli/static/favicon-err.ico differ diff --git a/d2cli/static/favicon.ico b/d2cli/static/favicon.ico new file mode 100644 index 000000000..452e6dcf6 Binary files /dev/null and b/d2cli/static/favicon.ico differ diff --git a/d2cli/static/watch.js b/d2cli/static/watch.js index 71fa9436f..c6efceb50 100644 --- a/d2cli/static/watch.js +++ b/d2cli/static/watch.js @@ -28,7 +28,7 @@ function init(reconnectDelay) { // we can't just set `d2SVG.innerHTML = msg.svg` need to parse this as xml not html const parsedXML = new DOMParser().parseFromString(msg.svg, "text/xml"); d2SVG.replaceChildren(parsedXML.documentElement); - + changeFavicon("./static/favicon.ico"); const svgEl = d2SVG.querySelector("#d2-svg"); // just use inner SVG in watch mode svgEl.parentElement.replaceWith(svgEl); @@ -56,6 +56,7 @@ function init(reconnectDelay) { if (msg.err) { d2ErrDiv.innerText = msg.err; d2ErrDiv.style.display = "block"; + changeFavicon("./static/favicon-err.ico"); d2ErrDiv.scrollIntoView(); } }; @@ -73,3 +74,18 @@ function init(reconnectDelay) { }, reconnectDelay); }; } + +const changeFavicon = function (iconURL) { + const head = document.getElementsByTagName("head")[0]; + const newLink = document.createElement("link"); + newLink.rel = "icon"; + newLink.href = iconURL; + removeExistingFavicons(); + head.appendChild(newLink); +}; +const removeExistingFavicons = function () { + const links = document.getElementsByTagName("link"); + Array.from(links) + .filter((link) => /\bicon\b/i.test(link.getAttribute("rel"))) + .forEach((link) => link.remove()); +}; diff --git a/d2cli/watch.go b/d2cli/watch.go index d1a2c64f0..b352a7b36 100644 --- a/d2cli/watch.go +++ b/d2cli/watch.go @@ -429,6 +429,7 @@ func (w *watcher) handleRoot(hw http.ResponseWriter, r *http.Request) { %s +