UNPKG

8.6 kBJavaScriptView Raw
1export class ColoredConsole {
2 constructor(targetElement) {
3 this.targetElement = targetElement;
4 this.state = {
5 bold: false,
6 italic: false,
7 underline: false,
8 strikethrough: false,
9 foregroundColor: null,
10 backgroundColor: null,
11 carriageReturn: false,
12 secret: false,
13 };
14 }
15 logs() {
16 return this.targetElement.innerText;
17 }
18 addLine(line) {
19 // @ts-expect-error
20 const re = /(?:\033|\\033)(?:\[(.*?)[@-~]|\].*?(?:\007|\033\\))/g;
21 let i = 0;
22 if (this.state.carriageReturn) {
23 if (line !== "\n") {
24 // don't remove if \r\n
25 this.targetElement.removeChild(this.targetElement.lastChild);
26 }
27 this.state.carriageReturn = false;
28 }
29 if (line.includes("\r")) {
30 this.state.carriageReturn = true;
31 }
32 const lineSpan = document.createElement("span");
33 lineSpan.classList.add("line");
34 this.targetElement.appendChild(lineSpan);
35 const addSpan = (content) => {
36 if (content === "")
37 return;
38 const span = document.createElement("span");
39 if (this.state.bold)
40 span.classList.add("log-bold");
41 if (this.state.italic)
42 span.classList.add("log-italic");
43 if (this.state.underline)
44 span.classList.add("log-underline");
45 if (this.state.strikethrough)
46 span.classList.add("log-strikethrough");
47 if (this.state.secret)
48 span.classList.add("log-secret");
49 if (this.state.foregroundColor !== null)
50 span.classList.add(`log-fg-${this.state.foregroundColor}`);
51 if (this.state.backgroundColor !== null)
52 span.classList.add(`log-bg-${this.state.backgroundColor}`);
53 span.appendChild(document.createTextNode(content));
54 lineSpan.appendChild(span);
55 if (this.state.secret) {
56 const redacted = document.createElement("span");
57 redacted.classList.add("log-secret-redacted");
58 redacted.appendChild(document.createTextNode("[redacted]"));
59 lineSpan.appendChild(redacted);
60 }
61 };
62 while (true) {
63 const match = re.exec(line);
64 if (match === null)
65 break;
66 const j = match.index;
67 addSpan(line.substring(i, j));
68 i = j + match[0].length;
69 if (match[1] === undefined)
70 continue;
71 for (const colorCode of match[1].split(";")) {
72 switch (parseInt(colorCode)) {
73 case 0:
74 // reset
75 this.state.bold = false;
76 this.state.italic = false;
77 this.state.underline = false;
78 this.state.strikethrough = false;
79 this.state.foregroundColor = null;
80 this.state.backgroundColor = null;
81 this.state.secret = false;
82 break;
83 case 1:
84 this.state.bold = true;
85 break;
86 case 3:
87 this.state.italic = true;
88 break;
89 case 4:
90 this.state.underline = true;
91 break;
92 case 5:
93 this.state.secret = true;
94 break;
95 case 6:
96 this.state.secret = false;
97 break;
98 case 9:
99 this.state.strikethrough = true;
100 break;
101 case 22:
102 this.state.bold = false;
103 break;
104 case 23:
105 this.state.italic = false;
106 break;
107 case 24:
108 this.state.underline = false;
109 break;
110 case 29:
111 this.state.strikethrough = false;
112 break;
113 case 30:
114 this.state.foregroundColor = "black";
115 break;
116 case 31:
117 this.state.foregroundColor = "red";
118 break;
119 case 32:
120 this.state.foregroundColor = "green";
121 break;
122 case 33:
123 this.state.foregroundColor = "yellow";
124 break;
125 case 34:
126 this.state.foregroundColor = "blue";
127 break;
128 case 35:
129 this.state.foregroundColor = "magenta";
130 break;
131 case 36:
132 this.state.foregroundColor = "cyan";
133 break;
134 case 37:
135 this.state.foregroundColor = "white";
136 break;
137 case 39:
138 this.state.foregroundColor = null;
139 break;
140 case 41:
141 this.state.backgroundColor = "red";
142 break;
143 case 42:
144 this.state.backgroundColor = "green";
145 break;
146 case 43:
147 this.state.backgroundColor = "yellow";
148 break;
149 case 44:
150 this.state.backgroundColor = "blue";
151 break;
152 case 45:
153 this.state.backgroundColor = "magenta";
154 break;
155 case 46:
156 this.state.backgroundColor = "cyan";
157 break;
158 case 47:
159 this.state.backgroundColor = "white";
160 break;
161 case 40:
162 case 49:
163 this.state.backgroundColor = null;
164 break;
165 }
166 }
167 }
168 const atBottom = this.targetElement.scrollTop >
169 this.targetElement.scrollHeight - this.targetElement.offsetHeight - 50;
170 addSpan(line.substring(i));
171 // Keep scroll at bottom
172 if (atBottom) {
173 this.targetElement.scrollTop = this.targetElement.scrollHeight;
174 }
175 }
176}
177export const coloredConsoleStyles = `
178 .log {
179 flex: 1;
180 background-color: #1c1c1c;
181 font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier,
182 monospace;
183 font-size: 12px;
184 padding: 16px;
185 overflow: auto;
186 line-height: 1.45;
187 border-radius: 3px;
188 white-space: pre-wrap;
189 overflow-wrap: break-word;
190 color: #ddd;
191 }
192
193 .log-bold {
194 font-weight: bold;
195 }
196 .log-italic {
197 font-style: italic;
198 }
199 .log-underline {
200 text-decoration: underline;
201 }
202 .log-strikethrough {
203 text-decoration: line-through;
204 }
205 .log-underline.log-strikethrough {
206 text-decoration: underline line-through;
207 }
208 .log-secret {
209 -webkit-user-select: none;
210 -moz-user-select: none;
211 -ms-user-select: none;
212 user-select: none;
213 }
214 .log-secret-redacted {
215 opacity: 0;
216 width: 1px;
217 font-size: 1px;
218 }
219 .log-fg-black {
220 color: rgb(128, 128, 128);
221 }
222 .log-fg-red {
223 color: rgb(255, 0, 0);
224 }
225 .log-fg-green {
226 color: rgb(0, 255, 0);
227 }
228 .log-fg-yellow {
229 color: rgb(255, 255, 0);
230 }
231 .log-fg-blue {
232 color: rgb(0, 0, 255);
233 }
234 .log-fg-magenta {
235 color: rgb(255, 0, 255);
236 }
237 .log-fg-cyan {
238 color: rgb(0, 255, 255);
239 }
240 .log-fg-white {
241 color: rgb(187, 187, 187);
242 }
243 .log-bg-black {
244 background-color: rgb(0, 0, 0);
245 }
246 .log-bg-red {
247 background-color: rgb(255, 0, 0);
248 }
249 .log-bg-green {
250 background-color: rgb(0, 255, 0);
251 }
252 .log-bg-yellow {
253 background-color: rgb(255, 255, 0);
254 }
255 .log-bg-blue {
256 background-color: rgb(0, 0, 255);
257 }
258 .log-bg-magenta {
259 background-color: rgb(255, 0, 255);
260 }
261 .log-bg-cyan {
262 background-color: rgb(0, 255, 255);
263 }
264 .log-bg-white {
265 background-color: rgb(255, 255, 255);
266 }
267`;