UNPKG

debug-server-next

Version:

Dev server for hippy-core.

185 lines (151 loc) 5.81 kB
// 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'; const colors = { reset: ['transparent', 'transparent'], black: '181818', red: 'E36049', green: 'B3CB74', yellow: 'FFD080', blue: '7CAFC2', magenta: '7FACCA', cyan: 'C3C2EF', lightgrey: 'EBE7E3', darkgrey: '6D7891', }; let iframeContainerElement; let containerElement; let 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 = () => { containerElement = 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'; const headerElement = document.createElement('span'); headerElement.innerText = 'Compiled with problems:'; const 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'; closeButtonElement.style.styleFloat = 'right'; closeButtonElement.addEventListener('click', () => { hide(); }); containerElement.appendChild(headerElement); containerElement.appendChild(closeButtonElement); containerElement.appendChild(document.createElement('br')); containerElement.appendChild(document.createElement('br')); iframeContainerElement.contentDocument.body.appendChild(containerElement); onLoadQueue.forEach((onLoad) => { onLoad(containerElement); }); onLoadQueue = []; iframeContainerElement.onload = null; }; document.body.appendChild(iframeContainerElement); } 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; } function formatProblem(type, item) { let header = type === 'warning' ? 'WARNING' : 'ERROR'; let body = ''; if (typeof item === 'string') { body += item; } else { const file = item.file || ''; // eslint-disable-next-line no-nested-ternary const moduleName = item.moduleName ? item.moduleName.indexOf('!') !== -1 ? `${item.moduleName.replace(/^(\s|\S)*!/, '')} (${item.moduleName})` : `${item.moduleName}` : ''; const { loc } = item; header += `${ moduleName || file ? ` in ${moduleName ? `${moduleName}${file ? ` (${file})` : ''}` : file}${ loc ? ` ${loc}` : '' }` : '' }`; body += item.message || ''; } return { header, body }; } // Compilation with errors (e.g. syntax error or missing modules). function show(type, messages) { ensureOverlayExists(() => { messages.forEach((message) => { const entryElement = document.createElement('div'); const typeElement = document.createElement('span'); const { header, body } = formatProblem(type, message); typeElement.innerText = header; typeElement.style.color = `#${colors.red}`; // Make it look similar to our terminal. const text = ansiHTML(encode(body)); const 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')); containerElement.appendChild(entryElement); }); }); } export { formatProblem, show, hide };