Skip to content

Commit 897b742

Browse files
refactor: regress before implementing info cmd
1 parent 6a2faf4 commit 897b742

2 files changed

Lines changed: 12 additions & 215 deletions

File tree

packages/webpack-cli/src/ui-renderer.ts

Lines changed: 0 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,6 @@ export interface CommandHelpData {
5959
globalOptions: HelpOption[];
6060
}
6161

62-
/** Passed to `renderCommandHeader` to describe the running command. */
63-
export interface CommandMeta {
64-
name: string;
65-
description: string;
66-
}
67-
68-
/** One section emitted by `renderInfoOutput`, e.g. "System" or "Binaries". */
69-
export interface InfoSection {
70-
title: string;
71-
rows: Row[];
72-
}
73-
7462
// ─── Layout constants ─────────────────────────────────────────────
7563
export const MAX_WIDTH = 80;
7664
export const INDENT = 2;
@@ -139,29 +127,6 @@ export function renderRows(
139127
}
140128
}
141129

142-
export function renderCommandHeader(meta: CommandMeta, opts: RenderOptions): void {
143-
const { colors, log } = opts;
144-
const termWidth = Math.min(opts.columns || MAX_WIDTH, MAX_WIDTH);
145-
146-
log("");
147-
log(`${indent(INDENT)}${colors.bold(colors.cyan("⬡"))} ${colors.bold(`webpack ${meta.name}`)}`);
148-
log(divider(termWidth, colors));
149-
150-
if (meta.description) {
151-
const descWidth = termWidth - INDENT * 2;
152-
for (const line of wrapValue(meta.description, descWidth)) {
153-
log(`${indent(INDENT)}${line}`);
154-
}
155-
log("");
156-
}
157-
}
158-
159-
export function renderCommandFooter(opts: RenderOptions): void {
160-
const termWidth = Math.min(opts.columns, MAX_WIDTH);
161-
opts.log(divider(termWidth, opts.colors));
162-
opts.log("");
163-
}
164-
165130
function _renderHelpOptions(
166131
options: HelpOption[],
167132
colors: Colors,
@@ -227,9 +192,6 @@ export function renderCommandHelp(data: CommandHelpData, opts: RenderOptions): v
227192
}
228193

229194
push(div);
230-
push(
231-
` ${colors.cyan("ℹ")} Run ${colors.bold(`'webpack help ${data.name} --verbose'`)} to see all available options.`,
232-
);
233195
push("");
234196

235197
for (const line of lines) opts.log(line);
@@ -274,116 +236,6 @@ export function renderAliasHelp(data: AliasHelpData, opts: RenderOptions): void
274236
renderOptionHelp(data.optionHelp, opts);
275237
}
276238

