UNPKG

webpack-plugin-serve

Version:
405 lines (346 loc) 8.47 kB
/* Copyright © 2018 Andrew Powell This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. The above copyright notice and this permission notice shall be included in all copies or substantial portions of this Source Code Form. */ const { addCss, addHtml, socketMessage } = require('./util'); const ns = 'wps-status'; const css = ` #${ns} { background: #282d35; border-radius: 0.6em; display: flex; flex-direction: column; font-family: 'Open Sans', Helvetica, Arial, sans-serif; font-size: 10px; height: 90%; min-height: 20em; left: 50%; opacity: 1; overflow: hidden; padding-bottom: 3em; position: absolute; top: 2rem; transform: translateX(-50%); transition: opacity .25s ease-in-out; width: 95%; z-index: 2147483645; } @keyframes ${ns}-hidden-display { 0% { opacity: 1; } 99% { display: inline-flex; opacity: 0; } 100% { display: none; opacity: 0; } } #${ns}.${ns}-hidden { animation: ${ns}-hidden-display .3s; animation-fill-mode:forwards; display: none; } #${ns}.${ns}-min { animation: minimize 10s; bottom: 2em; cursor: pointer; height: 6em; left: auto; min-height: 6em; padding-bottom: 0; position: absolute; right: 2em; top: auto; transform: none; width: 6em; } #${ns}.${ns}-min #${ns}-beacon { display: block; } #${ns}-title { color: #fff; font-size: 1.2em; font-weight: normal; margin: 0; padding: 0.6em 0; text-align: center; width: 100%; } #${ns}.${ns}-min #${ns}-title { display: none; } #${ns}-title-errors { color: #ff5f58; font-style: normal; padding-left: 1em; } #${ns}-title-warnings { color: #ffbd2e; font-style: normal; padding-left: 1em; } #${ns}-problems { overflow-y: auto; padding: 1em 2em; } #${ns}-problems pre { color: #ddd; background: #282d35; display: block; font-size: 1.3em; font-family: 'Open Sans', Helvetica, Arial, sans-serif; white-space: pre-wrap; } #${ns}-problems pre em { background: #ff5f58; border-radius: 0.3em; color: #641e16; font-style: normal; line-height: 3em; margin-right: 0.4em; padding: 0.1em 0.4em; text-transform: uppercase; } pre#${ns}-warnings em { background: #ffbd2e; color: #3e2723; } pre#${ns}-success { display: none; text-align: center; } pre#${ns}-success em { background: #7fb900; color: #004d40; } #${ns}-problems.${ns}-success #${ns}-success { display: block; } #${ns}.${ns}-min #${ns}-problems { display: none; } #${ns}-nav { opacity: 0.5; padding: 1.2em; position: absolute; } #${ns}.${ns}-min #${ns}-nav { display: none; } #${ns}-nav:hover { opacity: 1; } #${ns}-nav div { background: #ff5f58; border-radius: 1.2em; cursor: pointer; display: inline-block; height: 1.2em; position: relative; width: 1.2em; } div#${ns}-min { background: #ffbd2e; margin-left: 0.8em; } #${ns}-beacon { border-radius: 3em; display: none; font-size: 10px; height: 3em; margin: 1.6em auto; position: relative; width: 3em; } #${ns}-beacon:before, #${ns}-beacon:after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(127,185,0, 0.2); border-radius: 3em; opacity: 0; } #${ns}-beacon:before { animation: ${ns}-pulse 3s infinite linear; transform: scale(1); } #${ns}-beacon:after { animation: ${ns}-pulse 3s 2s infinite linear; } @keyframes ${ns}-pulse { 0% { opacity: 0; transform: scale(0.6); } 33% { opacity: 1; transform: scale(1); } 100% { opacity: 0; transform: scale(1.4); } } #${ns}-beacon mark { background: rgba(127, 185, 0, 1); border-radius: 100% 100%; height: 1em; left: 1em; position: absolute; top: 1em; width: 1em; } #${ns}-beacon.${ns}-error mark { background: #ff5f58; } #${ns}-beacon.${ns}-error:before, #${ns}-beacon.error:after { background: rgba(255, 95, 88, 0.2); } #${ns}-beacon.${ns}-warning mark { background: #ffbd2e; } #${ns}-beacon.${ns}-warning:before, #${ns}-beacon.warning:after { background: rgba(255, 189, 46, 0.2); } /* Put google web font at the end, or you'll see FOUC in Firefox */ @import url('https://fonts.googleapis.com/css?family=Open+Sans:400,700'); `; const html = ` <aside id="${ns}" class="${ns}-hidden" title="build status"> <figure id="${ns}-beacon"> <mark/> </figure> <nav id="${ns}-nav"> <div id="${ns}-close" title="close"></div> <div id="${ns}-min" title="minmize"></div> </nav> <h1 id="${ns}-title"> build status <em id="${ns}-title-errors"></em> <em id="${ns}-title-warnings"></em> </h1> <article id="${ns}-problems"> <pre id="${ns}-success"><em>Build Successful</em></pre> <pre id="${ns}-errors"></pre> <pre id="${ns}-warnings"></pre> </article> </aside> `; const init = (options, socket) => { const hidden = `${ns}-hidden`; let hasProblems = false; let aside; let beacon; let problems; let preErrors; let preWarnings; let titleErrors; let titleWarnings; const reset = () => { preErrors.innerHTML = ''; preWarnings.innerHTML = ''; problems.classList.remove(`${ns}-success`); beacon.className = ''; titleErrors.innerText = ''; titleWarnings.innerText = ''; }; const addErrors = (errors) => { if (errors.length) { problems.classList.remove(`${ns}-success`); beacon.classList.add(`${ns}-error`); for (const error of errors) { const markup = `<div><em>Error</em> in ${error}</div>`; addHtml(markup, preErrors); } titleErrors.innerText = `${errors.length} Error(s)`; } else { titleErrors.innerText = ''; } aside.classList.remove(hidden); }; const addWarnings = (warnings) => { if (warnings.length) { problems.classList.remove(`${ns}-success`); if (!beacon.classList.contains(`${ns}-error`)) { beacon.classList.add(`${ns}-warning`); } for (const warning of warnings) { const markup = `<div><em>Warning</em> in ${warning}</div>`; addHtml(markup, preWarnings); } titleWarnings.innerText = `${warnings.length} Warning(s)`; } else { titleWarnings.innerText = ''; } aside.classList.remove(hidden); }; if (options.firstInstance) { document.addEventListener('DOMContentLoaded', () => { addCss(css); [aside] = addHtml(html); beacon = document.querySelector(`#${ns}-beacon`); problems = document.querySelector(`#${ns}-problems`); preErrors = document.querySelector(`#${ns}-errors`); preWarnings = document.querySelector(`#${ns}-warnings`); titleErrors = document.querySelector(`#${ns}-title-errors`); titleWarnings = document.querySelector(`#${ns}-title-warnings`); const close = document.querySelector(`#${ns}-close`); const min = document.querySelector(`#${ns}-min`); aside.addEventListener('click', () => { aside.classList.remove(`${ns}-min`); }); close.addEventListener('click', () => { aside.classList.add(`${ns}-hidden`); }); min.addEventListener('click', (e) => { aside.classList.add(`${ns}-min`); e.stopImmediatePropagation(); }); }); } socketMessage(socket, (action, data) => { if (!aside) { return; } const { compilers } = window.webpackPluginServe; switch (action) { case 'build': // clear errors and warnings when a new build begins reset(); break; case 'problems': addErrors(data.errors); addWarnings(data.warnings); aside.classList.remove(hidden); hasProblems = data.errors.length || data.warnings.length; break; case 'replace': // if there's a compiler that isn't done yet, hold off and let it run the show for (const compilerName of Object.keys(compilers)) { if (!compilers[compilerName]) { return; } } if (hasProblems && !preErrors.children.length && !preWarnings.children.length) { reset(); hasProblems = false; problems.classList.add(`${ns}-success`); aside.classList.remove(hidden); setTimeout(() => aside.classList.add(hidden), 3e3); } break; default: } }); }; module.exports = { init };