forked from terrastruct/d2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwatch.js
81 lines (77 loc) · 2.54 KB
/
watch.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
"use strict";
window.addEventListener("DOMContentLoaded", () => {
init(1000);
});
function init(reconnectDelay) {
const d2ErrDiv = window.document.querySelector("#d2-err");
const d2SVG = window.document.querySelector("#d2-svg-container");
const devMode = document.body.dataset.d2DevMode === "true";
const ws = new WebSocket(
`ws://${window.location.host}${window.location.pathname}watch`
);
let isInit = true;
let ratio;
ws.onopen = () => {
reconnectDelay = 1000;
console.info("watch websocket opened");
};
ws.onmessage = (ev) => {
const msg = JSON.parse(ev.data);
if (devMode) {
console.debug("watch websocket received data", ev);
} else {
console.debug("watch websocket received data");
}
if (msg.svg) {
// 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);
let width = parseInt(svgEl.getAttribute("width"), 10);
let height = parseInt(svgEl.getAttribute("height"), 10);
if (isInit) {
if (width > height) {
if (width > window.innerWidth) {
ratio = window.innerWidth / width;
}
} else if (height > window.innerHeight) {
ratio = window.innerHeight / height;
}
// Scale svg fit to zoom
isInit = false;
}
if (ratio) {
// body padding is 8px
svgEl.setAttribute("width", width * ratio - 16);
svgEl.setAttribute("height", height * ratio - 16);
}
d2ErrDiv.style.display = "none";
}
if (msg.err) {
d2ErrDiv.innerText = msg.err;
d2ErrDiv.style.display = "block";
changeFavicon("./static/favicon-err.ico");
d2ErrDiv.scrollIntoView();
}
};
ws.onerror = (ev) => {
console.error("watch websocket connection error", ev);
};
ws.onclose = (ev) => {
console.error(`watch websocket closed with code`, ev.code, `and reason`, ev.reason);
console.info(`reconnecting in ${reconnectDelay / 1000} seconds`);
setTimeout(() => {
if (reconnectDelay < 16000) {
reconnectDelay *= 2;
}
init(reconnectDelay);
}, reconnectDelay);
};
}
const changeFavicon = function (iconURL) {
const faviconLink = document.getElementById("favicon");
faviconLink.href = iconURL;
};