Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add title and titleAlignment options #59

Merged
merged 24 commits into from
Sep 11, 2021
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
65f9cfd
Refactored the code into sub-functions
Caesarovich Aug 27, 2021
a19c2bd
Fix margin error shrink on specific cases
Caesarovich Aug 30, 2021
6da1b52
Remove outdated tests that aren't relevant anymore
Caesarovich Aug 30, 2021
39693c0
Code reduction
Caesarovich Sep 6, 2021
cf55cc3
Reforming corretly last commit
Caesarovich Sep 6, 2021
b93b3cc
Fix margin shrink error on negative values
Caesarovich Sep 6, 2021
e750e40
Added tests for box overflows
Caesarovich Sep 6, 2021
c3c1335
Re-adapted unit tests
Caesarovich Sep 6, 2021
64ff8c5
Added title feature with tests
Caesarovich Sep 6, 2021
51ef182
Improved code readability
Caesarovich Sep 6, 2021
0f53317
Merge branch 'sindresorhus:main' into main
Caesarovich Sep 6, 2021
363bdb0
Added title feature with tests
Caesarovich Sep 6, 2021
5402523
Cleaning left-overs
Caesarovich Sep 6, 2021
0dcdcc4
Merge branch 'feature-title' of https://github.com/Caesarovich/boxen …
Caesarovich Sep 6, 2021
f0eeb05
Update index.d.ts
Caesarovich Sep 7, 2021
01fba09
Document box enlargement
Caesarovich Sep 7, 2021
2027380
Place the constant variables back on top
Caesarovich Sep 7, 2021
fe8e663
Documented the new functionnalities
Caesarovich Sep 7, 2021
969a78f
Corrected documentations
Caesarovich Sep 9, 2021
d72cac4
Replace titleAlign by titleAlignement
Caesarovich Sep 9, 2021
82921d6
Change align to textAlignement
Caesarovich Sep 9, 2021
31923c6
Deprecate the align option
Caesarovich Sep 9, 2021
0650ba1
Fix 'alignment' typo
Caesarovich Sep 11, 2021
e7b88c7
Sync readme and index.d.ts
Caesarovich Sep 11, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions example.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,16 @@ console.log('\n\n' + boxen(chalk.black('unicorn'), {
}) + '\n');

const sentences = 'Unbreakable_text_because_it_has_no_spaces '.repeat(5);
console.log('\n\n' + boxen(sentences, {align: 'left'}) + '\n');
console.log('\n\n' + boxen(sentences, {textAlignement: 'left'}) + '\n');

console.log('\n\n' + boxen(sentences, {align: 'center'}) + '\n');
console.log('\n\n' + boxen(sentences, {textAlignement: 'center'}) + '\n');

console.log('\n\n' + boxen(sentences, {align: 'right', padding: {left: 1, right: 1, top: 0, bottom: 0}}) + '\n');
console.log('\n\n' + boxen(sentences, {textAlignement: 'right', padding: {left: 1, right: 1, top: 0, bottom: 0}}) + '\n');

const longWord = 'x'.repeat(process.stdout.columns + 20);
console.log('\n\n' + boxen(longWord, {align: 'center'}) + '\n');
console.log('\n\n' + boxen(longWord, {textAlignement: 'center'}) + '\n');

const title = 'Beautiful title';
console.log('\n\n' + boxen('This box has a nice title', {title}) + '\n');

console.log('\n\n' + boxen('This box has a centered title', {title, titleAlignement: 'center'}) + '\n');
42 changes: 42 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,50 @@ declare namespace boxen {
Align the text in the box based on the widest line.

@default 'left'
@deprecated Use `textAlignement` instead.
*/
readonly align?: 'left' | 'right' | 'center';

/**
Align the text in the box based on the widest line.

@default 'left'
*/
readonly textAlignement?: 'left' | 'right' | 'center';

/**
Display a title on the top of the box.
If needed, the box will horizontally expand to fit the title.

@example
```
console.log(boxen('foo bar foo bar', {title: 'title'}));
// ┌ title ────────┐
// │foo bar foo bar│
// └───────────────┘
```
*/
readonly title?: string;

/**
Align the title in the top bar.

@default 'left'

@example
```
console.log(boxen('foo bar foo bar', {title: 'example', textAlignementTitle: 'center'}));
// ┌─── example ───┐
// │foo bar foo bar│
// └───────────────┘

console.log(boxen('foo bar foo bar', {title: 'example', textAlignementTitle: 'right'}));
// ┌────── example ┐
// │foo bar foo bar│
// └───────────────┘
```
*/
readonly titleAlignement?: 'left' | 'right' | 'center';
}
}

Expand Down
56 changes: 52 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const wrapAnsi = require('wrap-ansi');

const NL = '\n';
const PAD = ' ';
const BORDERS_WIDTH = 2;

