source: frontend/node_modules/webpack/lib/node/nodeConsole.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 6.7 KB
RevLine 
[9af201e]1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const util = require("util");
9const truncateArgs = require("../logging/truncateArgs");
10const memoize = require("../util/memoize");
11
12const getCli = memoize(() => require("../cli"));
13
14const ESC = "\u001B[";
15const CURSOR_UP = `${ESC}1A`;
16const CLEAR_LINE = `${ESC}2K\r`;
17
18/** @typedef {import("../Compiler")} Compiler */
19/** @typedef {import("../config/defaults").InfrastructureLoggingNormalizedWithDefaults} InfrastructureLoggingNormalizedWithDefaults */
20/** @typedef {import("../logging/createConsoleLogger").LoggerConsole} LoggerConsole */
21/**
22 * @typedef {object} StatusMessageState
23 * @property {string[] | undefined} currentMessage current status message
24 * @property {number} currentLines current status message rows
25 */
26
27/** @type {WeakMap<Compiler, StatusMessageState>} */
28const logStatusStateByCompiler = new WeakMap();
29/** @type {Set<StatusMessageState>} */
30const logStatusStates = new Set();
31
32/**
33 * Returns status state
34 * @param {Compiler} compiler compiler
35 * @returns {StatusMessageState} status state
36 */
37const getLogStatusState = (compiler) => {
38 let state = logStatusStateByCompiler.get(compiler);
39 if (state === undefined) {
40 state = {
41 currentMessage: undefined,
42 currentLines: 0
43 };
44 logStatusStateByCompiler.set(compiler, state);
45 logStatusStates.add(state);
46 }
47 return state;
48};
49
50/* eslint-disable no-console */
51
52/**
53 * Returns logger function.
54 * @param {object} options options
55 * @param {boolean=} options.colors colors
56 * @param {boolean=} options.appendOnly append only
57 * @param {InfrastructureLoggingNormalizedWithDefaults["stream"]} options.stream stream
58 * @param {Compiler} options.compiler compiler
59 * @returns {LoggerConsole} logger function
60 */
61module.exports = ({ colors, appendOnly, stream, compiler }) => {
62 const c = getCli().createColors({ useColor: Boolean(colors) });
63 const logStatusState = getLogStatusState(compiler);
64
65 let currentIndent = "";
66 let currentCollapsed = 0;
67
68 /**
69 * Returns indented string.
70 * @param {string} str string
71 * @param {string} prefix prefix
72 * @param {(line: string) => string} colorFn color function
73 * @returns {string} indented string
74 */
75 const indent = (str, prefix, colorFn) => {
76 if (str === "") return str;
77 prefix = currentIndent + prefix;
78 return (
79 prefix +
80 str
81 .split("\n")
82 .map((line) => colorFn(line))
83 .join(`\n${prefix}`)
84 );
85 };
86
87 const clearStatusMessage = () => {
88 let lines = 0;
89 for (const state of logStatusStates) {
90 if (state.currentLines) {
91 lines += state.currentLines;
92 state.currentLines = 0;
93 }
94 }
95 for (let i = 0; i < lines; i++) {
96 if (i > 0) stream.write(CURSOR_UP);
97 stream.write(CLEAR_LINE);
98 }
99 };
100
101 const writeStatusMessage = () => {
102 const column = stream.columns || 40;
103 /** @type {string[]} */
104 const all = [];
105
106 for (const state of logStatusStates) {
107 if (!state.currentMessage) continue;
108 /** @type {string[][]} */
109 const lines = [[]];
110 for (const item of state.currentMessage) {
111 const parts = item.split("\n");
112 lines[lines.length - 1].push(parts[0]);
113 for (let i = 1; i < parts.length; i++) {
114 lines.push([parts[i]]);
115 }
116 }
117 const truncateLines = lines.map((args) =>
118 truncateArgs(args, column - 1).join(" ")
119 );
120 state.currentLines = truncateLines.length;
121 for (const line of truncateLines) all.push(line);
122 }
123 if (all.length === 0) return;
124
125 const coloredLines = all.map((str) => c.bold(str));
126 stream.write(`${CLEAR_LINE}${coloredLines.join(`\n${CLEAR_LINE}`)}`);
127 };
128
129 /**
130 * @param {EXPECTED_ANY[]} statusMessage status message
131 * @returns {void}
132 */
133 const setStatusMessage = (statusMessage) => {
134 clearStatusMessage();
135 logStatusState.currentMessage = statusMessage.map((item) => `${item}`);
136 writeStatusMessage();
137 };
138
139 /**
140 * Returns function to write with colors.
141 * @template T
142 * @param {string} prefix prefix
143 * @param {(line: string) => string} colorFn color function
144 * @returns {(...args: T[]) => void} function to write with colors
145 */
146 const writeColored =
147 (prefix, colorFn) =>
148 (...args) => {
149 if (currentCollapsed > 0) return;
150 clearStatusMessage();
151 const str = indent(util.format(...args), prefix, colorFn);
152 stream.write(`${str}\n`);
153 writeStatusMessage();
154 };
155
156 /** @type {<T extends unknown[]>(...args: T) => void} */
157 const writeGroupMessage = writeColored("<-> ", (str) => c.bold(c.cyan(str)));
158
159 /** @type {<T extends unknown[]>(...args: T) => void} */
160 const writeGroupCollapsedMessage = writeColored("<+> ", (str) =>
161 c.bold(c.cyan(str))
162 );
163
164 return {
165 /** @type {LoggerConsole["log"]} */
166 log: writeColored(" ", c.bold),
167 /** @type {LoggerConsole["debug"]} */
168 debug: writeColored(" ", String),
169 /** @type {LoggerConsole["trace"]} */
170 trace: writeColored(" ", String),
171 /** @type {LoggerConsole["info"]} */
172 info: writeColored("<i> ", (str) => c.bold(c.green(str))),
173 /** @type {LoggerConsole["warn"]} */
174 warn: writeColored("<w> ", (str) => c.bold(c.yellow(str))),
175 /** @type {LoggerConsole["error"]} */
176 error: writeColored("<e> ", (str) => c.bold(c.red(str))),
177 /** @type {LoggerConsole["logTime"]} */
178 logTime: writeColored("<t> ", (str) => c.bold(c.magenta(str))),
179 /** @type {LoggerConsole["group"]} */
180 group: (...args) => {
181 writeGroupMessage(...args);
182 if (currentCollapsed > 0) {
183 currentCollapsed++;
184 } else {
185 currentIndent += " ";
186 }
187 },
188 /** @type {LoggerConsole["groupCollapsed"]} */
189 groupCollapsed: (...args) => {
190 writeGroupCollapsedMessage(...args);
191 currentCollapsed++;
192 },
193 /** @type {LoggerConsole["groupEnd"]} */
194 groupEnd: () => {
195 if (currentCollapsed > 0) {
196 currentCollapsed--;
197 } else if (currentIndent.length >= 2) {
198 currentIndent = currentIndent.slice(0, -2);
199 }
200 },
201 /** @type {LoggerConsole["profile"]} */
202 profile: console.profile && ((name) => console.profile(name)),
203 /** @type {LoggerConsole["profileEnd"]} */
204 profileEnd: console.profileEnd && ((name) => console.profileEnd(name)),
205 /** @type {LoggerConsole["clear"]} */
206 clear:
207 /** @type {() => void} */
208 (
209 !appendOnly &&
210 console.clear &&
211 (() => {
212 clearStatusMessage();
213 console.clear();
214 writeStatusMessage();
215 })
216 ),
217 /** @type {LoggerConsole["status"]} */
218 status: appendOnly
219 ? writeColored("<s> ", String)
220 : (name, ...args) => {
221 args = args.filter(Boolean);
222 if (name === undefined && args.length === 0) {
223 clearStatusMessage();
224 logStatusState.currentMessage = undefined;
225 } else if (
226 typeof name === "string" &&
227 name.startsWith("[webpack.Progress] ")
228 ) {
229 setStatusMessage([name.slice(19), ...args]);
230 } else if (name === "[webpack.Progress]") {
231 setStatusMessage([...args]);
232 } else {
233 setStatusMessage([name, ...args]);
234 }
235 }
236 };
237};
Note: See TracBrowser for help on using the repository browser.