@depup/boxen 8.0.1-depup.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # @depup/boxen
2
+
3
+ > Dependency-bumped version of [boxen](https://www.npmjs.com/package/boxen)
4
+
5
+ Generated by [DepUp](https://github.com/depup/npm) -- all production
6
+ dependencies bumped to latest versions.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install @depup/boxen
12
+ ```
13
+
14
+ | Field | Value |
15
+ |-------|-------|
16
+ | Original | [boxen](https://www.npmjs.com/package/boxen) @ 8.0.1 |
17
+ | Processed | 2026-03-09 |
18
+ | Smoke test | passed |
19
+ | Deps updated | 7 |
20
+
21
+ ## Dependency Changes
22
+
23
+ | Dependency | From | To |
24
+ |------------|------|-----|
25
+ | camelcase | ^8.0.0 | ^9.0.0 |
26
+ | chalk | ^5.3.0 | ^5.6.2 |
27
+ | cli-boxes | ^3.0.0 | ^4.0.1 |
28
+ | string-width | ^7.2.0 | ^8.2.0 |
29
+ | type-fest | ^4.21.0 | ^5.4.4 |
30
+ | widest-line | ^5.0.0 | ^6.0.0 |
31
+ | wrap-ansi | ^9.0.0 | ^10.0.0 |
32
+
33
+ ---
34
+
35
+ Source: https://github.com/depup/npm | Original: https://www.npmjs.com/package/boxen
36
+
37
+ License inherited from the original package.
package/index.d.ts ADDED
@@ -0,0 +1,267 @@
1
+ import {type LiteralUnion} from 'type-fest';
2
+ import {type BoxStyle, type Boxes as CLIBoxes} from 'cli-boxes';
3
+
4
+ /**
5
+ All box styles.
6
+ */
7
+ type Boxes = {
8
+ readonly none: BoxStyle;
9
+ } & CLIBoxes;
10
+
11
+ /**
12
+ Characters used for custom border.
13
+
14
+ @example
15
+ ```
16
+ // attttb
17
+ // l r
18
+ // dbbbbc
19
+
20
+ const border: CustomBorderStyle = {
21
+ topLeft: 'a',
22
+ topRight: 'b',
23
+ bottomRight: 'c',
24
+ bottomLeft: 'd',
25
+ left: 'l',
26
+ right: 'r',
27
+ top: 't',
28
+ bottom: 'b',
29
+ };
30
+ ```
31
+ */
32
+ export type CustomBorderStyle = {
33
+ /**
34
+ @deprecated Use `top` and `bottom` instead.
35
+ */
36
+ horizontal?: string;
37
+
38
+ /**
39
+ @deprecated Use `left` and `right` instead.
40
+ */
41
+ vertical?: string;
42
+ } & BoxStyle;
43
+
44
+ /**
45
+ Spacing used for `padding` and `margin`.
46
+ */
47
+ export type Spacing = {
48
+ readonly top?: number;
49
+ readonly right?: number;
50
+ readonly bottom?: number;
51
+ readonly left?: number;
52
+ };
53
+
54
+ export type Options = {
55
+ /**
56
+ Color of the box border.
57
+ */
58
+ readonly borderColor?: LiteralUnion<
59
+ | 'black'
60
+ | 'red'
61
+ | 'green'
62
+ | 'yellow'
63
+ | 'blue'
64
+ | 'magenta'
65
+ | 'cyan'
66
+ | 'white'
67
+ | 'gray'
68
+ | 'grey'
69
+ | 'blackBright'
70
+ | 'redBright'
71
+ | 'greenBright'
72
+ | 'yellowBright'
73
+ | 'blueBright'
74
+ | 'magentaBright'
75
+ | 'cyanBright'
76
+ | 'whiteBright',
77
+ string
78
+ >;
79
+
80
+ /**
81
+ Style of the box border.
82
+
83
+ @default 'single'
84
+ */
85
+ readonly borderStyle?: keyof Boxes | CustomBorderStyle;
86
+
87
+ /**
88
+ Reduce opacity of the border.
89
+
90
+ @default false
91
+ */
92
+ readonly dimBorder?: boolean;
93
+
94
+ /**
95
+ Space between the text and box border.
96
+
97
+ @default 0
98
+ */
99
+ readonly padding?: number | Spacing;
100
+
101
+ /**
102
+ Space around the box.
103
+
104
+ @default 0
105
+ */
106
+ readonly margin?: number | Spacing;
107
+
108
+ /**
109
+ Float the box on the available terminal screen space.
110
+
111
+ @default 'left'
112
+ */
113
+ readonly float?: 'left' | 'right' | 'center';
114
+
115
+ /**
116
+ Color of the background.
117
+ */
118
+ readonly backgroundColor?: LiteralUnion<
119
+ | 'black'
120
+ | 'red'
121
+ | 'green'
122
+ | 'yellow'
123
+ | 'blue'
124
+ | 'magenta'
125
+ | 'cyan'
126
+ | 'white'
127
+ | 'blackBright'
128
+ | 'redBright'
129
+ | 'greenBright'
130
+ | 'yellowBright'
131
+ | 'blueBright'
132
+ | 'magentaBright'
133
+ | 'cyanBright'
134
+ | 'whiteBright',
135
+ string
136
+ >;
137
+
138
+ /**
139
+ Align the text in the box based on the widest line.
140
+
141
+ @default 'left'
142
+ @deprecated Use `textAlignment` instead.
143
+ */
144
+ readonly align?: 'left' | 'right' | 'center';
145
+
146
+ /**
147
+ Align the text in the box based on the widest line.
148
+
149
+ @default 'left'
150
+ */
151
+ readonly textAlignment?: 'left' | 'right' | 'center';
152
+
153
+ /**
154
+ Display a title at the top of the box.
155
+ If needed, the box will horizontally expand to fit the title.
156
+
157
+ @example
158
+ ```
159
+ console.log(boxen('foo bar', {title: 'example'}));
160
+ // ┌ example ┐
161
+ // │foo bar │
162
+ // └─────────┘
163
+ ```
164
+ */
165
+ readonly title?: string;
166
+
167
+ /**
168
+ Align the title in the top bar.
169
+
170
+ @default 'left'
171
+
172
+ @example
173
+ ```
174
+ console.log(boxen('foo bar foo bar', {title: 'example', titleAlignment: 'center'}));
175
+ // ┌─── example ───┐
176
+ // │foo bar foo bar│
177
+ // └───────────────┘
178
+
179
+ console.log(boxen('foo bar foo bar', {title: 'example', titleAlignment: 'right'}));
180
+ // ┌────── example ┐
181
+ // │foo bar foo bar│
182
+ // └───────────────┘
183
+ ```
184
+ */
185
+ readonly titleAlignment?: 'left' | 'right' | 'center';
186
+
187
+ /**
188
+ Set a fixed width for the box.
189
+
190
+ __Note__: This disables terminal overflow handling and may cause the box to look broken if the user's terminal is not wide enough.
191
+
192
+ @example
193
+ ```
194
+ import boxen from 'boxen';
195
+
196
+ console.log(boxen('foo bar', {width: 15}));
197
+ // ┌─────────────┐
198
+ // │foo bar │
199
+ // └─────────────┘
200
+ ```
201
+ */
202
+ readonly width?: number;
203
+
204
+ /**
205
+ Set a fixed height for the box.
206
+
207
+ __Note__: This option will crop overflowing content.
208
+
209
+ @example
210
+ ```
211
+ import boxen from 'boxen';
212
+
213
+ console.log(boxen('foo bar', {height: 5}));
214
+ // ┌───────┐
215
+ // │foo bar│
216
+ // │ │
217
+ // │ │
218
+ // └───────┘
219
+ ```
220
+ */
221
+ readonly height?: number;
222
+
223
+ /**
224
+ __boolean__: Whether or not to fit all available space within the terminal.
225
+
226
+ __function__: Pass a callback function to control box dimensions.
227
+
228
+ @example
229
+ ```
230
+ import boxen from 'boxen';
231
+
232
+ console.log(boxen('foo bar', {
233
+ fullscreen: (width, height) => [width, height - 1],
234
+ }));
235
+ ```
236
+ */
237
+ readonly fullscreen?: boolean | ((width: number, height: number) => [width: number, height: number]);
238
+ };
239
+
240
+ /**
241
+ Creates a box in the terminal.
242
+
243
+ @param text - The text inside the box.
244
+ @returns The box.
245
+
246
+ @example
247
+ ```
248
+ import boxen from 'boxen';
249
+
250
+ console.log(boxen('unicorn', {padding: 1}));
251
+ // ┌─────────────┐
252
+ // │ │
253
+ // │ unicorn │
254
+ // │ │
255
+ // └─────────────┘
256
+
257
+ console.log(boxen('unicorn', {padding: 1, margin: 1, borderStyle: 'double'}));
258
+ //
259
+ // ╔═════════════╗
260
+ // ║ ║
261
+ // ║ unicorn ║
262
+ // ║ ║
263
+ // ╚═════════════╝
264
+ //
265
+ ```
266
+ */
267
+ export default function boxen(text: string, options?: Options): string;
package/index.js ADDED
@@ -0,0 +1,376 @@
1
+ import process from 'node:process';
2
+ import stringWidth from 'string-width';
3
+ import chalk from 'chalk';
4
+ import widestLine from 'widest-line';
5
+ import cliBoxes from 'cli-boxes';
6
+ import camelCase from 'camelcase';
7
+ import ansiAlign from 'ansi-align';
8
+ import wrapAnsi from 'wrap-ansi';
9
+
10
+ const NEWLINE = '\n';
11
+ const PAD = ' ';
12
+ const NONE = 'none';
13
+
14
+ const terminalColumns = () => {
15
+ const {env, stdout, stderr} = process;
16
+
17
+ if (stdout?.columns) {
18
+ return stdout.columns;
19
+ }
20
+
21
+ if (stderr?.columns) {
22
+ return stderr.columns;
23
+ }
24
+
25
+ if (env.COLUMNS) {
26
+ return Number.parseInt(env.COLUMNS, 10);
27
+ }
28
+
29
+ return 80;
30
+ };
31
+
32
+ const getObject = detail => typeof detail === 'number' ? {
33
+ top: detail,
34
+ right: detail * 3,
35
+ bottom: detail,
36
+ left: detail * 3,
37
+ } : {
38
+ top: 0,
39
+ right: 0,
40
+ bottom: 0,
41
+ left: 0,
42
+ ...detail,
43
+ };
44
+
45
+ const getBorderWidth = borderStyle => borderStyle === NONE ? 0 : 2;
46
+
47
+ const getBorderChars = borderStyle => {
48
+ const sides = [
49
+ 'topLeft',
50
+ 'topRight',
51
+ 'bottomRight',
52
+ 'bottomLeft',
53
+ 'left',
54
+ 'right',
55
+ 'top',
56
+ 'bottom',
57
+ ];
58
+
59
+ let characters;
60
+
61
+ // Create empty border style
62
+ if (borderStyle === NONE) {
63
+ borderStyle = {};
64
+ for (const side of sides) {
65
+ borderStyle[side] = '';
66
+ }
67
+ }
68
+
69
+ if (typeof borderStyle === 'string') {
70
+ characters = cliBoxes[borderStyle];
71
+
72
+ if (!characters) {
73
+ throw new TypeError(`Invalid border style: ${borderStyle}`);
74
+ }
75
+ } else {
76
+ // Ensure retro-compatibility
77
+ if (typeof borderStyle?.vertical === 'string') {
78
+ borderStyle.left = borderStyle.vertical;
79
+ borderStyle.right = borderStyle.vertical;
80
+ }
81
+
82
+ // Ensure retro-compatibility
83
+ if (typeof borderStyle?.horizontal === 'string') {
84
+ borderStyle.top = borderStyle.horizontal;
85
+ borderStyle.bottom = borderStyle.horizontal;
86
+ }
87
+
88
+ for (const side of sides) {
89
+ if (borderStyle[side] === null || typeof borderStyle[side] !== 'string') {
90
+ throw new TypeError(`Invalid border style: ${side}`);
91
+ }
92
+ }
93
+
94
+ characters = borderStyle;
95
+ }
96
+
97
+ return characters;
98
+ };
99
+
100
+ const makeTitle = (text, horizontal, alignment) => {
101
+ let title = '';
102
+
103
+ const textWidth = stringWidth(text);
104
+
105
+ switch (alignment) {
106
+ case 'left': {
107
+ title = text + horizontal.slice(textWidth);
108
+ break;
109
+ }
110
+
111
+ case 'right': {
112
+ title = horizontal.slice(textWidth) + text;
113
+ break;
114
+ }
115
+
116
+ default: {
117
+ horizontal = horizontal.slice(textWidth);
118
+
119
+ if (horizontal.length % 2 === 1) { // This is needed in case the length is odd
120
+ horizontal = horizontal.slice(Math.floor(horizontal.length / 2));
121
+ title = horizontal.slice(1) + text + horizontal; // We reduce the left part of one character to avoid the bar to go beyond its limit
122
+ } else {
123
+ horizontal = horizontal.slice(horizontal.length / 2);
124
+ title = horizontal + text + horizontal;
125
+ }
126
+
127
+ break;
128
+ }
129
+ }
130
+
131
+ return title;
132
+ };
133
+
134
+ const makeContentText = (text, {padding, width, textAlignment, height}) => {
135
+ text = ansiAlign(text, {align: textAlignment});
136
+ let lines = text.split(NEWLINE);
137
+ const textWidth = widestLine(text);
138
+
139
+ const max = width - padding.left - padding.right;
140
+
141
+ if (textWidth > max) {
142
+ const newLines = [];
143
+ for (const line of lines) {
144
+ const createdLines = wrapAnsi(line, max, {hard: true});
145
+ const alignedLines = ansiAlign(createdLines, {align: textAlignment});
146
+ const alignedLinesArray = alignedLines.split('\n');
147
+ const longestLength = Math.max(...alignedLinesArray.map(s => stringWidth(s)));
148
+
149
+ for (const alignedLine of alignedLinesArray) {
150
+ let paddedLine;
151
+ switch (textAlignment) {
152
+ case 'center': {
153
+ paddedLine = PAD.repeat((max - longestLength) / 2) + alignedLine;
154
+ break;
155
+ }
156
+
157
+ case 'right': {
158
+ paddedLine = PAD.repeat(max - longestLength) + alignedLine;
159
+ break;
160
+ }
161
+
162
+ default: {
163
+ paddedLine = alignedLine;
164
+ break;
165
+ }
166
+ }
167
+
168
+ newLines.push(paddedLine);
169
+ }
170
+ }
171
+
172
+ lines = newLines;
173
+ }
174
+
175
+ if (textAlignment === 'center' && textWidth < max) {
176
+ lines = lines.map(line => PAD.repeat((max - textWidth) / 2) + line);
177
+ } else if (textAlignment === 'right' && textWidth < max) {
178
+ lines = lines.map(line => PAD.repeat(max - textWidth) + line);
179
+ }
180
+
181
+ const paddingLeft = PAD.repeat(padding.left);
182
+ const paddingRight = PAD.repeat(padding.right);
183
+
184
+ lines = lines.map(line => {
185
+ const newLine = paddingLeft + line + paddingRight;
186
+
187
+ return newLine + PAD.repeat(width - stringWidth(newLine));
188
+ });
189
+
190
+ if (padding.top > 0) {
191
+ lines = [...Array.from({length: padding.top}).fill(PAD.repeat(width)), ...lines];
192
+ }
193
+
194
+ if (padding.bottom > 0) {
195
+ lines = [...lines, ...Array.from({length: padding.bottom}).fill(PAD.repeat(width))];
196
+ }
197
+
198
+ if (height && lines.length > height) {
199
+ lines = lines.slice(0, height);
200
+ } else if (height && lines.length < height) {
201
+ lines = [...lines, ...Array.from({length: height - lines.length}).fill(PAD.repeat(width))];
202
+ }
203
+
204
+ return lines.join(NEWLINE);
205
+ };
206
+
207
+ const boxContent = (content, contentWidth, options) => {
208
+ const colorizeBorder = border => {
209
+ const newBorder = options.borderColor ? getColorFunction(options.borderColor)(border) : border;
210
+ return options.dimBorder ? chalk.dim(newBorder) : newBorder;
211
+ };
212
+
213
+ const colorizeContent = content => options.backgroundColor ? getBGColorFunction(options.backgroundColor)(content) : content;
214
+
215
+ const chars = getBorderChars(options.borderStyle);
216
+ const columns = terminalColumns();
217
+ let marginLeft = PAD.repeat(options.margin.left);
218
+
219
+ if (options.float === 'center') {
220
+ const marginWidth = Math.max((columns - contentWidth - getBorderWidth(options.borderStyle)) / 2, 0);
221
+ marginLeft = PAD.repeat(marginWidth);
222
+ } else if (options.float === 'right') {
223
+ const marginWidth = Math.max(columns - contentWidth - options.margin.right - getBorderWidth(options.borderStyle), 0);
224
+ marginLeft = PAD.repeat(marginWidth);
225
+ }
226
+
227
+ let result = '';
228
+
229
+ if (options.margin.top) {
230
+ result += NEWLINE.repeat(options.margin.top);
231
+ }
232
+
233
+ if (options.borderStyle !== NONE || options.title) {
234
+ result += colorizeBorder(marginLeft + chars.topLeft + (options.title ? makeTitle(options.title, chars.top.repeat(contentWidth), options.titleAlignment) : chars.top.repeat(contentWidth)) + chars.topRight) + NEWLINE;
235
+ }
236
+
237
+ const lines = content.split(NEWLINE);
238
+
239
+ result += lines.map(line => marginLeft + colorizeBorder(chars.left) + colorizeContent(line) + colorizeBorder(chars.right)).join(NEWLINE);
240
+
241
+ if (options.borderStyle !== NONE) {
242
+ result += NEWLINE + colorizeBorder(marginLeft + chars.bottomLeft + chars.bottom.repeat(contentWidth) + chars.bottomRight);
243
+ }
244
+
245
+ if (options.margin.bottom) {
246
+ result += NEWLINE.repeat(options.margin.bottom);
247
+ }
248
+
249
+ return result;
250
+ };
251
+
252
+ const sanitizeOptions = options => {
253
+ // If fullscreen is enabled, max-out unspecified width/height
254
+ if (options.fullscreen && process?.stdout) {
255
+ let newDimensions = [process.stdout.columns, process.stdout.rows];
256
+
257
+ if (typeof options.fullscreen === 'function') {
258
+ newDimensions = options.fullscreen(...newDimensions);
259
+ }
260
+
261
+ options.width ||= newDimensions[0];
262
+
263
+ options.height ||= newDimensions[1];
264
+ }
265
+
266
+ // If width is provided, make sure it's not below 1
267
+ options.width &&= Math.max(1, options.width - getBorderWidth(options.borderStyle));
268
+
269
+ // If height is provided, make sure it's not below 1
270
+ options.height &&= Math.max(1, options.height - getBorderWidth(options.borderStyle));
271
+
272
+ return options;
273
+ };
274
+
275
+ const formatTitle = (title, borderStyle) => borderStyle === NONE ? title : ` ${title} `;
276
+
277
+ const determineDimensions = (text, options) => {
278
+ options = sanitizeOptions(options);
279
+ const widthOverride = options.width !== undefined;
280
+ const columns = terminalColumns();
281
+ const borderWidth = getBorderWidth(options.borderStyle);
282
+ const maxWidth = columns - options.margin.left - options.margin.right - borderWidth;
283
+
284
+ const widest = widestLine(wrapAnsi(text, columns - borderWidth, {hard: true, trim: false})) + options.padding.left + options.padding.right;
285
+
286
+ // If title and width are provided, title adheres to fixed width
287
+ if (options.title && widthOverride) {
288
+ options.title = options.title.slice(0, Math.max(0, options.width - 2));
289
+ options.title &&= formatTitle(options.title, options.borderStyle);
290
+ } else if (options.title) {
291
+ options.title = options.title.slice(0, Math.max(0, maxWidth - 2));
292
+
293
+ // Recheck if title isn't empty now
294
+ if (options.title) {
295
+ options.title = formatTitle(options.title, options.borderStyle);
296
+ // If the title is larger than content, box adheres to title width
297
+ if (stringWidth(options.title) > widest) {
298
+ options.width = stringWidth(options.title);
299
+ }
300
+ }
301
+ }
302
+
303
+ // If fixed width is provided, use it or content width as reference
304
+ options.width ||= widest;
305
+
306
+ if (!widthOverride) {
307
+ if ((options.margin.left && options.margin.right) && options.width > maxWidth) {
308
+ // Let's assume we have margins: left = 3, right = 5, in total = 8
309
+ const spaceForMargins = columns - options.width - borderWidth;
310
+ // Let's assume we have space = 4
311
+ const multiplier = spaceForMargins / (options.margin.left + options.margin.right);
312
+ // Here: multiplier = 4/8 = 0.5
313
+ options.margin.left = Math.max(0, Math.floor(options.margin.left * multiplier));
314
+ options.margin.right = Math.max(0, Math.floor(options.margin.right * multiplier));
315
+ // Left: 3 * 0.5 = 1.5 -> 1
316
+ // Right: 6 * 0.5 = 3
317
+ }
318
+
319
+ // Re-cap width considering the margins after shrinking
320
+ options.width = Math.min(options.width, columns - borderWidth - options.margin.left - options.margin.right);
321
+ }
322
+
323
+ // Prevent padding overflow
324
+ if (options.width - (options.padding.left + options.padding.right) <= 0) {
325
+ options.padding.left = 0;
326
+ options.padding.right = 0;
327
+ }
328
+
329
+ if (options.height && options.height - (options.padding.top + options.padding.bottom) <= 0) {
330
+ options.padding.top = 0;
331
+ options.padding.bottom = 0;
332
+ }
333
+
334
+ return options;
335
+ };
336
+
337
+ const isHex = color => color.match(/^#(?:[0-f]{3}){1,2}$/i);
338
+ const isColorValid = color => typeof color === 'string' && (chalk[color] ?? isHex(color));
339
+ const getColorFunction = color => isHex(color) ? chalk.hex(color) : chalk[color];
340
+ const getBGColorFunction = color => isHex(color) ? chalk.bgHex(color) : chalk[camelCase(['bg', color])];
341
+
342
+ export default function boxen(text, options) {
343
+ options = {
344
+ padding: 0,
345
+ borderStyle: 'single',
346
+ dimBorder: false,
347
+ textAlignment: 'left',
348
+ float: 'left',
349
+ titleAlignment: 'left',
350
+ ...options,
351
+ };
352
+
353
+ // This option is deprecated
354
+ if (options.align) {
355
+ options.textAlignment = options.align;
356
+ }
357
+
358
+ if (options.borderColor && !isColorValid(options.borderColor)) {
359
+ throw new Error(`${options.borderColor} is not a valid borderColor`);
360
+ }
361
+
362
+ if (options.backgroundColor && !isColorValid(options.backgroundColor)) {
363
+ throw new Error(`${options.backgroundColor} is not a valid backgroundColor`);
364
+ }
365
+
366
+ options.padding = getObject(options.padding);
367
+ options.margin = getObject(options.margin);
368
+
369
+ options = determineDimensions(text, options);
370
+
371
+ text = makeContentText(text, options);
372
+
373
+ return boxContent(text, options.width, options);
374
+ }
375
+
376
+ export {default as _borderStyles} from 'cli-boxes';
package/license ADDED
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/package.json ADDED
@@ -0,0 +1,110 @@
1
+ {
2
+ "name": "@depup/boxen",
3
+ "version": "8.0.1-depup.0",
4
+ "description": "[DepUp] Create boxes in the terminal",
5
+ "license": "MIT",
6
+ "repository": "sindresorhus/boxen",
7
+ "funding": "https://github.com/sponsors/sindresorhus",
8
+ "author": {
9
+ "name": "Sindre Sorhus",
10
+ "email": "sindresorhus@gmail.com",
11
+ "url": "https://sindresorhus.com"
12
+ },
13
+ "type": "module",
14
+ "exports": {
15
+ "types": "./index.d.ts",
16
+ "default": "./index.js"
17
+ },
18
+ "sideEffects": false,
19
+ "engines": {
20
+ "node": ">=18"
21
+ },
22
+ "scripts": {
23
+ "test": "xo && nyc ava && tsd"
24
+ },
25
+ "files": [
26
+ "index.js",
27
+ "index.d.ts"
28
+ ],
29
+ "keywords": [
30
+ "depup",
31
+ "dependency-bumped",
32
+ "updated-deps",
33
+ "boxen",
34
+ "cli",
35
+ "box",
36
+ "boxes",
37
+ "terminal",
38
+ "term",
39
+ "console",
40
+ "ascii",
41
+ "unicode",
42
+ "border",
43
+ "text"
44
+ ],
45
+ "dependencies": {
46
+ "ansi-align": "^3.0.1",
47
+ "camelcase": "^9.0.0",
48
+ "chalk": "^5.6.2",
49
+ "cli-boxes": "^4.0.1",
50
+ "string-width": "^8.2.0",
51
+ "type-fest": "^5.4.4",
52
+ "widest-line": "^6.0.0",
53
+ "wrap-ansi": "^10.0.0"
54
+ },
55
+ "devDependencies": {
56
+ "ava": "^6.1.3",
57
+ "nyc": "^17.0.0",
58
+ "tsd": "^0.31.1",
59
+ "xo": "^0.58.0"
60
+ },
61
+ "ava": {
62
+ "snapshotDir": "tests/snapshots",
63
+ "environmentVariables": {
64
+ "COLUMNS": "60",
65
+ "FORCE_COLOR": "0"
66
+ }
67
+ },
68
+ "xo": {
69
+ "rules": {
70
+ "@typescript-eslint/no-unsafe-assignment": "off"
71
+ }
72
+ },
73
+ "depup": {
74
+ "changes": {
75
+ "camelcase": {
76
+ "from": "^8.0.0",
77
+ "to": "^9.0.0"
78
+ },
79
+ "chalk": {
80
+ "from": "^5.3.0",
81
+ "to": "^5.6.2"
82
+ },
83
+ "cli-boxes": {
84
+ "from": "^3.0.0",
85
+ "to": "^4.0.1"
86
+ },
87
+ "string-width": {
88
+ "from": "^7.2.0",
89
+ "to": "^8.2.0"
90
+ },
91
+ "type-fest": {
92
+ "from": "^4.21.0",
93
+ "to": "^5.4.4"
94
+ },
95
+ "widest-line": {
96
+ "from": "^5.0.0",
97
+ "to": "^6.0.0"
98
+ },
99
+ "wrap-ansi": {
100
+ "from": "^9.0.0",
101
+ "to": "^10.0.0"
102
+ }
103
+ },
104
+ "depsUpdated": 7,
105
+ "originalPackage": "boxen",
106
+ "originalVersion": "8.0.1",
107
+ "processedAt": "2026-03-09T04:41:35.446Z",
108
+ "smokeTest": "passed"
109
+ }
110
+ }
package/readme.md ADDED
@@ -0,0 +1,300 @@
1
+ # boxen
2
+
3
+ > Create boxes in the terminal
4
+
5
+ ![](screenshot.png)
6
+
7
+ ## Install
8
+
9
+ ```sh
10
+ npm install boxen
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```js
16
+ import boxen from 'boxen';
17
+
18
+ console.log(boxen('unicorn', {padding: 1}));
19
+ /*
20
+ ┌─────────────┐
21
+ │ │
22
+ │ unicorn │
23
+ │ │
24
+ └─────────────┘
25
+ */
26
+
27
+ console.log(boxen('unicorn', {padding: 1, margin: 1, borderStyle: 'double'}));
28
+ /*
29
+
30
+ ╔═════════════╗
31
+ ║ ║
32
+ ║ unicorn ║
33
+ ║ ║
34
+ ╚═════════════╝
35
+
36
+ */
37
+
38
+ console.log(boxen('unicorns love rainbows', {title: 'magical', titleAlignment: 'center'}));
39
+ /*
40
+ ┌────── magical ───────┐
41
+ │unicorns love rainbows│
42
+ └──────────────────────┘
43
+ */
44
+ ```
45
+
46
+ ## API
47
+
48
+ ### boxen(text, options?)
49
+
50
+ #### text
51
+
52
+ Type: `string`
53
+
54
+ Text inside the box.
55
+
56
+ #### options
57
+
58
+ Type: `object`
59
+
60
+ ##### borderColor
61
+
62
+ Type: `string`\
63
+ Values: `'black'` `'red'` `'green'` `'yellow'` `'blue'` `'magenta'` `'cyan'` `'white'` `'gray'` or a hex value like `'#ff0000'`
64
+
65
+ Color of the box border.
66
+
67
+ ##### borderStyle
68
+
69
+ Type: `string | object`\
70
+ Default: `'single'`\
71
+ Values:
72
+ - `'single'`
73
+ ```
74
+ ┌───┐
75
+ │foo│
76
+ └───┘
77
+ ```
78
+ - `'double'`
79
+ ```
80
+ ╔═══╗
81
+ ║foo║
82
+ ╚═══╝
83
+ ```
84
+ - `'round'` (`'single'` sides with round corners)
85
+ ```
86
+ ╭───╮
87
+ │foo│
88
+ ╰───╯
89
+ ```
90
+ - `'bold'`
91
+ ```
92
+ ┏━━━┓
93
+ ┃foo┃
94
+ ┗━━━┛
95
+ ```
96
+ - `'singleDouble'` (`'single'` on top and bottom, `'double'` on right and left)
97
+ ```
98
+ ╓───╖
99
+ ║foo║
100
+ ╙───╜
101
+ ```
102
+ - `'doubleSingle'` (`'double'` on top and bottom, `'single'` on right and left)
103
+ ```
104
+ ╒═══╕
105
+ │foo│
106
+ ╘═══╛
107
+ ```
108
+ - `'classic'`
109
+ ```
110
+ +---+
111
+ |foo|
112
+ +---+
113
+ ```
114
+ - `'arrow'`
115
+ ```
116
+ ↘↓↓↓↙
117
+ →foo←
118
+ ↗↑↑↑↖
119
+ ```
120
+ - `'none'`
121
+ ```
122
+ foo
123
+ ```
124
+
125
+ Style of the box border.
126
+
127
+ Can be any of the above predefined styles or an object with the following keys:
128
+
129
+ ```js
130
+ {
131
+ topLeft: '+',
132
+ topRight: '+',
133
+ bottomLeft: '+',
134
+ bottomRight: '+',
135
+ top: '-',
136
+ bottom: '-',
137
+ left: '|',
138
+ right: '|'
139
+ }
140
+ ```
141
+
142
+ ##### dimBorder
143
+
144
+ Type: `boolean`\
145
+ Default: `false`
146
+
147
+ Reduce opacity of the border.
148
+
149
+ ##### title
150
+
151
+ Type: `string`
152
+
153
+ Display a title at the top of the box.
154
+ If needed, the box will horizontally expand to fit the title.
155
+
156
+ Example:
157
+ ```js
158
+ console.log(boxen('foo bar', {title: 'example'}));
159
+ /*
160
+ ┌ example ┐
161
+ │foo bar │
162
+ └─────────┘
163
+ */
164
+ ```
165
+
166
+ ##### titleAlignment
167
+
168
+ Type: `string`\
169
+ Default: `'left'`
170
+
171
+ Align the title in the top bar.
172
+
173
+ Values:
174
+ - `'left'`
175
+ ```js
176
+ /*
177
+ ┌ example ──────┐
178
+ │foo bar foo bar│
179
+ └───────────────┘
180
+ */
181
+ ```
182
+ - `'center'`
183
+ ```js
184
+ /*
185
+ ┌─── example ───┐
186
+ │foo bar foo bar│
187
+ └───────────────┘
188
+ */
189
+ ```
190
+ - `'right'`
191
+ ```js
192
+ /*
193
+ ┌────── example ┐
194
+ │foo bar foo bar│
195
+ └───────────────┘
196
+ */
197
+ ```
198
+
199
+ ##### width
200
+
201
+ Type: `number`
202
+
203
+ Set a fixed width for the box.
204
+
205
+ *Note:* This disables terminal overflow handling and may cause the box to look broken if the user's terminal is not wide enough.
206
+
207
+ ```js
208
+ import boxen from 'boxen';
209
+
210
+ console.log(boxen('foo bar', {width: 15}));
211
+ // ┌─────────────┐
212
+ // │foo bar │
213
+ // └─────────────┘
214
+ ```
215
+
216
+ ##### height
217
+
218
+ Type: `number`
219
+
220
+ Set a fixed height for the box.
221
+
222
+ *Note:* This option will crop overflowing content.
223
+
224
+ ```js
225
+ import boxen from 'boxen';
226
+
227
+ console.log(boxen('foo bar', {height: 5}));
228
+ // ┌───────┐
229
+ // │foo bar│
230
+ // │ │
231
+ // │ │
232
+ // └───────┘
233
+ ```
234
+
235
+ ##### fullscreen
236
+
237
+ Type: `boolean | (width: number, height: number) => [width: number, height: number]`
238
+
239
+ Whether or not to fit all available space within the terminal.
240
+
241
+ Pass a callback function to control box dimensions:
242
+
243
+ ```js
244
+ import boxen from 'boxen';
245
+
246
+ console.log(boxen('foo bar', {
247
+ fullscreen: (width, height) => [width, height - 1],
248
+ }));
249
+ ```
250
+
251
+ ##### padding
252
+
253
+ Type: `number | object`\
254
+ Default: `0`
255
+
256
+ Space between the text and box border.
257
+
258
+ Accepts a number or an object with any of the `top`, `right`, `bottom`, `left` properties. When a number is specified, the left/right padding is 3 times the top/bottom to make it look nice.
259
+
260
+ ##### margin
261
+
262
+ Type: `number | object`\
263
+ Default: `0`
264
+
265
+ Space around the box.
266
+
267
+ Accepts a number or an object with any of the `top`, `right`, `bottom`, `left` properties. When a number is specified, the left/right margin is 3 times the top/bottom to make it look nice.
268
+
269
+ ##### float
270
+
271
+ Type: `string`\
272
+ Default: `'left'`\
273
+ Values: `'right'` `'center'` `'left'`
274
+
275
+ Float the box on the available terminal screen space.
276
+
277
+ ##### backgroundColor
278
+
279
+ Type: `string`\
280
+ Values: `'black'` `'red'` `'green'` `'yellow'` `'blue'` `'magenta'` `'cyan'` `'white'` `'gray'` or a hex value like `'#ff0000'`
281
+
282
+ Color of the background.
283
+
284
+ ##### textAlignment
285
+
286
+ Type: `string`\
287
+ Default: `'left'`\
288
+ Values: `'left'` `'center'` `'right'`
289
+
290
+ Align the text in the box based on the widest line.
291
+
292
+ ## Maintainer
293
+
294
+ - [Sindre Sorhus](https://github.com/sindresorhus)
295
+ - [Caesarovich](https://github.com/Caesarovich)
296
+
297
+ ## Related
298
+
299
+ - [boxen-cli](https://github.com/sindresorhus/boxen-cli) - CLI for this module
300
+ - [cli-boxes](https://github.com/sindresorhus/cli-boxes) - Boxes for use in the terminal