const terminalColumns = () => {
const {env, stdout, stderr} = process;
Expand Down Expand Up @@ -75,6 +74,35 @@ const getBorderChars = borderStyle => {
return chararacters;
};

const makeTitle = (text, horizontal, alignement) => {
let title = '';

const textWidth = stringWidth(text);

switch (alignement) {
case 'left':
title = text + horizontal.slice(textWidth);
break;
case 'right':
title = horizontal.slice(textWidth) + text;
break;
default:
horizontal = horizontal.slice(textWidth);

if (horizontal.length % 2 === 1) { // This is needed in case the length is odd
horizontal = horizontal.slice(Math.floor(horizontal.length / 2));
title = horizontal.slice(1) + text + horizontal; // We reduce the left part of one character to avoid the bar to go beyond its limit
} else {
horizontal = horizontal.slice(horizontal.length / 2);
title = horizontal + text + horizontal;
}

break;
}

return title;
};

const makeContentText = (text, padding, columns, align) => {
text = ansiAlign(text, {align});
let lines = text.split(NL);
Expand Down Expand Up @@ -158,11 +186,19 @@ module.exports = (text, options) => {
padding: 0,
borderStyle: 'single',
dimBorder: false,
align: 'left',
textAlignement: 'left',
float: 'left',
titleAlignement: 'left',
...options
};

// This option is deprecated
if (options.align) {
options.textAlignement = options.align;
}

const BORDERS_WIDTH = 2;

if (options.borderColor && !isColorValid(options.borderColor)) {
throw new Error(`${options.borderColor} is not a valid borderColor`);
}
Expand All @@ -186,6 +222,18 @@ module.exports = (text, options) => {

let contentWidth = widestLine(wrapAnsi(text, columns - BORDERS_WIDTH, {hard: true})) + padding.left + padding.right;

// This prevents the title bar to exceed the console's width
let title = options.title && options.title.slice(0, columns - 4 - margin.left - margin.right);

if (title) {
title = ` ${title} `;
}

// Make the box larger to fit a larger title
if (stringWidth(title) > contentWidth) {
contentWidth = stringWidth(title);
}

if ((margin.left && margin.right) && contentWidth + BORDERS_WIDTH + margin.left + margin.right > columns) {
// Let's assume we have margins: left = 3, right = 5, in total = 8
const spaceForMargins = columns - contentWidth - BORDERS_WIDTH;
Expand All @@ -201,7 +249,7 @@ module.exports = (text, options) => {
// Prevent content from exceeding the console's width
contentWidth = Math.min(contentWidth, columns - BORDERS_WIDTH - margin.left - margin.right);

text = makeContentText(text, padding, contentWidth, options.align);
text = makeContentText(text, padding, contentWidth, options.textAlignement);

let marginLeft = PAD.repeat(margin.left);

Expand All @@ -214,7 +262,7 @@ module.exports = (text, options) => {
}

const horizontal = chars.horizontal.repeat(contentWidth);
const top = colorizeBorder(NL.repeat(margin.top) + marginLeft + chars.topLeft + horizontal + chars.topRight);
const top = colorizeBorder(NL.repeat(margin.top) + marginLeft + chars.topLeft + (title ? makeTitle(title, horizontal, options.titleAlignement) : horizontal) + chars.topRight);
const bottom = colorizeBorder(marginLeft + chars.bottomLeft + horizontal + chars.bottomRight + NL.repeat(margin.bottom));
const side = colorizeBorder(chars.vertical);

Expand Down
4 changes: 3 additions & 1 deletion index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const spacing: Spacing = {
};

expectType<string>(boxen('unicorns'));
expectType<string>(boxen('unicorns', {title: 'title'}));
expectType<string>(boxen('unicorns', {title: 'title', titleAlignement: 'center'}));
expectType<string>(boxen('unicorns', {borderColor: 'green'}));
expectType<string>(boxen('unicorns', {borderColor: '#ff0000'}));
expectType<string>(boxen('unicorns', {borderStyle: 'double'}));
Expand All @@ -31,4 +33,4 @@ expectType<string>(boxen('unicorns', {margin: spacing}));
expectType<string>(boxen('unicorns', {float: 'center'}));
expectType<string>(boxen('unicorns', {backgroundColor: 'green'}));
expectType<string>(boxen('unicorns', {backgroundColor: '#ff0000'}));
expectType<string>(boxen('unicorns', {align: 'right'}));
expectType<string>(boxen('unicorns', {textAlignement: 'right'}));
58 changes: 57 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ console.log(boxen('unicorn', {padding: 1, margin: 1, borderStyle: 'double'}));
╚═════════════╝

*/

console.log(boxen('unicorns love rainbows', {title: 'magical', titleAlignement: 'center'}));
/*
┌────── magical ───────┐
│unicorns love rainbows│
└──────────────────────┘
*/
```

## API
Expand Down Expand Up @@ -127,6 +134,55 @@ Default: `false`

Reduce opacity of the border.

##### title

Type: `string`

Add a title to the box. If needed, the box will horizontally expand to fit the title.

Example:
```js
console.log(boxen('foo bar', {title: 'example'}));
/*
┌ example ┐
│foo bar │
└─────────┘
*/
```

##### titleAlignement

Type: `string`\
Default: `'left'`

Align the title in the top bar.

Values:
- `'left'`
```js
/*
┌ example ──────┐
│foo bar foo bar│
└───────────────┘
*/
```
- `'center'`
```js
/*
┌─── example ───┐
│foo bar foo bar│
└───────────────┘
*/
```
- `'right'`
```js
/*
┌────── example ┐
│foo bar foo bar│
└───────────────┘
*/
```

##### padding

Type: `number | object`\
Expand Down Expand Up @@ -160,7 +216,7 @@ Values: `'black'` `'red'` `'green'` `'yellow'` `'blue'` `'magenta'` `'cyan'` `'w

Color of the background.

##### align
##### textAlignement

Type: `string`\
Default: `'left'`\
Expand Down
Loading