277-
export function renderError(message: string, opts: RenderOptions): void {
278-
const { colors, log } = opts;
279-
log(`${indent(INDENT)}${colors.red("✖")} ${colors.bold(message)}`);
280-
}
281-
282-
export function renderSuccess(message: string, opts: RenderOptions): void {
283-
const { colors, log } = opts;
284-
log(`${indent(INDENT)}${colors.green("✔")} ${colors.bold(message)}`);
285-
}
286-
287-
export function renderWarning(message: string, opts: RenderOptions): void {
288-
const { colors, log } = opts;
289-
log(`${indent(INDENT)}${colors.yellow("⚠")} ${message}`);
290-
}
291-
292-
export function renderInfo(message: string, opts: RenderOptions): void {
293-
const { colors, log } = opts;
294-
log(`${indent(INDENT)}${colors.cyan("ℹ")} ${message}`);
295-
}
296-
297-
export function parseEnvinfoSections(raw: string): InfoSection[] {
298-
const sections: InfoSection[] = [];
299-
let current: InfoSection | null = null;
300-
301-
for (const line of raw.split("\n")) {
302-
const sectionMatch = line.match(/^ {2}([^:]+):\s*$/);
303-
if (sectionMatch) {
304-
if (current) sections.push(current);
305-
current = { title: sectionMatch[1].trim(), rows: [] };
306-
continue;
307-
}
308-
309-
const rowMatch = line.match(/^ {4}([^:]+):\s+(.+)$/);
310-
if (rowMatch && current) {
311-
current.rows.push({ label: rowMatch[1].trim(), value: rowMatch[2].trim() });
312-
continue;
313-
}
314-
315-
const emptyRowMatch = line.match(/^ {4}([^:]+):\s*$/);
316-
if (emptyRowMatch && current) {
317-
current.rows.push({ label: emptyRowMatch[1].trim(), value: "N/A", color: (str) => str });
318-
}
319-
}
320-
321-
if (current) sections.push(current);
322-
return sections.filter((section) => section.rows.length > 0);
323-
}
324-
325-
export function renderInfoOutput(rawEnvinfo: string, opts: RenderOptions): void {
326-
const { colors, log } = opts;
327-
const termWidth = Math.min(opts.columns, MAX_WIDTH);
328-
const div = divider(termWidth, colors);
329-
const sections = parseEnvinfoSections(rawEnvinfo);
330-
331-
log("");
332-
333-
for (const section of sections) {
334-
log(
335-
`${indent(INDENT)}${colors.bold(colors.cyan("⬡"))} ${colors.bold(colors.cyan(section.title))}`,
336-
);
337-
log(div);
338-
renderRows(section.rows, colors, log, termWidth);
339-
log(div);
340-
log("");
341-
}
342-
}
343-
344-
export function renderVersionOutput(rawEnvinfo: string, opts: RenderOptions): void {
345-
const { colors, log } = opts;
346-
const termWidth = Math.min(opts.columns, MAX_WIDTH);
347-
const div = divider(termWidth, colors);
348-
const sections = parseEnvinfoSections(rawEnvinfo);
349-
350-
for (const section of sections) {
351-
log("");
352-
log(
353-
`${indent(INDENT)}${colors.bold(colors.cyan("⬡"))} ${colors.bold(colors.cyan(section.title))}`,
354-
);
355-
log(div);
356-
357-
const labelWidth = Math.max(...section.rows.map((row) => row.label.length));
358-
359-
for (const { label, value } of section.rows) {
360-
const arrowIdx = value.indexOf("=>");
361-
362-
if (arrowIdx !== -1) {
363-
const requested = value.slice(0, arrowIdx).trim();
364-
const resolved = value.slice(arrowIdx + 2).trim();
365-
log(
366-
`${indent(INDENT)}${colors.bold(label.padEnd(labelWidth))}${indent(COL_GAP)}` +
367-
`${colors.cyan(requested.padEnd(12))} ${colors.cyan("→")} ${colors.green(colors.bold(resolved))}`,
368-
);
369-
} else {
370-
log(
371-
`${indent(INDENT)}${colors.bold(label.padEnd(labelWidth))}${indent(COL_GAP)}${colors.green(value)}`,
372-
);
373-
}
374-
}
375-
log(div);
376-
}
377-
}
378-
379-
export function renderSection(title: string, opts: RenderOptions): void {
380-
const { colors, log } = opts;
381-
const termWidth = Math.min(opts.columns, MAX_WIDTH);
382-
log("");
383-
log(`${indent(INDENT)}${colors.bold(title)}`);
384-
log(divider(termWidth, colors));
385-
}
386-
387239
export function renderFooter(opts: RenderOptions, footer: FooterOptions = {}): void {
388240
const { colors, log } = opts;
389241

packages/webpack-cli/src/webpack-cli.ts

Lines changed: 12 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,9 @@ import {
3636
HelpOption,
3737
RenderOptions,
3838
renderAliasHelp,
39-
renderCommandFooter,
40-
renderCommandHeader,
4139
renderCommandHelp,
42-
renderError,
4340
renderFooter,
44-
renderInfoOutput,
4541
renderOptionHelp,
46-
renderSuccess,
47-
renderVersionOutput,
48-
renderWarning,
4942
} from "./ui-renderer.js";
5043

5144
const WEBPACK_PACKAGE_IS_CUSTOM = Boolean(process.env.WEBPACK_PACKAGE);
@@ -117,7 +110,6 @@ interface CommandOptions<
117110
dependencies?: string[];
118111
pkg?: string;
119112
preload?: () => Promise<C>;
120-
header?: { name: string; description: string };
121113
options?:
122114
| CommandOption[]
123115
| ((command: Command & { context: C }) => CommandOption[])
@@ -672,8 +664,6 @@ class WebpackCLI {
672664
}
673665
}
674666

