Skip to content

Commit fdbff33

Browse files
committed
feat(cli): replace @poppinss/cliui sticker for upload hints
1 parent a38e8cd commit fdbff33

File tree

6 files changed

+76
-33
lines changed

6 files changed

+76
-33
lines changed

packages/cli/src/lib/collect/collect-command.ts

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ import {
44
type CollectAndPersistReportsOptions,
55
collectAndPersistReports,
66
} from '@code-pushup/core';
7-
import { formatAsciiLink, logger, ui } from '@code-pushup/utils';
7+
import {
8+
formatAsciiLink,
9+
formatAsciiSticker,
10+
logger,
11+
} from '@code-pushup/utils';
812
import { CLI_NAME } from '../constants.js';
913
import {
1014
collectSuccessfulLog,
@@ -40,28 +44,20 @@ export function yargsCollectCommandObject(): CommandModule {
4044
}
4145

4246
export function renderUploadAutorunHint(): void {
43-
// TODO: replace @poppinss/cliui
44-
ui()
45-
.sticker()
46-
.add(ansis.bold.gray('💡 Visualize your reports'))
47-
.add('')
48-
.add(
47+
logger.info(
48+
formatAsciiSticker([
49+
ansis.bold.gray('💡 Visualize your reports'),
50+
'',
4951
`${ansis.gray('❯')} npx code-pushup upload - ${ansis.gray(
5052
'Run upload to upload the created report to the server',
5153
)}`,
52-
)
53-
.add(
5454
` ${formatAsciiLink(
5555
'https://github.com/code-pushup/cli/tree/main/packages/cli#upload-command',
5656
)}`,
57-
)
58-
.add(
5957
`${ansis.gray('❯')} npx code-pushup autorun - ${ansis.gray('Run collect & upload')}`,
60-
)
61-
.add(
6258
` ${formatAsciiLink(
6359
'https://github.com/code-pushup/cli/tree/main/packages/cli#autorun-command',
6460
)}`,
65-
)
66-
.render();
61+
]),
62+
);
6763
}
Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import ansis from 'ansis';
2-
import { formatAsciiLink, logger, ui } from '@code-pushup/utils';
2+
import {
3+
formatAsciiLink,
4+
formatAsciiSticker,
5+
logger,
6+
} from '@code-pushup/utils';
37

48
export function renderConfigureCategoriesHint(): void {
59
logger.debug(
@@ -19,30 +23,22 @@ export function collectSuccessfulLog(): void {
1923
}
2024

2125
export function renderIntegratePortalHint(): void {
22-
// TODO: replace @poppinss/cliui
23-
ui()
24-
.sticker()
25-
.add(ansis.bold.gray('💡 Integrate the portal'))
26-
.add('')
27-
.add(
26+
logger.info(
27+
formatAsciiSticker([
28+
ansis.bold.gray('💡 Integrate the portal'),
29+
'',
2830
`${ansis.gray('❯')} Upload a report to the server - ${ansis.gray(
2931
'npx code-pushup upload',
3032
)}`,
31-
)
32-
.add(
3333
` ${formatAsciiLink(
3434
'https://github.com/code-pushup/cli/tree/main/packages/cli#upload-command',
3535
)}`,
36-
)
37-
.add(
3836
`${ansis.gray('❯')} ${ansis.gray('Portal Integration')} - ${formatAsciiLink(
3937
'https://github.com/code-pushup/cli/blob/main/packages/cli/README.md#portal-integration',
4038
)}`,
41-
)
42-
.add(
4339
`${ansis.gray('❯')} ${ansis.gray('Upload Command')} - ${formatAsciiLink(
4440
'https://github.com/code-pushup/cli/blob/main/packages/cli/README.md#portal-integration',
4541
)}`,
46-
)
47-
.render();
42+
]),
43+
);
4844
}

packages/utils/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ export {
145145
} from './lib/reports/utils.js';
146146
export { isSemver, normalizeSemver, sortSemvers } from './lib/semver.js';
147147
export { formatAsciiLink } from './lib/text-formats/ascii/link.js';
148+
export { formatAsciiSticker } from './lib/text-formats/ascii/sticker.js';
148149
export { formatAsciiTable } from './lib/text-formats/ascii/table.js';
149150
export { formatAsciiTree } from './lib/text-formats/ascii/tree.js';
150151
export * from './lib/text-formats/index.js';
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { formatAsciiTable } from './table.js';
2+
3+
export function formatAsciiSticker(lines: string[]): string {
4+
return formatAsciiTable(
5+
{ rows: ['', ...lines, ''].map(line => [line]) },
6+
{ padding: 4 },
7+
);
8+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import ansis from 'ansis';
2+
import { formatAsciiSticker } from './sticker';
3+
4+
describe('formatAsciiSticker', () => {
5+
it('should frame lines with border and padding', () => {
6+
const output = formatAsciiSticker(['Hello,', 'How are you today?']);
7+
expect(ansis.strip(output)).toBe(
8+
`
9+
┌──────────────────────────┐
10+
│ │
11+
│ Hello, │
12+
│ How are you today? │
13+
│ │
14+
└──────────────────────────┘
15+
`.trim(),
16+
);
17+
});
18+
19+
it('should align emojis, color codes and line breaks correctly', () => {
20+
const output = formatAsciiSticker([
21+
`✅ ${ansis.bold('ESLint')} ${ansis.gray('(1.2 s)')}`,
22+
`✅ ${ansis.bold('Code Coverage')} ${ansis.gray('(680 ms)')}`,
23+
`❌ ${ansis.bold('Lighthouse')}\n - ${ansis.red('Unable to connect to Chrome')}`,
24+
]);
25+
expect(ansis.strip(output)).toBe(
26+
`
27+
┌────────────────────────────────────────┐
28+
│ │
29+
│ ✅ ESLint (1.2 s) │
30+
│ ✅ Code Coverage (680 ms) │
31+
│ ❌ Lighthouse │
32+
│ - Unable to connect to Chrome │
33+
│ │
34+
└────────────────────────────────────────┘
35+
`.trim(),
36+
);
37+
});
38+
});

packages/utils/src/lib/text-formats/ascii/table.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ function wrapRow(cells: TableCell[], columnWidths: number[]): TableCell[][] {
142142
const wrapped: string = wrapText(cell.text, columnWidths[colIndex]);
143143
const lines = wrapped.split('\n').filter(Boolean);
144144

145-
const rowCount = Math.max(acc.length, lines.length);
145+
const rowCount = Math.max(acc.length, lines.length, 1);
146146

147147
return Array.from({ length: rowCount }).map((_, rowIndex) => {
148148
const prevCols =
@@ -154,7 +154,7 @@ function wrapRow(cells: TableCell[], columnWidths: number[]): TableCell[][] {
154154
}
155155

156156
function wrapText(text: string, width: number | undefined): string {
157-
if (!width || stringWidth(text) <= width) {
157+
if (!width || getTextWidth(text) <= width) {
158158
return text;
159159
}
160160
const words = extractWords(text);
@@ -173,6 +173,10 @@ function wrapText(text: string, width: number | undefined): string {
173173
return wrapAnsi(textWithSplitLongWords, width);
174174
}
175175

176+
function getTextWidth(text: string): number {
177+
return Math.max(...text.split('\n').map(line => stringWidth(line)));
178+
}
179+
176180
function extractWords(text: string): string[] {
177181
return ansis
178182
.strip(text)
@@ -234,7 +238,7 @@ function getColumnTexts(table: NormalizedTable): string[][] {
234238

235239
function aggregateColumnsStats(columnTexts: string[][]): ColumnStats[] {
236240
return columnTexts.map(texts => {
237-
const widths = texts.map(text => stringWidth(text));
241+
const widths = texts.map(getTextWidth);
238242
const longestWords = texts
239243
.flatMap(extractWords)
240244
.toSorted((a, b) => b.length - a.length);

0 commit comments

Comments
 (0)