diff --git a/packages/utils/src/lib/text-formats/ascii/link.ts b/packages/utils/src/lib/text-formats/ascii/link.ts index 1525fa5e2..93e727f22 100644 --- a/packages/utils/src/lib/text-formats/ascii/link.ts +++ b/packages/utils/src/lib/text-formats/ascii/link.ts @@ -1,5 +1,6 @@ import ansis from 'ansis'; export function formatAsciiLink(url: string): string { - return ansis.underline.blueBright(url); + // no underline because terminals recognize URLs, and nested ansis styles aren't handled by wrap-ansi + return ansis.blueBright(url); } diff --git a/packages/utils/src/lib/text-formats/ascii/table.ts b/packages/utils/src/lib/text-formats/ascii/table.ts index f8c888e7b..0efa9ee7e 100644 --- a/packages/utils/src/lib/text-formats/ascii/table.ts +++ b/packages/utils/src/lib/text-formats/ascii/table.ts @@ -158,6 +158,9 @@ function wrapText(text: string, width: number | undefined): string { if (!width || getTextWidth(text) <= width) { return text; } + if (text !== ansis.strip(text)) { + return wrapAnsi(text, width, { hard: true }); + } const words = extractWords(text); const longWords = words.filter(word => word.length > width); const replacements = longWords.map(original => { diff --git a/packages/utils/src/lib/text-formats/ascii/table.unit.test.ts b/packages/utils/src/lib/text-formats/ascii/table.unit.test.ts index 52bd6cc64..c330f5fec 100644 --- a/packages/utils/src/lib/text-formats/ascii/table.unit.test.ts +++ b/packages/utils/src/lib/text-formats/ascii/table.unit.test.ts @@ -453,6 +453,69 @@ Code coverage: ├──────────┼────────────┼─────────┼────────────┼──────────┼─────────┼──────────┤ │ 81 │ 64 │ 92 │ 100 │ 95 │ 62 │ 6 │ └──────────┴────────────┴─────────┴────────────┴──────────┴─────────┴──────────┘ +`.trim(), + ); + }); + + it('should wrap ansi styles correctly', () => { + const output = formatAsciiTable( + { + rows: [ + [''], + [ansis.bold('💡 Integrate the Portal')], + [''], + [`${ansis.gray('❯')} Configure upload in code-pushup.config.ts`], + [ + ansis.underline( + 'https://github.com/code-pushup/cli/blob/main/packages/cli/README.md#portal-integration', + ), + ], + [ + `${ansis.gray('❯')} npx code-pushup upload${ansis.gray(' - Upload previously collected report to the Portal')}`, + ], + [ + ansis.underline( + 'https://github.com/code-pushup/cli/tree/main/packages/cli#upload-command', + ), + ], + [''], + ], + }, + { padding: 4 }, + ); + + expect(ansis.strip(output)).toBe( + ` +┌──────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ 💡 Integrate the Portal │ +│ │ +│ ❯ Configure upload in code-pushup.config.ts │ +│ https://github.com/code-pushup/cli/blob/main/packages/cli/README.md#po │ +│ rtal-integration │ +│ ❯ npx code-pushup upload - Upload previously collected report to the │ +│ Portal │ +│ https://github.com/code-pushup/cli/tree/main/packages/cli#upload-comma │ +│ nd │ +│ │ +└──────────────────────────────────────────────────────────────────────────────┘ +`.trim(), + ); + expect(output).toBe( + ` +${ansis.dim('┌──────────────────────────────────────────────────────────────────────────────┐')} +${ansis.dim('│')} ${ansis.dim('│')} +${ansis.dim('│')} ${ansis.bold('💡 Integrate the Portal')} ${ansis.dim('│')} +${ansis.dim('│')} ${ansis.dim('│')} +${ansis.dim('│')} ${ansis.gray('❯')} Configure upload in code-pushup.config.ts ${ansis.dim('│')} +${ansis.dim('│')} ${ansis.underline('https://github.com/code-pushup/cli/blob/main/packages/cli/README.md#po')} ${ansis.dim('│')} +${ansis.dim('│')} ${ansis.underline('rtal-integration')} ${ansis.dim('│')} +${ansis.dim('│')} ${ansis.gray('❯')} npx code-pushup upload${ansis.gray(' - Upload previously collected report to the')} ${ansis.dim('│')} +${ansis.dim('│')} ${ansis.gray('Portal')} ${ansis.dim('│')} +${ansis.dim('│')} ${ansis.underline('https://github.com/code-pushup/cli/tree/main/packages/cli#upload-comma')} ${ansis.dim('│')} +${ansis.dim('│')} ${ansis.underline('nd')} ${ansis.dim('│')} +${ansis.dim('│')} ${ansis.dim('│')} +${ansis.dim('└──────────────────────────────────────────────────────────────────────────────┘')} `.trim(), ); });