UNPKG

10.4 kBJavaScriptView Raw
1function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
2function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
3function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
4function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
5function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
6// The error overlay is inspired (and mostly copied) from Create React App (https://github.com/facebookincubator/create-react-app)
7// They, in turn, got inspired by webpack-hot-middleware (https://github.com/glenjamin/webpack-hot-middleware).
8
9import ansiHTML from "ansi-html-community";
10import { encode } from "html-entities";
11import { listenToRuntimeError, parseErrorToStacks } from "./overlay/runtime-error.js";
12import createOverlayMachine from "./overlay/state-machine.js";
13import { containerStyle, dismissButtonStyle, headerStyle, iframeStyle, msgStyles, msgTextStyle, msgTypeStyle } from "./overlay/styles.js";
14var colors = {
15 reset: ["transparent", "transparent"],
16 black: "181818",
17 red: "E36049",
18 green: "B3CB74",
19 yellow: "FFD080",
20 blue: "7CAFC2",
21 magenta: "7FACCA",
22 cyan: "C3C2EF",
23 lightgrey: "EBE7E3",
24 darkgrey: "6D7891"
25};
26ansiHTML.setColors(colors);
27
28/**
29 * @param {string} type
30 * @param {string | { file?: string, moduleName?: string, loc?: string, message?: string; stack?: string[] }} item
31 * @returns {{ header: string, body: string }}
32 */
33function formatProblem(type, item) {
34 var header = type === "warning" ? "WARNING" : "ERROR";
35 var body = "";
36 if (typeof item === "string") {
37 body += item;
38 } else {
39 var file = item.file || "";
40 // eslint-disable-next-line no-nested-ternary
41 var moduleName = item.moduleName ? item.moduleName.indexOf("!") !== -1 ? "".concat(item.moduleName.replace(/^(\s|\S)*!/, ""), " (").concat(item.moduleName, ")") : "".concat(item.moduleName) : "";
42 var loc = item.loc;
43 header += "".concat(moduleName || file ? " in ".concat(moduleName ? "".concat(moduleName).concat(file ? " (".concat(file, ")") : "") : file).concat(loc ? " ".concat(loc) : "") : "");
44 body += item.message || "";
45 }
46 if (Array.isArray(item.stack)) {
47 item.stack.forEach(function (stack) {
48 if (typeof stack === "string") {
49 body += "\r\n".concat(stack);
50 }
51 });
52 }
53 return {
54 header: header,
55 body: body
56 };
57}
58
59/**
60 * @typedef {Object} CreateOverlayOptions
61 * @property {string | null} trustedTypesPolicyName
62 * @property {boolean} [catchRuntimeError]
63 */
64
65/**
66 *
67 * @param {CreateOverlayOptions} options
68 */
69var createOverlay = function createOverlay(options) {
70 /** @type {HTMLIFrameElement | null | undefined} */
71 var iframeContainerElement;
72 /** @type {HTMLDivElement | null | undefined} */
73 var containerElement;
74 /** @type {Array<(element: HTMLDivElement) => void>} */
75 var onLoadQueue = [];
76 /** @type {TrustedTypePolicy | undefined} */
77 var overlayTrustedTypesPolicy;
78
79 /**
80 *
81 * @param {HTMLElement} element
82 * @param {CSSStyleDeclaration} style
83 */
84 function applyStyle(element, style) {
85 Object.keys(style).forEach(function (prop) {
86 element.style[prop] = style[prop];
87 });
88 }
89
90 /**
91 * @param {string | null} trustedTypesPolicyName
92 */
93 function createContainer(trustedTypesPolicyName) {
94 // Enable Trusted Types if they are available in the current browser.
95 if (window.trustedTypes) {
96 overlayTrustedTypesPolicy = window.trustedTypes.createPolicy(trustedTypesPolicyName || "webpack-dev-server#overlay", {
97 createHTML: function createHTML(value) {
98 return value;
99 }
100 });
101 }
102 iframeContainerElement = document.createElement("iframe");
103 iframeContainerElement.id = "webpack-dev-server-client-overlay";
104 iframeContainerElement.src = "about:blank";
105 applyStyle(iframeContainerElement, iframeStyle);
106 iframeContainerElement.onload = function () {
107 var contentElement = /** @type {Document} */
108 /** @type {HTMLIFrameElement} */
109 iframeContainerElement.contentDocument.createElement("div");
110 containerElement = /** @type {Document} */
111 /** @type {HTMLIFrameElement} */
112 iframeContainerElement.contentDocument.createElement("div");
113 contentElement.id = "webpack-dev-server-client-overlay-div";
114 applyStyle(contentElement, containerStyle);
115 var headerElement = document.createElement("div");
116 headerElement.innerText = "Compiled with problems:";
117 applyStyle(headerElement, headerStyle);
118 var closeButtonElement = document.createElement("button");
119 applyStyle(closeButtonElement, dismissButtonStyle);
120 closeButtonElement.innerText = "×";
121 closeButtonElement.ariaLabel = "Dismiss";
122 closeButtonElement.addEventListener("click", function () {
123 // eslint-disable-next-line no-use-before-define
124 overlayService.send({
125 type: "DISMISS"
126 });
127 });
128 contentElement.appendChild(headerElement);
129 contentElement.appendChild(closeButtonElement);
130 contentElement.appendChild(containerElement);
131
132 /** @type {Document} */
133 /** @type {HTMLIFrameElement} */
134 iframeContainerElement.contentDocument.body.appendChild(contentElement);
135 onLoadQueue.forEach(function (onLoad) {
136 onLoad( /** @type {HTMLDivElement} */contentElement);
137 });
138 onLoadQueue = [];
139
140 /** @type {HTMLIFrameElement} */
141 iframeContainerElement.onload = null;
142 };
143 document.body.appendChild(iframeContainerElement);
144 }
145
146 /**
147 * @param {(element: HTMLDivElement) => void} callback
148 * @param {string | null} trustedTypesPolicyName
149 */
150 function ensureOverlayExists(callback, trustedTypesPolicyName) {
151 if (containerElement) {
152 containerElement.innerHTML = "";
153 // Everything is ready, call the callback right away.
154 callback(containerElement);
155 return;
156 }
157 onLoadQueue.push(callback);
158 if (iframeContainerElement) {
159 return;
160 }
161 createContainer(trustedTypesPolicyName);
162 }
163
164 // Successful compilation.
165 function hide() {
166 if (!iframeContainerElement) {
167 return;
168 }
169
170 // Clean up and reset internal state.
171 document.body.removeChild(iframeContainerElement);
172 iframeContainerElement = null;
173 containerElement = null;
174 }
175
176 // Compilation with errors (e.g. syntax error or missing modules).
177 /**
178 * @param {string} type
179 * @param {Array<string | { moduleIdentifier?: string, moduleName?: string, loc?: string, message?: string }>} messages
180 * @param {string | null} trustedTypesPolicyName
181 */
182 function show(type, messages, trustedTypesPolicyName) {
183 ensureOverlayExists(function () {
184 messages.forEach(function (message) {
185 var entryElement = document.createElement("div");
186 var msgStyle = type === "warning" ? msgStyles.warning : msgStyles.error;
187 applyStyle(entryElement, _objectSpread(_objectSpread({}, msgStyle), {}, {
188 padding: "1rem 1rem 1.5rem 1rem"
189 }));
190 var typeElement = document.createElement("div");
191 var _formatProblem = formatProblem(type, message),
192 header = _formatProblem.header,
193 body = _formatProblem.body;
194 typeElement.innerText = header;
195 applyStyle(typeElement, msgTypeStyle);
196 if (message.moduleIdentifier) {
197 applyStyle(typeElement, {
198 cursor: "pointer"
199 });
200 // element.dataset not supported in IE
201 typeElement.setAttribute("data-can-open", true);
202 typeElement.addEventListener("click", function () {
203 fetch("/webpack-dev-server/open-editor?fileName=".concat(message.moduleIdentifier));
204 });
205 }
206
207 // Make it look similar to our terminal.
208 var text = ansiHTML(encode(body));
209 var messageTextNode = document.createElement("div");
210 applyStyle(messageTextNode, msgTextStyle);
211 messageTextNode.innerHTML = overlayTrustedTypesPolicy ? overlayTrustedTypesPolicy.createHTML(text) : text;
212 entryElement.appendChild(typeElement);
213 entryElement.appendChild(messageTextNode);
214
215 /** @type {HTMLDivElement} */
216 containerElement.appendChild(entryElement);
217 });
218 }, trustedTypesPolicyName);
219 }
220 var overlayService = createOverlayMachine({
221 showOverlay: function showOverlay(_ref) {
222 var _ref$level = _ref.level,
223 level = _ref$level === void 0 ? "error" : _ref$level,
224 messages = _ref.messages;
225 return show(level, messages, options.trustedTypesPolicyName);
226 },
227 hideOverlay: hide
228 });
229 if (options.catchRuntimeError) {
230 listenToRuntimeError(function (errorEvent) {
231 // error property may be empty in older browser like IE
232 var error = errorEvent.error,
233 message = errorEvent.message;
234 if (!error && !message) {
235 return;
236 }
237 var errorObject = error instanceof Error ? error : new Error(error || message);
238 overlayService.send({
239 type: "RUNTIME_ERROR",
240 messages: [{
241 message: errorObject.message,
242 stack: parseErrorToStacks(errorObject)
243 }]
244 });
245 });
246 }
247 return overlayService;
248};
249export { formatProblem, createOverlay };
\No newline at end of file