overlay.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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. /** @type {TrustedTypePolicy | undefined} */
  24. var overlayTrustedTypesPolicy;
  25. ansiHTML.setColors(colors);
  26. /**
  27. * @param {string | null} trustedTypesPolicyName
  28. */
  29. function createContainer(trustedTypesPolicyName) {
  30. // Enable Trusted Types if they are available in the current browser.
  31. if (window.trustedTypes) {
  32. overlayTrustedTypesPolicy = window.trustedTypes.createPolicy(trustedTypesPolicyName || "webpack-dev-server#overlay", {
  33. createHTML: function createHTML(value) {
  34. return value;
  35. }
  36. });
  37. }
  38. iframeContainerElement = document.createElement("iframe");
  39. iframeContainerElement.id = "webpack-dev-server-client-overlay";
  40. iframeContainerElement.src = "about:blank";
  41. iframeContainerElement.style.position = "fixed";
  42. iframeContainerElement.style.left = 0;
  43. iframeContainerElement.style.top = 0;
  44. iframeContainerElement.style.right = 0;
  45. iframeContainerElement.style.bottom = 0;
  46. iframeContainerElement.style.width = "100vw";
  47. iframeContainerElement.style.height = "100vh";
  48. iframeContainerElement.style.border = "none";
  49. iframeContainerElement.style.zIndex = 9999999999;
  50. iframeContainerElement.onload = function () {
  51. containerElement =
  52. /** @type {Document} */
  53. /** @type {HTMLIFrameElement} */
  54. iframeContainerElement.contentDocument.createElement("div");
  55. containerElement.id = "webpack-dev-server-client-overlay-div";
  56. containerElement.style.position = "fixed";
  57. containerElement.style.boxSizing = "border-box";
  58. containerElement.style.left = 0;
  59. containerElement.style.top = 0;
  60. containerElement.style.right = 0;
  61. containerElement.style.bottom = 0;
  62. containerElement.style.width = "100vw";
  63. containerElement.style.height = "100vh";
  64. containerElement.style.backgroundColor = "rgba(0, 0, 0, 0.85)";
  65. containerElement.style.color = "#E8E8E8";
  66. containerElement.style.fontFamily = "Menlo, Consolas, monospace";
  67. containerElement.style.fontSize = "large";
  68. containerElement.style.padding = "2rem";
  69. containerElement.style.lineHeight = "1.2";
  70. containerElement.style.whiteSpace = "pre-wrap";
  71. containerElement.style.overflow = "auto";
  72. var headerElement = document.createElement("span");
  73. headerElement.innerText = "Compiled with problems:";
  74. var closeButtonElement = document.createElement("button");
  75. closeButtonElement.innerText = "X";
  76. closeButtonElement.style.background = "transparent";
  77. closeButtonElement.style.border = "none";
  78. closeButtonElement.style.fontSize = "20px";
  79. closeButtonElement.style.fontWeight = "bold";
  80. closeButtonElement.style.color = "white";
  81. closeButtonElement.style.cursor = "pointer";
  82. closeButtonElement.style.cssFloat = "right"; // @ts-ignore
  83. closeButtonElement.style.styleFloat = "right";
  84. closeButtonElement.addEventListener("click", function () {
  85. hide();
  86. });
  87. containerElement.appendChild(headerElement);
  88. containerElement.appendChild(closeButtonElement);
  89. containerElement.appendChild(document.createElement("br"));
  90. containerElement.appendChild(document.createElement("br"));
  91. /** @type {Document} */
  92. /** @type {HTMLIFrameElement} */
  93. iframeContainerElement.contentDocument.body.appendChild(containerElement);
  94. onLoadQueue.forEach(function (onLoad) {
  95. onLoad(
  96. /** @type {HTMLDivElement} */
  97. containerElement);
  98. });
  99. onLoadQueue = [];
  100. /** @type {HTMLIFrameElement} */
  101. iframeContainerElement.onload = null;
  102. };
  103. document.body.appendChild(iframeContainerElement);
  104. }
  105. /**
  106. * @param {(element: HTMLDivElement) => void} callback
  107. * @param {string | null} trustedTypesPolicyName
  108. */
  109. function ensureOverlayExists(callback, trustedTypesPolicyName) {
  110. if (containerElement) {
  111. // Everything is ready, call the callback right away.
  112. callback(containerElement);
  113. return;
  114. }
  115. onLoadQueue.push(callback);
  116. if (iframeContainerElement) {
  117. return;
  118. }
  119. createContainer(trustedTypesPolicyName);
  120. } // Successful compilation.
  121. function hide() {
  122. if (!iframeContainerElement) {
  123. return;
  124. } // Clean up and reset internal state.
  125. document.body.removeChild(iframeContainerElement);
  126. iframeContainerElement = null;
  127. containerElement = null;
  128. }
  129. /**
  130. * @param {string} type
  131. * @param {string | { file?: string, moduleName?: string, loc?: string, message?: string }} item
  132. * @returns {{ header: string, body: string }}
  133. */
  134. function formatProblem(type, item) {
  135. var header = type === "warning" ? "WARNING" : "ERROR";
  136. var body = "";
  137. if (typeof item === "string") {
  138. body += item;
  139. } else {
  140. var file = item.file || ""; // eslint-disable-next-line no-nested-ternary
  141. var moduleName = item.moduleName ? item.moduleName.indexOf("!") !== -1 ? "".concat(item.moduleName.replace(/^(\s|\S)*!/, ""), " (").concat(item.moduleName, ")") : "".concat(item.moduleName) : "";
  142. var loc = item.loc;
  143. header += "".concat(moduleName || file ? " in ".concat(moduleName ? "".concat(moduleName).concat(file ? " (".concat(file, ")") : "") : file).concat(loc ? " ".concat(loc) : "") : "");
  144. body += item.message || "";
  145. }
  146. return {
  147. header: header,
  148. body: body
  149. };
  150. } // Compilation with errors (e.g. syntax error or missing modules).
  151. /**
  152. * @param {string} type
  153. * @param {Array<string | { file?: string, moduleName?: string, loc?: string, message?: string }>} messages
  154. * @param {string | null} trustedTypesPolicyName
  155. */
  156. function show(type, messages, trustedTypesPolicyName) {
  157. ensureOverlayExists(function () {
  158. messages.forEach(function (message) {
  159. var entryElement = document.createElement("div");
  160. var typeElement = document.createElement("span");
  161. var _formatProblem = formatProblem(type, message),
  162. header = _formatProblem.header,
  163. body = _formatProblem.body;
  164. typeElement.innerText = header;
  165. typeElement.style.color = "#".concat(colors.red); // Make it look similar to our terminal.
  166. var text = ansiHTML(encode(body));
  167. var messageTextNode = document.createElement("div");
  168. messageTextNode.innerHTML = overlayTrustedTypesPolicy ? overlayTrustedTypesPolicy.createHTML(text) : text;
  169. entryElement.appendChild(typeElement);
  170. entryElement.appendChild(document.createElement("br"));
  171. entryElement.appendChild(document.createElement("br"));
  172. entryElement.appendChild(messageTextNode);
  173. entryElement.appendChild(document.createElement("br"));
  174. entryElement.appendChild(document.createElement("br"));
  175. /** @type {HTMLDivElement} */
  176. containerElement.appendChild(entryElement);
  177. });
  178. }, trustedTypesPolicyName);
  179. }
  180. export { formatProblem, show, hide };