webpack-dev-service 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +17 -0
  3. package/client/cjs/client.cjs +128 -0
  4. package/client/cjs/events.cjs +64 -0
  5. package/client/cjs/hot.cjs +111 -0
  6. package/client/cjs/index.cjs +15 -0
  7. package/client/cjs/main.cjs +53 -0
  8. package/client/cjs/ui/overlay.cjs +236 -0
  9. package/client/cjs/ui/progress.cjs +94 -0
  10. package/client/cjs/ui/utils/ansi/index.cjs +443 -0
  11. package/client/cjs/ui/utils/ansi/regx.cjs +70 -0
  12. package/client/cjs/ui/utils/ansi/utils.cjs +27 -0
  13. package/client/cjs/ui/utils/index.cjs +126 -0
  14. package/client/esm/client.js +126 -0
  15. package/client/esm/events.js +60 -0
  16. package/client/esm/hot.js +106 -0
  17. package/client/esm/index.js +10 -0
  18. package/client/esm/main.js +51 -0
  19. package/client/esm/ui/overlay.js +234 -0
  20. package/client/esm/ui/progress.js +92 -0
  21. package/client/esm/ui/utils/ansi/index.js +441 -0
  22. package/client/esm/ui/utils/ansi/regx.js +66 -0
  23. package/client/esm/ui/utils/ansi/utils.js +24 -0
  24. package/client/esm/ui/utils/index.js +120 -0
  25. package/global.d.ts +14 -0
  26. package/package.json +121 -0
  27. package/server/cjs/dev.cjs +50 -0
  28. package/server/cjs/hot.cjs +216 -0
  29. package/server/cjs/index.cjs +33 -0
  30. package/server/esm/dev.js +42 -0
  31. package/server/esm/hot.js +207 -0
  32. package/server/esm/index.js +25 -0
  33. package/types/client/client.d.ts +13 -0
  34. package/types/client/events.d.ts +35 -0
  35. package/types/client/hot.d.ts +27 -0
  36. package/types/client/index.d.ts +4 -0
  37. package/types/client/main.d.ts +4 -0
  38. package/types/client/message.d.ts +39 -0
  39. package/types/client/ui/overlay.d.ts +19 -0
  40. package/types/client/ui/progress.d.ts +15 -0
  41. package/types/client/ui/utils/ansi/enum.d.ts +12 -0
  42. package/types/client/ui/utils/ansi/index.d.ts +18 -0
  43. package/types/client/ui/utils/ansi/interface.d.ts +68 -0
  44. package/types/client/ui/utils/ansi/regx.d.ts +6 -0
  45. package/types/client/ui/utils/ansi/utils.d.ts +6 -0
  46. package/types/client/ui/utils/index.d.ts +9 -0
  47. package/types/server/dev.d.ts +17 -0
  48. package/types/server/hot.d.ts +16 -0
  49. package/types/server/index.d.ts +42 -0
