[READ-ONLY] Mirror of https://github.com/bombshell-dev/clack. Effortlessly build beautiful command-line apps bomb.sh/docs/clack/basics/getting-started/
cli command-line command-line-app node prompt prompts
5

Configure Feed

Select the types of activity you want to include in your feed.

fix(note,box): handle cjk correctly (#391)

authored by

Hyper-Z11 and committed by
GitHub
(Sep 8, 2025, 8:47 PM +0100) d25f6d03 2310b439

+379 -128
+5
.changeset/lucky-dragons-think.md
··· 1 + --- 2 + "@clack/prompts": patch 3 + --- 4 + 5 + fix(note, box): handle CJK correctly
+3 -2
packages/prompts/package.json
··· 58 58 "sisteransi": "^1.0.5" 59 59 }, 60 60 "devDependencies": { 61 + "fast-string-width": "^1.1.0", 62 + "fast-wrap-ansi": "^0.1.3", 61 63 "is-unicode-supported": "^1.3.0", 62 64 "memfs": "^4.17.2", 63 65 "vitest": "^3.2.4", 64 - "vitest-ansi-serializer": "^0.1.2", 65 - "fast-wrap-ansi": "^0.1.3" 66 + "vitest-ansi-serializer": "^0.1.2" 66 67 } 67 68 }
+10 -7
packages/prompts/src/box.ts
··· 14 14 S_CORNER_TOP_LEFT, 15 15 S_CORNER_TOP_RIGHT, 16 16 } from './common.js'; 17 + import stringWidth from "fast-string-width"; 17 18 18 19 export type BoxAlignment = 'left' | 'center' | 'right'; 19 20 ··· 72 73 const symbols = (opts?.rounded ? roundedSymbols : squareSymbols).map(formatBorder); 73 74 const hSymbol = formatBorder(S_BAR_H); 74 75 const vSymbol = formatBorder(S_BAR); 75 - const maxBoxWidth = columns - linePrefix.length; 76 - let boxWidth = Math.floor(columns * width) - linePrefix.length; 76 + const linePrefixWidth = stringWidth(linePrefix); 77 + const titleWidth = stringWidth(title); 78 + const maxBoxWidth = columns - linePrefixWidth; 79 + let boxWidth = Math.floor(columns * width) - linePrefixWidth; 77 80 if (opts?.width === 'auto') { 78 81 const lines = message.split('\n'); 79 - let longestLine = title.length + titlePadding * 2; 82 + let longestLine = titleWidth + titlePadding * 2; 80 83 for (const line of lines) { 81 - const lineWithPadding = line.length + contentPadding * 2; 84 + const lineWithPadding = stringWidth(line) + contentPadding * 2; 82 85 if (lineWithPadding > longestLine) { 83 86 longestLine = lineWithPadding; 84 87 } ··· 98 101 const innerWidth = boxWidth - borderTotalWidth; 99 102 const maxTitleLength = innerWidth - titlePadding * 2; 100 103 const truncatedTitle = 101 - title.length > maxTitleLength ? `${title.slice(0, maxTitleLength - 3)}...` : title; 104 + titleWidth > maxTitleLength ? `${title.slice(0, maxTitleLength - 3)}...` : title; 102 105 const [titlePaddingLeft, titlePaddingRight] = getPaddingForLine( 103 - truncatedTitle.length, 106 + stringWidth(truncatedTitle), 104 107 innerWidth, 105 108 titlePadding, 106 109 opts?.titleAlign ··· 115 118 const wrappedLines = wrappedMessage.split('\n'); 116 119 for (const line of wrappedLines) { 117 120 const [leftLinePadding, rightLinePadding] = getPaddingForLine( 118 - line.length, 121 + stringWidth(line), 119 122 innerWidth, 120 123 contentPadding, 121 124 opts?.contentAlign
+7 -7
packages/prompts/src/note.ts
··· 1 1 import process from 'node:process'; 2 2 import type { Writable } from 'node:stream'; 3 - import { stripVTControlCharacters as strip } from 'node:util'; 4 3 import { getColumns } from '@clack/core'; 5 4 import { type Options as WrapAnsiOptions, wrapAnsi } from 'fast-wrap-ansi'; 6 5 import color from 'picocolors'; ··· 13 12 S_CORNER_TOP_RIGHT, 14 13 S_STEP_SUBMIT, 15 14 } from './common.js'; 15 + import stringWidth from "fast-string-width"; 16 16 17 17 type FormatFn = (line: string) => string; 18 18 export interface NoteOptions extends CommonOptions { ··· 27 27 trim: false, 28 28 }; 29 29 const wrapMsg = wrapAnsi(message, width, opts).split('\n'); 30 - const maxWidthNormal = wrapMsg.reduce((sum, ln) => Math.max(strip(ln).length, sum), 0); 30 + const maxWidthNormal = wrapMsg.reduce((sum, ln) => Math.max(stringWidth(ln), sum), 0); 31 31 const maxWidthFormat = wrapMsg 32 32 .map(format) 33 - .reduce((sum, ln) => Math.max(strip(ln).length, sum), 0); 33 + .reduce((sum, ln) => Math.max(stringWidth(ln), sum), 0); 34 34 const wrapWidth = width - (maxWidthFormat - maxWidthNormal); 35 35 return wrapAnsi(message, wrapWidth, opts); 36 36 }; ··· 40 40 const format = opts?.format ?? defaultNoteFormatter; 41 41 const wrapMsg = wrapWithFormat(message, getColumns(output) - 6, format); 42 42 const lines = ['', ...wrapMsg.split('\n').map(format), '']; 43 - const titleLen = strip(title).length; 43 + const titleLen = stringWidth(title); 44 44 const len = 45 45 Math.max( 46 46 lines.reduce((sum, ln) => { 47 - const line = strip(ln); 48 - return line.length > sum ? line.length : sum; 47 + const width = stringWidth(ln); 48 + return width > sum ? width : sum; 49 49 }, 0), 50 50 titleLen 51 51 ) + 2; 52 52 const msg = lines 53 53 .map( 54 - (ln) => `${color.gray(S_BAR)} ${ln}${' '.repeat(len - strip(ln).length)}${color.gray(S_BAR)}` 54 + (ln) => `${color.gray(S_BAR)} ${ln}${' '.repeat(len - stringWidth(ln))}${color.gray(S_BAR)}` 55 55 ) 56 56 .join('\n'); 57 57 output.write(
+64
packages/prompts/test/__snapshots__/box.test.ts.snap
··· 191 191 ] 192 192 `; 193 193 194 + exports[`box (isCI = false) > renders wide characters with auto width 1`] = ` 195 + [ 196 + "┌─这是标题─────────────────┐ 197 + ", 198 + "│ 이게 첫 번째 줄이에요 │ 199 + ", 200 + "│ これは次の行です │ 201 + ", 202 + "└──────────────────────────┘ 203 + ", 204 + ] 205 + `; 206 + 207 + exports[`box (isCI = false) > renders wide characters with specified width 1`] = ` 208 + [ 209 + "┌─这是标题─────┐ 210 + ", 211 + "│ 이게 첫 │ 212 + ", 213 + "│ 번째 │ 214 + ", 215 + "│ 줄이에요 │ 216 + ", 217 + "│ これは次の │ 218 + ", 219 + "│ 行です │ 220 + ", 221 + "└──────────────┘ 222 + ", 223 + ] 224 + `; 225 + 194 226 exports[`box (isCI = false) > renders with formatBorder formatting 1`] = ` 195 227 [ 196 228 "┌─title──────┐ ··· 417 449 "┌─foofoofoo...─┐ 418 450 ", 419 451 "│ message │ 452 + ", 453 + "└──────────────┘ 454 + ", 455 + ] 456 + `; 457 + 458 + exports[`box (isCI = true) > renders wide characters with auto width 1`] = ` 459 + [ 460 + "┌─这是标题─────────────────┐ 461 + ", 462 + "│ 이게 첫 번째 줄이에요 │ 463 + ", 464 + "│ これは次の行です │ 465 + ", 466 + "└──────────────────────────┘ 467 + ", 468 + ] 469 + `; 470 + 471 + exports[`box (isCI = true) > renders wide characters with specified width 1`] = ` 472 + [ 473 + "┌─这是标题─────┐ 474 + ", 475 + "│ 이게 첫 │ 476 + ", 477 + "│ 번째 │ 478 + ", 479 + "│ 줄이에요 │ 480 + ", 481 + "│ これは次の │ 482 + ", 483 + "│ 行です │ 420 484 ", 421 485 "└──────────────┘ 422 486 ",
+228 -112
packages/prompts/test/__snapshots__/note.test.ts.snap
··· 3 3 exports[`note (isCI = false) > don't overflow 1`] = ` 4 4 [ 5 5 "│ 6 - ◇ title ────────────────────────────────────────────────────────────────────╮ 7 - │ │ 8 - │ test string test string test string test string test string test string  │ 9 - │ test string test string test string test string test string test string  │ 10 - │ test string test string test string test string test string test string  │ 11 - │ test string test string test string test string test string test string  │ 12 - │ test string test string test string test string test string test string  │ 13 - │ test string test string  │ 14 - │ test string test string test string test string test string test string  │ 15 - │ test string test string test string test string test string test string  │ 16 - │ test string test string test string test string test string test string  │ 17 - │ test string test string test string test string test string test string  │ 18 - │ test string test string test string test string test string test string  │ 19 - │ test string test string  │ 20 - │ test string test string test string test string test string test string  │ 21 - │ test string test string test string test string test string test string  │ 22 - │ test string test string test string test string test string test string  │ 23 - │ test string test string test string test string test string test string  │ 24 - │ test string test string test string test string test string test string  │ 25 - │ test string test string  │ 26 - │ test string test string test string test string test string test string  │ 27 - │ test string test string test string test string test string test string  │ 28 - │ test string test string test string test string test string test string  │ 29 - │ test string test string test string test string test string test string  │ 30 - │ test string test string test string test string test string test string  │ 31 - │ test string test string │ 32 - │ │ 33 - ├────────────────────────────────────────────────────────────────────────────╯ 6 + ◇ title ───────────────────────────────────────────────────────────────╮ 7 + │ │ 8 + │ test string test string test string test string test string test  │ 9 + │ string test string test string test string test string test string  │ 10 + │ test string test string test string test string test string test  │ 11 + │ string test string test string test string test string test string  │ 12 + │ test string test string test string test string test string test  │ 13 + │ string test string test string test string test string  │ 14 + │ test string test string test string test string test string test  │ 15 + │ string test string test string test string test string test string  │ 16 + │ test string test string test string test string test string test  │ 17 + │ string test string test string test string test string test string  │ 18 + │ test string test string test string test string test string test  │ 19 + │ string test string test string test string test string  │ 20 + │ test string test string test string test string test string test  │ 21 + │ string test string test string test string test string test string  │ 22 + │ test string test string test string test string test string test  │ 23 + │ string test string test string test string test string test string  │ 24 + │ test string test string test string test string test string test  │ 25 + │ string test string test string test string test string  │ 26 + │ test string test string test string test string test string test  │ 27 + │ string test string test string test string test string test string  │ 28 + │ test string test string test string test string test string test  │ 29 + │ string test string test string test string test string test string  │ 30 + │ test string test string test string test string test string test  │ 31 + │ string test string test string test string test string │ 32 + │ │ 33 + ├───────────────────────────────────────────────────────────────────────╯ 34 34 ", 35 35 ] 36 36 `; ··· 38 38 exports[`note (isCI = false) > don't overflow with formatter 1`] = ` 39 39 [ 40 40 "│ 41 - ◇ title ───────────────────────────────────────────────────────────────────╮ 42 - │ │ 43 - │ * test string test string test string test string test string test  * │ 44 - │ * string test string test string test string test string test string  * │ 45 - │ * test string test string test string test string test string test  * │ 46 - │ * string test string test string test string test string test string  * │ 47 - │ * test string test string test string test string test string test  * │ 48 - │ * string test string test string test string test string  * │ 49 - │ * test string test string test string test string test string test  * │ 50 - │ * string test string test string test string test string test string  * │ 51 - │ * test string test string test string test string test string test  * │ 52 - │ * string test string test string test string test string test string  * │ 53 - │ * test string test string test string test string test string test  * │ 54 - │ * string test string test string test string test string  * │ 55 - │ * test string test string test string test string test string test  * │ 56 - │ * string test string test string test string test string test string  * │ 57 - │ * test string test string test string test string test string test  * │ 58 - │ * string test string test string test string test string test string  * │ 59 - │ * test string test string test string test string test string test  * │ 60 - │ * string test string test string test string test string  * │ 61 - │ * test string test string test string test string test string test  * │ 62 - │ * string test string test string test string test string test string  * │ 63 - │ * test string test string test string test string test string test  * │ 64 - │ * string test string test string test string test string test string  * │ 65 - │ * test string test string test string test string test string test  * │ 66 - │ * string test string test string test string test string * │ 67 - │ │ 68 - ├───────────────────────────────────────────────────────────────────────────╯ 41 + ◇ title ─────────────────────────────────────────────────────────────────╮ 42 + │ │ 43 + │ * test string test string test string test string test string test  * │ 44 + │ * string test string test string test string test string test  * │ 45 + │ * string test string test string test string test string test  * │ 46 + │ * string test string test string test string test string test  * │ 47 + │ * string test string test string test string test string test  * │ 48 + │ * string test string test string test string test string test  * │ 49 + │ * string test string  * │ 50 + │ * test string test string test string test string test string test  * │ 51 + │ * string test string test string test string test string test  * │ 52 + │ * string test string test string test string test string test  * │ 53 + │ * string test string test string test string test string test  * │ 54 + │ * string test string test string test string test string test  * │ 55 + │ * string test string test string test string test string test  * │ 56 + │ * string test string  * │ 57 + │ * test string test string test string test string test string test  * │ 58 + │ * string test string test string test string test string test  * │ 59 + │ * string test string test string test string test string test  * │ 60 + │ * string test string test string test string test string test  * │ 61 + │ * string test string test string test string test string test  * │ 62 + │ * string test string test string test string test string test  * │ 63 + │ * string test string  * │ 64 + │ * test string test string test string test string test string test  * │ 65 + │ * string test string test string test string test string test  * │ 66 + │ * string test string test string test string test string test  * │ 67 + │ * string test string test string test string test string test  * │ 68 + │ * string test string test string test string test string test  * │ 69 + │ * string test string test string test string test string test  * │ 70 + │ * string test string * │ 71 + │ │ 72 + ├─────────────────────────────────────────────────────────────────────────╯ 69 73 ", 70 74 ] 71 75 `; ··· 94 98 │ * line 2 * │ 95 99 │ │ 96 100 ├──────────────╯ 101 + ", 102 + ] 103 + `; 104 + 105 + exports[`note (isCI = false) > handle wide characters 1`] = ` 106 + [ 107 + "│ 108 + ◇ 这是标题 ─╮ 109 + │ │ 110 + │ 이게 │ 111 + │  첫  │ 112 + │ 번째 │ 113 + │   │ 114 + │ 줄이 │ 115 + │ 에요 │ 116 + │ これ │ 117 + │ は次 │ 118 + │ の行 │ 119 + │ です │ 120 + │ │ 121 + ├────────────╯ 122 + ", 123 + ] 124 + `; 125 + 126 + exports[`note (isCI = false) > handle wide characters with formatter 1`] = ` 127 + [ 128 + "│ 129 + ◇ 这是标题 ─╮ 130 + │ │ 131 + │ *  * │ 132 + │ * 이 * │ 133 + │ * 게 * │ 134 + │ *   * │ 135 + │ * 첫 * │ 136 + │ *   * │ 137 + │ * 번 * │ 138 + │ * 째 * │ 139 + │ *   * │ 140 + │ * 줄 * │ 141 + │ * 이 * │ 142 + │ * 에 * │ 143 + │ * 요 * │ 144 + │ *  * │ 145 + │ * こ * │ 146 + │ * れ * │ 147 + │ * は * │ 148 + │ * 次 * │ 149 + │ * の * │ 150 + │ * 行 * │ 151 + │ * で * │ 152 + │ * す * │ 153 + │ │ 154 + ├────────────╯ 97 155 ", 98 156 ] 99 157 `; ··· 126 184 exports[`note (isCI = true) > don't overflow 1`] = ` 127 185 [ 128 186 "│ 129 - ◇ title ────────────────────────────────────────────────────────────────────╮ 130 - │ │ 131 - │ test string test string test string test string test string test string  │ 132 - │ test string test string test string test string test string test string  │ 133 - │ test string test string test string test string test string test string  │ 134 - │ test string test string test string test string test string test string  │ 135 - │ test string test string test string test string test string test string  │ 136 - │ test string test string  │ 137 - │ test string test string test string test string test string test string  │ 138 - │ test string test string test string test string test string test string  │ 139 - │ test string test string test string test string test string test string  │ 140 - │ test string test string test string test string test string test string  │ 141 - │ test string test string test string test string test string test string  │ 142 - │ test string test string  │ 143 - │ test string test string test string test string test string test string  │ 144 - │ test string test string test string test string test string test string  │ 145 - │ test string test string test string test string test string test string  │ 146 - │ test string test string test string test string test string test string  │ 147 - │ test string test string test string test string test string test string  │ 148 - │ test string test string  │ 149 - │ test string test string test string test string test string test string  │ 150 - │ test string test string test string test string test string test string  │ 151 - │ test string test string test string test string test string test string  │ 152 - │ test string test string test string test string test string test string  │ 153 - │ test string test string test string test string test string test string  │ 154 - │ test string test string │ 155 - │ │ 156 - ├────────────────────────────────────────────────────────────────────────────╯ 187 + ◇ title ───────────────────────────────────────────────────────────────╮ 188 + │ │ 189 + │ test string test string test string test string test string test  │ 190 + │ string test string test string test string test string test string  │ 191 + │ test string test string test string test string test string test  │ 192 + │ string test string test string test string test string test string  │ 193 + │ test string test string test string test string test string test  │ 194 + │ string test string test string test string test string  │ 195 + │ test string test string test string test string test string test  │ 196 + │ string test string test string test string test string test string  │ 197 + │ test string test string test string test string test string test  │ 198 + │ string test string test string test string test string test string  │ 199 + │ test string test string test string test string test string test  │ 200 + │ string test string test string test string test string  │ 201 + │ test string test string test string test string test string test  │ 202 + │ string test string test string test string test string test string  │ 203 + │ test string test string test string test string test string test  │ 204 + │ string test string test string test string test string test string  │ 205 + │ test string test string test string test string test string test  │ 206 + │ string test string test string test string test string  │ 207 + │ test string test string test string test string test string test  │ 208 + │ string test string test string test string test string test string  │ 209 + │ test string test string test string test string test string test  │ 210 + │ string test string test string test string test string test string  │ 211 + │ test string test string test string test string test string test  │ 212 + │ string test string test string test string test string │ 213 + │ │ 214 + ├───────────────────────────────────────────────────────────────────────╯ 157 215 ", 158 216 ] 159 217 `; ··· 161 219 exports[`note (isCI = true) > don't overflow with formatter 1`] = ` 162 220 [ 163 221 "│ 164 - ◇ title ───────────────────────────────────────────────────────────────────╮ 165 - │ │ 166 - │ * test string test string test string test string test string test  * │ 167 - │ * string test string test string test string test string test string  * │ 168 - │ * test string test string test string test string test string test  * │ 169 - │ * string test string test string test string test string test string  * │ 170 - │ * test string test string test string test string test string test  * │ 171 - │ * string test string test string test string test string  * │ 172 - │ * test string test string test string test string test string test  * │ 173 - │ * string test string test string test string test string test string  * │ 174 - │ * test string test string test string test string test string test  * │ 175 - │ * string test string test string test string test string test string  * │ 176 - │ * test string test string test string test string test string test  * │ 177 - │ * string test string test string test string test string  * │ 178 - │ * test string test string test string test string test string test  * │ 179 - │ * string test string test string test string test string test string  * │ 180 - │ * test string test string test string test string test string test  * │ 181 - │ * string test string test string test string test string test string  * │ 182 - │ * test string test string test string test string test string test  * │ 183 - │ * string test string test string test string test string  * │ 184 - │ * test string test string test string test string test string test  * │ 185 - │ * string test string test string test string test string test string  * │ 186 - │ * test string test string test string test string test string test  * │ 187 - │ * string test string test string test string test string test string  * │ 188 - │ * test string test string test string test string test string test  * │ 189 - │ * string test string test string test string test string * │ 190 - │ │ 191 - ├───────────────────────────────────────────────────────────────────────────╯ 222 + ◇ title ─────────────────────────────────────────────────────────────────╮ 223 + │ │ 224 + │ * test string test string test string test string test string test  * │ 225 + │ * string test string test string test string test string test  * │ 226 + │ * string test string test string test string test string test  * │ 227 + │ * string test string test string test string test string test  * │ 228 + │ * string test string test string test string test string test  * │ 229 + │ * string test string test string test string test string test  * │ 230 + │ * string test string  * │ 231 + │ * test string test string test string test string test string test  * │ 232 + │ * string test string test string test string test string test  * │ 233 + │ * string test string test string test string test string test  * │ 234 + │ * string test string test string test string test string test  * │ 235 + │ * string test string test string test string test string test  * │ 236 + │ * string test string test string test string test string test  * │ 237 + │ * string test string  * │ 238 + │ * test string test string test string test string test string test  * │ 239 + │ * string test string test string test string test string test  * │ 240 + │ * string test string test string test string test string test  * │ 241 + │ * string test string test string test string test string test  * │ 242 + │ * string test string test string test string test string test  * │ 243 + │ * string test string test string test string test string test  * │ 244 + │ * string test string  * │ 245 + │ * test string test string test string test string test string test  * │ 246 + │ * string test string test string test string test string test  * │ 247 + │ * string test string test string test string test string test  * │ 248 + │ * string test string test string test string test string test  * │ 249 + │ * string test string test string test string test string test  * │ 250 + │ * string test string test string test string test string test  * │ 251 + │ * string test string * │ 252 + │ │ 253 + ├─────────────────────────────────────────────────────────────────────────╯ 192 254 ", 193 255 ] 194 256 `; ··· 217 279 │ * line 2 * │ 218 280 │ │ 219 281 ├──────────────╯ 282 + ", 283 + ] 284 + `; 285 + 286 + exports[`note (isCI = true) > handle wide characters 1`] = ` 287 + [ 288 + "│ 289 + ◇ 这是标题 ─╮ 290 + │ │ 291 + │ 이게 │ 292 + │  첫  │ 293 + │ 번째 │ 294 + │   │ 295 + │ 줄이 │ 296 + │ 에요 │ 297 + │ これ │ 298 + │ は次 │ 299 + │ の行 │ 300 + │ です │ 301 + │ │ 302 + ├────────────╯ 303 + ", 304 + ] 305 + `; 306 + 307 + exports[`note (isCI = true) > handle wide characters with formatter 1`] = ` 308 + [ 309 + "│ 310 + ◇ 这是标题 ─╮ 311 + │ │ 312 + │ *  * │ 313 + │ * 이 * │ 314 + │ * 게 * │ 315 + │ *   * │ 316 + │ * 첫 * │ 317 + │ *   * │ 318 + │ * 번 * │ 319 + │ * 째 * │ 320 + │ *   * │ 321 + │ * 줄 * │ 322 + │ * 이 * │ 323 + │ * 에 * │ 324 + │ * 요 * │ 325 + │ *  * │ 326 + │ * こ * │ 327 + │ * れ * │ 328 + │ * は * │ 329 + │ * 次 * │ 330 + │ * の * │ 331 + │ * 行 * │ 332 + │ * で * │ 333 + │ * す * │ 334 + │ │ 335 + ├────────────╯ 220 336 ", 221 337 ] 222 338 `;
+28
packages/prompts/test/box.test.ts
··· 234 234 235 235 expect(output.buffer).toMatchSnapshot(); 236 236 }); 237 + 238 + test('renders wide characters with auto width', () => { 239 + const messages = [ 240 + '이게 첫 번째 줄이에요', 241 + 'これは次の行です', 242 + ]; 243 + prompts.box(messages.join("\n"), '这是标题', { 244 + input, 245 + output, 246 + width: 'auto', 247 + }); 248 + 249 + expect(output.buffer).toMatchSnapshot(); 250 + }); 251 + 252 + test('renders wide characters with specified width', () => { 253 + const messages = [ 254 + '이게 첫 번째 줄이에요', 255 + 'これは次の行です', 256 + ]; 257 + prompts.box(messages.join("\n"), '这是标题', { 258 + input, 259 + output, 260 + width: 0.2, 261 + }); 262 + 263 + expect(output.buffer).toMatchSnapshot(); 264 + }); 237 265 });
+31
packages/prompts/test/note.test.ts
··· 66 66 67 67 test("don't overflow", () => { 68 68 const message = `${'test string '.repeat(32)}\n`.repeat(4).trim(); 69 + output.columns = 75; 69 70 prompts.note(message, 'title', { 70 71 input, 71 72 output, ··· 76 77 77 78 test("don't overflow with formatter", () => { 78 79 const message = `${'test string '.repeat(32)}\n`.repeat(4).trim(); 80 + output.columns = 75; 79 81 prompts.note(message, 'title', { 82 + format: (line) => colors.red(`* ${colors.cyan(line)} *`), 83 + input, 84 + output, 85 + }); 86 + 87 + expect(output.buffer).toMatchSnapshot(); 88 + }); 89 + 90 + test("handle wide characters", () => { 91 + const messages = [ 92 + '이게 첫 번째 줄이에요', 93 + 'これは次の行です', 94 + ]; 95 + output.columns = 10; 96 + prompts.note(messages.join("\n"), '这是标题', { 97 + input, 98 + output, 99 + }); 100 + 101 + expect(output.buffer).toMatchSnapshot(); 102 + }); 103 + 104 + test("handle wide characters with formatter", () => { 105 + const messages = [ 106 + '이게 첫 번째 줄이에요', 107 + 'これは次の行です', 108 + ]; 109 + output.columns = 10; 110 + prompts.note(messages.join("\n"), '这是标题', { 80 111 format: (line) => colors.red(`* ${colors.cyan(line)} *`), 81 112 input, 82 113 output,
+3
pnpm-lock.yaml
··· 86 86 specifier: ^1.0.5 87 87 version: 1.0.5 88 88 devDependencies: 89 + fast-string-width: 90 + specifier: ^1.1.0 91 + version: 1.1.0 89 92 fast-wrap-ansi: 90 93 specifier: ^0.1.3 91 94 version: 0.1.3