You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
6.5 KiB
197 lines
6.5 KiB
3 years ago
|
// The error overlay is inspired (and mostly copied) from Create React App (https://github.com/facebookincubator/create-react-app)
|
||
|
// They, in turn, got inspired by webpack-hot-middleware (https://github.com/glenjamin/webpack-hot-middleware).
|
||
|
import ansiHTML from "ansi-html-community";
|
||
|
import { encode } from "html-entities";
|
||
|
var colors = {
|
||
|
reset: ["transparent", "transparent"],
|
||
|
black: "181818",
|
||
|
red: "E36049",
|
||
|
green: "B3CB74",
|
||
|
yellow: "FFD080",
|
||
|
blue: "7CAFC2",
|
||
|
magenta: "7FACCA",
|
||
|
cyan: "C3C2EF",
|
||
|
lightgrey: "EBE7E3",
|
||
|
darkgrey: "6D7891"
|
||
|
};
|
||
|
/** @type {HTMLIFrameElement | null | undefined} */
|
||
|
|
||
|
var iframeContainerElement;
|
||
|
/** @type {HTMLDivElement | null | undefined} */
|
||
|
|
||
|
var containerElement;
|
||
|
/** @type {Array<(element: HTMLDivElement) => void>} */
|
||
|
|
||
|
var onLoadQueue = [];
|
||
|
ansiHTML.setColors(colors);
|
||
|
|
||
|
function createContainer() {
|
||
|
iframeContainerElement = document.createElement("iframe");
|
||
|
iframeContainerElement.id = "webpack-dev-server-client-overlay";
|
||
|
iframeContainerElement.src = "about:blank";
|
||
|
iframeContainerElement.style.position = "fixed";
|
||
|
iframeContainerElement.style.left = 0;
|
||
|
iframeContainerElement.style.top = 0;
|
||
|
iframeContainerElement.style.right = 0;
|
||
|
iframeContainerElement.style.bottom = 0;
|
||
|
iframeContainerElement.style.width = "100vw";
|
||
|
iframeContainerElement.style.height = "100vh";
|
||
|
iframeContainerElement.style.border = "none";
|
||
|
iframeContainerElement.style.zIndex = 9999999999;
|
||
|
|
||
|
iframeContainerElement.onload = function () {
|
||
|
containerElement =
|
||
|
/** @type {Document} */
|
||
|
|
||
|
/** @type {HTMLIFrameElement} */
|
||
|
iframeContainerElement.contentDocument.createElement("div");
|
||
|
containerElement.id = "webpack-dev-server-client-overlay-div";
|
||
|
containerElement.style.position = "fixed";
|
||
|
containerElement.style.boxSizing = "border-box";
|
||
|
containerElement.style.left = 0;
|
||
|
containerElement.style.top = 0;
|
||
|
containerElement.style.right = 0;
|
||
|
containerElement.style.bottom = 0;
|
||
|
containerElement.style.width = "100vw";
|
||
|
containerElement.style.height = "100vh";
|
||
|
containerElement.style.backgroundColor = "rgba(0, 0, 0, 0.85)";
|
||
|
containerElement.style.color = "#E8E8E8";
|
||
|
containerElement.style.fontFamily = "Menlo, Consolas, monospace";
|
||
|
containerElement.style.fontSize = "large";
|
||
|
containerElement.style.padding = "2rem";
|
||
|
containerElement.style.lineHeight = "1.2";
|
||
|
containerElement.style.whiteSpace = "pre-wrap";
|
||
|
containerElement.style.overflow = "auto";
|
||
|
var headerElement = document.createElement("span");
|
||
|
headerElement.innerText = "Compiled with problems:";
|
||
|
var closeButtonElement = document.createElement("button");
|
||
|
closeButtonElement.innerText = "X";
|
||
|
closeButtonElement.style.background = "transparent";
|
||
|
closeButtonElement.style.border = "none";
|
||
|
closeButtonElement.style.fontSize = "20px";
|
||
|
closeButtonElement.style.fontWeight = "bold";
|
||
|
closeButtonElement.style.color = "white";
|
||
|
closeButtonElement.style.cursor = "pointer";
|
||
|
closeButtonElement.style.cssFloat = "right"; // @ts-ignore
|
||
|
|
||
|
closeButtonElement.style.styleFloat = "right";
|
||
|
closeButtonElement.addEventListener("click", function () {
|
||
|
hide();
|
||
|
});
|
||
|
containerElement.appendChild(headerElement);
|
||
|
containerElement.appendChild(closeButtonElement);
|
||
|
containerElement.appendChild(document.createElement("br"));
|
||
|
containerElement.appendChild(document.createElement("br"));
|
||
|
/** @type {Document} */
|
||
|
|
||
|
/** @type {HTMLIFrameElement} */
|
||
|
iframeContainerElement.contentDocument.body.appendChild(containerElement);
|
||
|
onLoadQueue.forEach(function (onLoad) {
|
||
|
onLoad(
|
||
|
/** @type {HTMLDivElement} */
|
||
|
containerElement);
|
||
|
});
|
||
|
onLoadQueue = [];
|
||
|
/** @type {HTMLIFrameElement} */
|
||
|
|
||
|
iframeContainerElement.onload = null;
|
||
|
};
|
||
|
|
||
|
document.body.appendChild(iframeContainerElement);
|
||
|
}
|
||
|
/**
|
||
|
* @param {(element: HTMLDivElement) => void} callback
|
||
|
*/
|
||
|
|
||
|
|
||
|
function ensureOverlayExists(callback) {
|
||
|
if (containerElement) {
|
||
|
// Everything is ready, call the callback right away.
|
||
|
callback(containerElement);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
onLoadQueue.push(callback);
|
||
|
|
||
|
if (iframeContainerElement) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
createContainer();
|
||
|
} // Successful compilation.
|
||
|
|
||
|
|
||
|
function hide() {
|
||
|
if (!iframeContainerElement) {
|
||
|
return;
|
||
|
} // Clean up and reset internal state.
|
||
|
|
||
|
|
||
|
document.body.removeChild(iframeContainerElement);
|
||
|
iframeContainerElement = null;
|
||
|
containerElement = null;
|
||
|
}
|
||
|
/**
|
||
|
* @param {string} type
|
||
|
* @param {string | { file?: string, moduleName?: string, loc?: string, message?: string }} item
|
||
|
* @returns {{ header: string, body: string }}
|
||
|
*/
|
||
|
|
||
|
|
||
|
function formatProblem(type, item) {
|
||
|
var header = type === "warning" ? "WARNING" : "ERROR";
|
||
|
var body = "";
|
||
|
|
||
|
if (typeof item === "string") {
|
||
|
body += item;
|
||
|
} else {
|
||
|
var file = item.file || ""; // eslint-disable-next-line no-nested-ternary
|
||
|
|
||
|
var moduleName = item.moduleName ? item.moduleName.indexOf("!") !== -1 ? "".concat(item.moduleName.replace(/^(\s|\S)*!/, ""), " (").concat(item.moduleName, ")") : "".concat(item.moduleName) : "";
|
||
|
var loc = item.loc;
|
||
|
header += "".concat(moduleName || file ? " in ".concat(moduleName ? "".concat(moduleName).concat(file ? " (".concat(file, ")") : "") : file).concat(loc ? " ".concat(loc) : "") : "");
|
||
|
body += item.message || "";
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
header: header,
|
||
|
body: body
|
||
|
};
|
||
|
} // Compilation with errors (e.g. syntax error or missing modules).
|
||
|
|
||
|
/**
|
||
|
* @param {string} type
|
||
|
* @param {Array<string | { file?: string, moduleName?: string, loc?: string, message?: string }>} messages
|
||
|
*/
|
||
|
|
||
|
|
||
|
function show(type, messages) {
|
||
|
ensureOverlayExists(function () {
|
||
|
messages.forEach(function (message) {
|
||
|
var entryElement = document.createElement("div");
|
||
|
var typeElement = document.createElement("span");
|
||
|
|
||
|
var _formatProblem = formatProblem(type, message),
|
||
|
header = _formatProblem.header,
|
||
|
body = _formatProblem.body;
|
||
|
|
||
|
typeElement.innerText = header;
|
||
|
typeElement.style.color = "#".concat(colors.red); // Make it look similar to our terminal.
|
||
|
|
||
|
var text = ansiHTML(encode(body));
|
||
|
var messageTextNode = document.createElement("div");
|
||
|
messageTextNode.innerHTML = text;
|
||
|
entryElement.appendChild(typeElement);
|
||
|
entryElement.appendChild(document.createElement("br"));
|
||
|
entryElement.appendChild(document.createElement("br"));
|
||
|
entryElement.appendChild(messageTextNode);
|
||
|
entryElement.appendChild(document.createElement("br"));
|
||
|
entryElement.appendChild(document.createElement("br"));
|
||
|
/** @type {HTMLDivElement} */
|
||
|
|
||
|
containerElement.appendChild(entryElement);
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
export { formatProblem, show, hide };
|