@@ -0,0 +1,126 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.1.0
5
+ * @author nuintun <nuintun@qq.com>
6
+ * @description A koa 2 middleware for webpack development and hot reloading.
7
+ * @see https://github.com/nuintun/webpack-dev-service#readme
8
+ */
9
+
10
+ 'use strict';
11
+
12
+ const index = require('./ansi/index.cjs');
13
+
14
+ /**
15
+ * @module utils
16
+ */
17
+ const ansi = new index();
18
+ const defaultStyleElement = document.createElement('style');
19
+ function injectCSS(css, styleElement = defaultStyleElement) {
20
+ const { head } = document;
21
+ styleElement.appendChild(document.createTextNode(css.trim()));
22
+ if (!head.contains(styleElement)) {
23
+ head.appendChild(styleElement);
24
+ }
25
+ return styleElement;
26
+ }
27
+ function appendHTML(html, parent) {
28
+ const nodes = [];
29
+ const parser = new DOMParser();
30
+ const stage = parent || document.body;
31
+ const fragment = document.createDocumentFragment();
32
+ const { body } = parser.parseFromString(html.trim(), 'text/html');
33
+ while (body.firstChild) {
34
+ nodes.push(fragment.appendChild(body.firstChild));
35
+ }
36
+ stage.appendChild(fragment);
37
+ return nodes;
38
+ }
39
+ function escapeHTML(text) {
40
+ return text.replace(/[&<>"']/gm, match => {
41
+ switch (match) {
42
+ case '&':
43
+ return '&amp;';
44
+ case '<':
45
+ return '&lt;';
46
+ case '>':
47
+ return '&gt;';
48
+ case '"':
49
+ return '&quot;';
50
+ case "'":
51
+ return '&#x27;';
52
+ default:
53
+ return match;
54
+ }
55
+ });
56
+ }
57
+ function blockToHTML({ style, value, url }) {
58
+ const styles = [];
59
+ const textDecorations = [];
60
+ if (style.dim) {
61
+ styles.push(`opacity:0.5`);
62
+ }
63
+ if (style.bold) {
64
+ styles.push(`font-weight:bold`);
65
+ }
66
+ if (style.italic) {
67
+ styles.push(`font-style:italic`);
68
+ }
69
+ if (style.inverse) {
70
+ styles.push(`filter:invert(1)`);
71
+ }
72
+ if (style.hidden) {
73
+ styles.push(`visibility:hidden`);
74
+ }
75
+ if (style.blink) {
76
+ textDecorations.push('blink');
77
+ }
78
+ if (style.overline) {
79
+ textDecorations.push('overline');
80
+ }
81
+ if (style.underline) {
82
+ textDecorations.push('underline');
83
+ }
84
+ if (style.strikethrough) {
85
+ textDecorations.push('line-through');
86
+ }
87
+ const { color, background } = style;
88
+ if (color) {
89
+ styles.push(`color:rgb(${color})`);
90
+ }
91
+ if (background) {
92
+ styles.push(`background-color:rgb(${background})`);
93
+ }
94
+ if (textDecorations.length > 0) {
95
+ styles.push(`text-decoration:${textDecorations.join(' ')}`);
96
+ }
97
+ const escapedValue = escapeHTML(value);
98
+ const href = url ? JSON.stringify(escapeHTML(url)) : null;
99
+ if (styles.length <= 0) {
100
+ if (!href) {
101
+ return escapedValue;
102
+ }
103
+ return `<a href=${href} target="_blank">${escapedValue}</a>`;
104
+ }
105
+ const inlineStyle = JSON.stringify(`${styles.join(';')};`);
106
+ if (!href) {
107
+ return `<span style=${inlineStyle}>${escapedValue}</span>`;
108
+ }
109
+ return `<a style=${inlineStyle} href=${href} target="_blank">${escapedValue}</a>`;
110
+ }
111
+ function ansiToHTML(text) {
112
+ let html = '';
113
+ ansi.write(text, block => {
114
+ html += blockToHTML(block);
115
+ });
116
+ ansi.flush(block => {
117
+ html += blockToHTML(block);
118
+ });
119
+ return html;
120
+ }
121
+
122
+ exports.ansiToHTML = ansiToHTML;
123
+ exports.appendHTML = appendHTML;
124
+ exports.blockToHTML = blockToHTML;
125
+ exports.escapeHTML = escapeHTML;
126
+ exports.injectCSS = injectCSS;
@@ -0,0 +1,126 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.1.0
5
+ * @author nuintun <nuintun@qq.com>
6
+ * @description A koa 2 middleware for webpack development and hot reloading.
7
+ * @see https://github.com/nuintun/webpack-dev-service#readme
8
+ */
9
+
10
+ import { emit } from './events.js';
11
+ import Overlay from './ui/overlay.js';
12
+ import Progress from './ui/progress.js';
13
+ import { applyUpdate, setHash } from './hot.js';
14
+
15
+ /**
16
+ * @module client
17
+ */
18
+ function createClient(options) {
19
+ let updateTimer;
20
+ const UPDATE_DELAY = 128;
21
+ const RETRY_INTERVAL = 3000;
22
+ const progress = new Progress();
23
+ const overlay = new Overlay(options.name);
24
+ const fallback = error => {
25
+ if (options.live) {
26
+ self.location.reload();
27
+ } else if (error) {
28
+ console.error(error);
29
+ console.warn('Use fallback update but you turn off live reload, please reload by yourself.');
30
+ }
31
+ };
32
+ const applyUpdateAsync = () => {
33
+ updateTimer = self.setTimeout(() => {
34
+ applyUpdate(options.hmr, fallback);
35
+ }, UPDATE_DELAY);
36
+ };
37
+ const onInvalid = () => {
38
+ clearTimeout(updateTimer);
39
+ if (options.progress) {
40
+ progress.update(0);
41
+ progress.show();
42
+ }
43
+ };
44
+ const onProgress = ({ value }) => {
45
+ if (options.progress) {
46
+ progress.update(value);
47
+ }
48
+ };
49
+ const onHash = ({ hash }) => {
50
+ setHash(hash);
51
+ };
52
+ const setProblems = (type, problems) => {
53
+ const maps = {
54
+ errors: ['Error', 'error'],
55
+ warnings: ['Warning', 'warn']
56
+ };
57
+ if (options.overlay) {
58
+ overlay.setProblems(type, problems);
59
+ }
60
+ const [name, method] = maps[type];
61
+ const debug = console[method];
62
+ for (const { moduleName, message } of problems) {
63
+ debug(`\x1b[0m${name} in ${moduleName}\r\n\x1b[0m${message}`);
64
+ }
65
+ };
66
+ const onProblems = ({ errors, warnings }) => {
67
+ progress.hide();
68
+ setProblems('errors', errors);
69
+ setProblems('warnings', warnings);
70
+ if (options.overlay) {
71
+ overlay.show();
72
+ }
73
+ if (errors.length <= 0) {
74
+ applyUpdateAsync();
75
+ }
76
+ };
77
+ const onSuccess = () => {
78
+ overlay.hide();
79
+ progress.hide();
80
+ applyUpdateAsync();
81
+ };
82
+ const parseMessage = message => {
83
+ try {
84
+ return JSON.parse(message.data);
85
+ } catch {
86
+ return null;
87
+ }
88
+ };
89
+ const createWebSocket = url => {
90
+ const ws = new WebSocket(url);
91
+ ws.onmessage = message => {
92
+ const parsed = parseMessage(message);
93
+ if (parsed) {
94
+ const { action, payload } = parsed;
95
+ switch (action) {
96
+ case 'invalid':
97
+ onInvalid();
98
+ break;
99
+ case 'progress':
100
+ onProgress(payload);
101
+ break;
102
+ case 'hash':
103
+ onHash(payload);
104
+ break;
105
+ case 'problems':
106
+ onProblems(payload);
107
+ break;
108
+ case 'ok':
109
+ onSuccess();
110
+ break;
111
+ }
112
+ emit(action, payload, options);
113
+ }
114
+ };
115
+ ws.onclose = () => {
116
+ overlay.hide();
117
+ progress.hide();
118
+ setTimeout(() => {
119
+ createWebSocket(url);
120
+ }, RETRY_INTERVAL);
121
+ };
122
+ };
123
+ createWebSocket(options.host + options.path);
124
+ }
125
+
126
+ export { createClient as default };
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.1.0
5
+ * @author nuintun <nuintun@qq.com>
6
+ * @description A koa 2 middleware for webpack development and hot reloading.
7
+ * @see https://github.com/nuintun/webpack-dev-service#readme
8
+ */
9
+
10
+ /**
11
+ * @module events
12
+ */
13
+ const events = {
14
+ ok: [],
15
+ hash: [],
16
+ invalid: [],
17
+ problems: [],
18
+ progress: []
19
+ };
20
+ /**
21
+ * @function on
22
+ * @description Add an event listener callback.
23
+ * @param event Event name.
24
+ * @param callback Event listener callback.
25
+ */
26
+ function on(event, callback) {
27
+ const callbacks = events[event];
28
+ if (callbacks) {
29
+ callbacks.push(callback);
30
+ }
31
+ }
32
+ /**
33
+ * @function off
34
+ * @description Remove an event listener callback.
35
+ * @param event Event name.
36
+ * @param callback Event listener callback.
37
+ */
38
+ function off(event, callback) {
39
+ const callbacks = events[event];
40
+ if (callbacks) {
41
+ if (callback) {
42
+ const index = callbacks.indexOf(callback);
43
+ if (index >= 0) {
44
+ callbacks.splice(index, 1);
45
+ }
46
+ } else {
47
+ events[event] = [];
48
+ }
49
+ }
50
+ }
51
+ function emit(event, message, options) {
52
+ const callbacks = events[event];
53
+ if (callbacks && callbacks.length > 0) {
54
+ for (const callback of callbacks) {
55
+ callback(message, options);
56
+ }
57
+ }
58
+ }
59
+
60
+ export { emit, off, on };
@@ -0,0 +1,106 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.1.0
5
+ * @author nuintun <nuintun@qq.com>
6
+ * @description A koa 2 middleware for webpack development and hot reloading.
7
+ * @see https://github.com/nuintun/webpack-dev-service#readme
8
+ */
9
+
10
+ /**
11
+ * @module hot
12
+ */
13
+ // Last error.
14
+ let error;
15
+ // Last update hash.
16
+ let hash = __webpack_hash__;
17
+ // HMR status.
18
+ let status = 'idle';
19
+ /**
20
+ * @function isUpdateAvailable
21
+ * @description Is there a newer version of this code available.
22
+ */
23
+ function isUpdateAvailable() {
24
+ // __webpack_hash__ is the hash of the current compilation.
25
+ // It's a global variable injected by webpack.
26
+ return hash !== __webpack_hash__;
27
+ }
28
+ /**
29
+ * @function setHash
30
+ * @description Set webpack hash.
31
+ * @param value - The new hash value.
32
+ */
33
+ function setHash(value) {
34
+ hash = value;
35
+ }
36
+ /**
37
+ * @function setStatus
38
+ * @description Set hot status.
39
+ * @param value The new status of the hot update.
40
+ */
41
+ function setStatus(value) {
42
+ status = value;
43
+ }
44
+ // Initialize status.
45
+ if (import.meta.webpackHot) {
46
+ setStatus(import.meta.webpackHot.status());
47
+ }
48
+ /**
49
+ * @function applyUpdate
50
+ * @description Apply update.
51
+ * @param hmr Whether to enable HMR.
52
+ * @param fallback Fallback function when HMR fail.
53
+ */
54
+ function applyUpdate(hmr, fallback) {
55
+ // Update available.
56
+ if (isUpdateAvailable()) {
57
+ // HMR enabled.
58
+ if (hmr && import.meta.webpackHot) {
59
+ switch (status) {
60
+ case 'idle':
61
+ // Set status.
62
+ setStatus('check');
63
+ // Auto check and apply updates.
64
+ import.meta.webpackHot
65
+ .check(true)
66
+ .then(updated => {
67
+ // Update status.
68
+ setStatus(import.meta.webpackHot.status());
69
+ // When updated modules is available,
70
+ // it indicates server is ready to serve new bundle.
71
+ if (updated) {
72
+ // While update completed, do it again until no update available.
73
+ applyUpdate(hmr, fallback);
74
+ }
75
+ })
76
+ .catch(exception => {
77
+ // Get status.
78
+ const status = import.meta.webpackHot.status();
79
+ // Update status.
80
+ switch (status) {
81
+ case 'fail':
82
+ case 'abort':
83
+ setStatus(status);
84
+ default:
85
+ setStatus('fail');
86
+ }
87
+ // Cache error.
88
+ error = exception;
89
+ // Call fallback.
90
+ fallback(error);
91
+ });
92
+ break;
93
+ case 'fail':
94
+ case 'abort':
95
+ // Call fallback.
96
+ fallback(error);
97
+ break;
98
+ }
99
+ } else {
100
+ // HMR disabled.
101
+ fallback();
102
+ }
103
+ }
104
+ }
105
+
106
+ export { applyUpdate, isUpdateAvailable, setHash, setStatus };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.1.0
5
+ * @author nuintun <nuintun@qq.com>
6
+ * @description A koa 2 middleware for webpack development and hot reloading.
7
+ * @see https://github.com/nuintun/webpack-dev-service#readme
8
+ */
9
+
10
+ export { off, on } from './events.js';
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.1.0
5
+ * @author nuintun <nuintun@qq.com>
6
+ * @description A koa 2 middleware for webpack development and hot reloading.
7
+ * @see https://github.com/nuintun/webpack-dev-service#readme
8
+ */
9
+
10
+ import createClient from './client.js';
11
+
12
+ /**
13
+ * @module main
14
+ */
15
+ const isTLS = protocol => {
16
+ return protocol === 'https:';
17
+ };
18
+ const getCurrentScript = () => {
19
+ const { currentScript } = document;
20
+ if (currentScript) {
21
+ return currentScript;
22
+ }
23
+ };
24
+ const resolveHost = params => {
25
+ let host = params.get('host');
26
+ let tls = params.get('tls') || isTLS(self.location.protocol);
27
+ if (!host) {
28
+ const script = getCurrentScript();
29
+ if (script) {
30
+ const { src } = script;
31
+ const url = new URL(src);
32
+ host = url.host;
33
+ tls = isTLS(url.protocol) || tls;
34
+ } else {
35
+ host = self.location.host;
36
+ }
37
+ }
38
+ return `${tls ? 'wss' : 'ws'}://${host}`;
39
+ };
40
+ const resolveOptions = () => {
41
+ const params = new URLSearchParams(__resourceQuery);
42
+ const host = resolveHost(params);
43
+ const live = params.get('live') !== 'false';
44
+ const overlay = params.get('overlay') !== 'false';
45
+ try {
46
+ return { ...__WDS_HOT_OPTIONS__, host, live, overlay };
47
+ } catch {
48
+ throw new Error('Imported the hot client but the hot server is not enabled.');
49
+ }
50
+ };
51
+ createClient(resolveOptions());
@@ -0,0 +1,234 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.1.0
5
+ * @author nuintun <nuintun@qq.com>
6
+ * @description A koa 2 middleware for webpack development and hot reloading.
7
+ * @see https://github.com/nuintun/webpack-dev-service#readme
8
+ */
9
+
10
+ import { injectCSS, appendHTML, ansiToHTML } from './utils/index.js';
11
+
12
+ /**
13
+ * @module overlay
14
+ * @see https://github.com/shellscape/webpack-plugin-serve
15
+ */
16
+ const OVERLAY = 'wds-overlay';
17
+ const CSS = `
18
+ .${OVERLAY} {
19
+ top:0;
20
+ left: 0;
21
+ right: 0;
22
+ bottom: 0;
23
+ display: flex;
24
+ position: fixed;
25
+ font-size: 16px;
26
+ overflow: hidden;
27
+ font-style: normal;
28
+ font-weight: normal;
29
+ z-index: 2147483646;
30
+ flex-direction: column;
31
+ box-sizing: border-box;
32
+ transform-origin: center;
33
+ background: rgba(0, 0, 0, .85);
34
+ transform: scale(0) translateZ(0);
35
+ transition: transform .25s ease-out;
36
+ font-family: Consolas, "Lucida Console", monospace;
37
+ }
38
+ .${OVERLAY}-show {
39
+ transform: scale(1) translateZ(0);
40
+ }
41
+ .${OVERLAY}-close {
42
+ top: 16px;
43
+ right: 16px;
44
+ width: 16px;
45
+ height: 16px;
46
+ cursor: pointer;
47
+ position: absolute;
48
+ border-radius: 16px;
49
+ background: #ff5f58;
50
+ display: inline-block;
51
+ transform-origin: center;
52
+ box-shadow: #ff5f58 0 0 6px;
53
+ transform: rotate(0) translateZ(0);
54
+ transition: transform .25s ease-in-out;
55
+ }
56
+ .${OVERLAY}-close:before,
57
+ .${OVERLAY}-close:after {
58
+ top: 7px;
59
+ left: 3px;
60
+ content: "";
61
+ width: 10px;
62
+ height: 2px;
63
+ position: absolute;
64
+ background-color: white;
65
+ transform-origin: center;
66
+ }
67
+ .${OVERLAY}-close:before {
68
+ transform: rotate(45deg);
69
+ }
70
+ .${OVERLAY}-close:after {
71
+ transform: rotate(-45deg);
72
+ }
73
+ .${OVERLAY}-close:hover {
74
+ transform: rotate(180deg) translateZ(0);
75
+ }
76
+ .${OVERLAY}-title {
77
+ margin: 0;
78
+ color: #fff;
79
+ line-height: 16px;
80
+ text-align: center;
81
+ background: #282d35;
82
+ overflow-wrap: break-word;
83
+ border-radius: 0 0 4px 4px;
84
+ padding: 16px 48px 16px 16px;
85
+ }
86
+ .${OVERLAY}-name {
87
+ font-weight: bold;
88
+ font-style: normal;
89
+ text-transform: uppercase;
90
+ }
91
+ .${OVERLAY}-errors-title,
92
+ .${OVERLAY}-warnings-title {
93
+ color: #ff5f58;
94
+ padding-left: 8px;
95
+ font-style: normal;
96
+ }
97
+ .${OVERLAY}-warnings-title {
98
+ color: #ffbd2e;
99
+ }
100
+ .${OVERLAY}-problems {
101
+ padding: 0 16px;
102
+ overflow-y: auto;
103
+ scrollbar-width: none;
104
+ -ms-overflow-style: none;
105
+ -ms-scroll-chaining: none;
106
+ overscroll-behavior: contain;
107
+ -webkit-overflow-scrolling: touch;
108
+ }
109
+ .${OVERLAY}-problems::-webkit-scrollbar {
110
+ display: none;
111
+ }
112
+ .${OVERLAY}-errors,
113
+ .${OVERLAY}-warnings {
114
+ color: #ddd;
115
+ padding: 16px;
116
+ margin: 16px 0;
117
+ display: block;
118
+ line-height: 1.2;
119
+ border-radius: 4px;
120
+ background: #282d35;
121
+ white-space: pre-wrap;
122
+ font-family: Consolas, "Lucida Console", monospace;
123
+ }
124
+ .${OVERLAY}-errors > div,
125
+ .${OVERLAY}-warnings > div {
126
+ overflow-wrap: break-word;
127
+ }
128
+ .${OVERLAY}-errors > div + div,
129
+ .${OVERLAY}-warnings > div + div {
130
+ margin: 16px 0 0;
131
+ }
132
+ .${OVERLAY}-errors > div > em,
133
+ .${OVERLAY}-warnings > div > em {
134
+ line-height: 1;
135
+ color: #641e16;
136
+ padding: 4px 8px;
137
+ font-style: normal;
138
+ border-radius: 4px;
139
+ font-weight: normal;
140
+ background: #ff5f58;
141
+ display: inline-block;
142
+ text-transform: uppercase;
143
+ }
144
+ .${OVERLAY}-warnings > div > em {
145
+ color: #3e2723;
146
+ background: #ffbd2e;
147
+ }
148
+ .${OVERLAY}-errors > div > div,
149
+ .${OVERLAY}-warnings > div > div {
150
+ font-size: 14px;
151
+ padding: 8px 0 0 16px;
152
+ overflow-wrap: break-word;
153
+ }
154
+ .${OVERLAY}-hidden {
155
+ display: none;
156
+ }
157
+ `;
158
+ const DEFAULT_NAME = 'webpack';
159
+ const HTML = `
160
+ <aside class="${OVERLAY}">
161
+ <i class="${OVERLAY}-close"></i>
162
+ <div class="${OVERLAY}-title">
163
+ <em class="${OVERLAY}-name"></em>
164
+ <em class="${OVERLAY}-errors-title"></em>
165
+ <em class="${OVERLAY}-warnings-title"></em>
166
+ </div>
167
+ <article class="${OVERLAY}-problems">
168
+ <pre class="${OVERLAY}-errors ${OVERLAY}-hidden"></pre>
169
+ <pre class="${OVERLAY}-warnings ${OVERLAY}-hidden"></pre>
170
+ </article>
171
+ </aside>
172
+ `;
173
+ class Overlay {
174
+ hidden = true;
175
+ name;
176
+ close;
177
+ aside;
178
+ errorsList;
179
+ errorsTitle;
180
+ warningsList;
181
+ warningsTitle;
182
+ constructor(name) {
183
+ injectCSS(CSS);
184
+ [this.aside] = appendHTML(HTML);
185
+ this.name = this.aside.querySelector(`.${OVERLAY}-name`);
186
+ this.close = this.aside.querySelector(`.${OVERLAY}-close`);
187
+ this.errorsList = this.aside.querySelector(`.${OVERLAY}-errors`);
188
+ this.warningsList = this.aside.querySelector(`.${OVERLAY}-warnings`);
189
+ this.errorsTitle = this.aside.querySelector(`.${OVERLAY}-errors-title`);
190
+ this.warningsTitle = this.aside.querySelector(`.${OVERLAY}-warnings-title`);
191
+ this.name.innerHTML = `⭕ ${name || DEFAULT_NAME}`;
192
+ this.close.addEventListener('click', () => {
193
+ this.hide();
194
+ });
195
+ }
196
+ setProblems(type, problems) {
197
+ const count = problems.length;
198
+ const hidden = `${OVERLAY}-hidden`;
199
+ const problemMaps = {
200
+ errors: ['Error', this.errorsTitle, this.errorsList],
201
+ warnings: ['Warning', this.warningsTitle, this.warningsList]
202
+ };
203
+ const [name, problemTitle, problemList] = problemMaps[type];
204
+ if (count > 0) {
205
+ let html = '';
206
+ problemTitle.innerText = `${count} ${name}(s)`;
207
+ for (const { moduleName = 'unknown', message } of problems) {
208
+ const src = ansiToHTML(moduleName);
209
+ const details = ansiToHTML(message);
210
+ html += `<div><em>${name}</em> in ${src}<div>${details}</div></div>`;
211
+ }
212
+ problemList.innerHTML = html;
213
+ problemList.classList.remove(hidden);
214
+ problemTitle.classList.remove(hidden);
215
+ } else {
216
+ problemList.classList.add(hidden);
217
+ problemTitle.classList.add(hidden);
218
+ }
219
+ }
220
+ show() {
221
+ if (this.hidden) {
222
+ this.hidden = false;
223
+ this.aside.classList.add(`${OVERLAY}-show`);
224
+ }
225
+ }
226
+ hide() {
227
+ if (!this.hidden) {
228
+ this.hidden = true;
229
+ this.aside.classList.remove(`${OVERLAY}-show`);
230
+ }
231
+ }
232
+ }
233
+
234
+ export { Overlay as default };