overlay.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // The error overlay is inspired (and mostly copied) from Create React App (https://github.com/facebookincubator/create-react-app)
  2. // They, in turn, got inspired by webpack-hot-middleware (https://github.com/glenjamin/webpack-hot-middleware).
  3. import ansiHTML from "ansi-html-community";
  4. import { encode } from "html-entities";
  5. var colors = {
  6. reset: ["transparent", "transparent"],
  7. black: "181818",
  8. red: "E36049",
  9. green: "B3CB74",
  10. yellow: "FFD080",
  11. blue: "7CAFC2",
  12. magenta: "7FACCA",
  13. cyan: "C3C2EF",
  14. lightgrey: "EBE7E3",
  15. darkgrey: "6D7891"
  16. };
  17. /** @type {HTMLIFrameElement | null | undefined} */
  18. var iframeContainerElement;
  19. /** @type {HTMLDivElement | null | undefined} */
  20. var containerElement;
  21. /** @type {Array<(element: HTMLDivElement) => void>} */
  22. var onLoadQueue = [];
  23. ansiHTML.setColors(colors);
  24. function createContainer() {
  25. iframeContainerElement = document.createElement("iframe");
  26. iframeContainerElement.id = "webpack-dev-server-client-overlay";
  27. iframeContainerElement.src = "about:blank";
  28. iframeContainerElement.style.position = "fixed";
  29. iframeContainerElement.style.left = 0;
  30. iframeContainerElement.style.top = 0;
  31. iframeContainerElement.style.right = 0;
  32. iframeContainerElement.style.bottom = 0;
  33. iframeContainerElement.style.width = "100vw";
  34. iframeContainerElement.style.height = "100vh";
  35. iframeContainerElement.style.border = "none";
  36. iframeContainerElement.style.zIndex = 9999999999;
  37. iframeContainerElement.onload = function () {
  38. containerElement =
  39. /** @type {Document} */
  40. /** @type {HTMLIFrameElement} */
  41. iframeContainerElement.contentDocument.createElement("div");
  42. containerElement.id = "webpack-dev-server-client-overlay-div";
  43. containerElement.style.position = "fixed";
  44. containerElement.style.boxSizing = "border-box";
  45. containerElement.style.left = 0;
  46. containerElement.style.top = 0;
  47. containerElement.style.right = 0;
  48. containerElement.style.bottom = 0;
  49. containerElement.style.width = "100vw";
  50. containerElement.style.height = "100vh";
  51. containerElement.style.backgroundColor = "rgba(0, 0, 0, 0.85)";
  52. containerElement.style.color = "#E8E8E8";
  53. containerElement.style.fontFamily = "Menlo, Consolas, monospace";
  54. containerElement.style.fontSize = "large";
  55. containerElement.style.padding = "2rem";
  56. containerElement.style.lineHeight = "1.2";
  57. containerElement.style.whiteSpace = "pre-wrap";
  58. containerElement.style.overflow = "auto";
  59. var headerElement = document.createElement("span");
  60. headerElement.innerText = "Compiled with problems:";
  61. var closeButtonElement = document.createElement("button");
  62. closeButtonElement.innerText = "X";
  63. closeButtonElement.style.background = "transparent";
  64. closeButtonElement.style.border = "none";
  65. closeButtonElement.style.fontSize = "20px";
  66. closeButtonElement.style.fontWeight = "bold";
  67. closeButtonElement.style.color = "white";
  68. closeButtonElement.style.cursor = "pointer";
  69. closeButtonElement.style.cssFloat = "right"; // @ts-ignore
  70. closeButtonElement.style.styleFloat = "right";
  71. closeButtonElement.addEventListener("click", function () {
  72. hide();
  73. });
  74. containerElement.appendChild(headerElement);
  75. containerElement.appendChild(closeButtonElement);
  76. containerElement.appendChild(document.createElement("br"));
  77. containerElement.appendChild(document.createElement("br"));
  78. /** @type {Document} */
  79. /** @type {HTMLIFrameElement} */
  80. iframeContainerElement.contentDocument.body.appendChild(containerElement);
  81. onLoadQueue.forEach(function (onLoad) {
  82. onLoad(
  83. /** @type {HTMLDivElement} */
  84. containerElement);
  85. });
  86. onLoadQueue = [];
  87. /** @type {HTMLIFrameElement} */
  88. iframeContainerElement.onload = null;
  89. };
  90. document.body.appendChild(iframeContainerElement);
  91. }
  92. /**
  93. * @param {(element: HTMLDivElement) => void} callback
  94. */
  95. function ensureOverlayExists(callback) {
  96. if (containerElement) {
  97. // Everything is ready, call the callback right away.
  98. callback(containerElement);
  99. return;
  100. }
  101. onLoadQueue.push(callback);
  102. if (iframeContainerElement) {
  103. return;
  104. }
  105. createContainer();
  106. } // Successful compilation.
  107. function hide() {
  108. if (!iframeContainerElement) {
  109. return;
  110. } // Clean up and reset internal state.
  111. document.body.removeChild(iframeContainerElement);
  112. iframeContainerElement = null;
  113. containerElement = null;
  114. }
  115. /**
  116. * @param {string} type
  117. * @param {string | { file?: string, moduleName?: string, loc?: string, message?: string }} item
  118. * @returns {{ header: string, body: string }}
  119. */
  120. function formatProblem(type, item) {
  121. var header = type === "warning" ? "WARNING" : "ERROR";
  122. var body = "";
  123. if (typeof item === "string") {
  124. body += item;
  125. } else {
  126. var file = item.file || ""; // eslint-disable-next-line no-nested-ternary
  127. var moduleName = item.moduleName ? item.moduleName.indexOf("!") !== -1 ? "".concat(item.moduleName.replace(/^(\s|\S)*!/, ""), " (").concat(item.moduleName, ")") : "".concat(item.moduleName) : "";
  128. var loc = item.loc;
  129. header += "".concat(moduleName || file ? " in ".concat(moduleName ? "".concat(moduleName).concat(file ? " (".concat(file, ")") : "") : file).concat(loc ? " ".concat(loc) : "") : "");
  130. body += item.message || "";
  131. }
  132. return {
  133. header: header,
  134. body: body
  135. };
  136. } // Compilation with errors (e.g. syntax error or missing modules).
  137. /**
  138. * @param {string} type
  139. * @param {Array<string | { file?: string, moduleName?: string, loc?: string, message?: string }>} messages
  140. */
  141. function show(type, messages) {
  142. ensureOverlayExists(function () {
  143. messages.forEach(function (message) {
  144. var entryElement = document.createElement("div");
  145. var typeElement = document.createElement("span");
  146. var _formatProblem = formatProblem(type, message),
  147. header = _formatProblem.header,
  148. body = _formatProblem.body;
  149. typeElement.innerText = header;
  150. typeElement.style.color = "#".concat(colors.red); // Make it look similar to our terminal.
  151. var text = ansiHTML(encode(body));
  152. var messageTextNode = document.createElement("div");
  153. messageTextNode.innerHTML = text;
  154. entryElement.appendChild(typeElement);
  155. entryElement.appendChild(document.createElement("br"));
  156. entryElement.appendChild(document.createElement("br"));
  157. entryElement.appendChild(messageTextNode);
  158. entryElement.appendChild(document.createElement("br"));
  159. entryElement.appendChild(document.createElement("br"));
  160. /** @type {HTMLDivElement} */
  161. containerElement.appendChild(entryElement);
  162. });
  163. });
  164. }
  165. export { formatProblem, show, hide };