675-
// Without this, `webpack watch --help` would start the watcher (never exits).
676-
command.addOption(new Option("-h, --help [verbose]", "Display help for commands and options."));
677667
command.hook("preAction", async (thisCommand) => {
678668
const opts = thisCommand.opts();
679669

@@ -690,7 +680,6 @@ class WebpackCLI {
690680
this.program,
691681
isVerbose,
692682
);
693-
694683
renderCommandHelp(commandHelpData, this.#renderOptions());
695684
renderFooter(this.#renderOptions(), { verbose: isVerbose });
696685
process.exit(0);
@@ -1032,16 +1021,12 @@ class WebpackCLI {
10321021
}
10331022

10341023
#renderOptions(): RenderOptions {
1035-
const helpConfig = this.program.configureHelp();
1036-
const columns =
1037-
typeof helpConfig.helpWidth === "number"
1038-
? helpConfig.helpWidth
1039-
: (process.stdout.columns ?? 80);
1040-
10411024
return {
10421025
colors: this.colors,
10431026
log: (line) => this.logger.raw(line),
1044-
columns,
1027+
// process.stdout.columns can be undefined in non-TTY environments
1028+
// (CI, test runners, pipes). Fall back to 80 which fits most terminals.
1029+
columns: process.stdout.columns ?? 80,
10451030
};
10461031
}
10471032

@@ -1860,28 +1845,9 @@ class WebpackCLI {
18601845
},
18611846
],
18621847
action: async (options: { output?: string }) => {
1863-
const renderOpts = this.#renderOptions();
1864-
1865-
if (options.output) {
1866-
// Machine-readable output requested, bypass the visual renderer entirely.
1867-
const info = await this.#renderVersion(options);
1868-
this.logger.raw(info);
1869-
return;
1870-
}
1848+
const info = await this.#renderVersion(options);
18711849

1872-
renderCommandHeader(
1873-
{ name: "version", description: "Installed package versions." },
1874-
renderOpts,
1875-
);
1876-
1877-
const rawInfo = await this.#getInfoOutput({
1878-
information: {
1879-
npmPackages: `{${DEFAULT_WEBPACK_PACKAGES.map((item) => `*${item}*`).join(",")}}`,
1880-
},
1881-
});
1882-
1883-
renderVersionOutput(rawInfo, renderOpts);
1884-
renderFooter(renderOpts);
1850+
this.logger.raw(info);
18851851
},
18861852
},
18871853
info: {
@@ -1912,23 +1878,9 @@ class WebpackCLI {
19121878
},
19131879
],
19141880
action: async (options: { output?: string; additionalPackage?: string[] }) => {
1915-
const renderOpts = this.#renderOptions();
1916-
1917-
if (!options.output) {
1918-
renderCommandHeader(
1919-
{ name: "info", description: "System and environment information." },
1920-
renderOpts,
1921-
);
1922-
}
1923-
19241881
const info = await this.#getInfoOutput(options);
19251882

1926-
if (options.output) {
1927-
this.logger.raw(info);
1928-
return;
1929-
}
1930-
1931-
renderInfoOutput(info, renderOpts);
1883+
this.logger.raw(info);
19321884
},
19331885
},
19341886
configtest: {
@@ -1950,7 +1902,6 @@ class WebpackCLI {
19501902
configPath ? { env, argv, webpack, config: [configPath] } : { env, argv, webpack },
19511903
);
19521904
const configPaths = new Set<string>();
1953-
const renderOpts = this.#renderOptions();
19541905

19551906
if (Array.isArray(config.options)) {
19561907
for (const options of config.options) {
@@ -1969,31 +1920,25 @@ class WebpackCLI {
19691920
}
19701921

19711922
if (configPaths.size === 0) {
1972-
renderError("No configuration found.", renderOpts);
1923+
this.logger.error("No configuration found.");
19731924
process.exit(2);
19741925
}
19751926

1976-
renderCommandHeader(
1977-
{ name: "configtest", description: "Validating your webpack configuration." },
1978-
renderOpts,
1979-
);
1980-
1981-
const pathList = [...configPaths].join(", ");
1982-
renderWarning(`Validating: ${pathList}`, renderOpts);
1927+
this.logger.info(`Validate '${[...configPaths].join(" ,")}'.`);
19831928

19841929
try {
19851930
cmd.context.webpack.validate(config.options);
19861931
} catch (error) {
19871932
if (this.isValidationError(error as Error)) {
1988-
renderError((error as Error).message, renderOpts);
1933+
this.logger.error((error as Error).message);
19891934
} else {
1990-
renderError(String(error), renderOpts);
1935+
this.logger.error(error);
19911936
}
1937+
19921938
process.exit(2);
19931939
}
19941940

1995-
renderSuccess("No validation errors found.", renderOpts);
1996-
renderCommandFooter(renderOpts);
1941+
this.logger.success("There are no validation errors in the given webpack configuration.");
19971942
},
19981943
},
19991944
};

0 commit comments

Comments
 (0)