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

Completes implementation of borderStyle "none" #89

Merged
merged 3 commits into from
Jul 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
56 changes: 38 additions & 18 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import wrapAnsi from 'wrap-ansi';

const NEWLINE = '\n';
const PAD = ' ';
const BORDERS_WIDTH = 2;
const NONE = 'none';

const terminalColumns = () => {
const {env, stdout, stderr} = process;
Expand Down Expand Up @@ -42,6 +42,8 @@ const getObject = detail => typeof detail === 'number' ? {
...detail,
};

const getBorderWidth = borderStyle => borderStyle === NONE ? 0 : 2;

const getBorderChars = borderStyle => {
const sides = [
'topLeft',
Expand All @@ -57,7 +59,7 @@ const getBorderChars = borderStyle => {
let characters;

// Create empty border style
if (borderStyle === 'none') {
if (borderStyle === NONE) {
borderStyle = {};
for (const side of sides) {
borderStyle[side] = '';
Expand Down Expand Up @@ -95,12 +97,12 @@ const getBorderChars = borderStyle => {
return characters;
};

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

const textWidth = stringWidth(text);

switch (alignement) {
switch (alignment) {
case 'left': {
title = text + horizontal.slice(textWidth);
break;
Expand Down Expand Up @@ -231,21 +233,36 @@ const boxContent = (content, contentWidth, options) => {
let marginLeft = PAD.repeat(options.margin.left);

if (options.float === 'center') {
const marginWidth = Math.max((columns - contentWidth - BORDERS_WIDTH) / 2, 0);
const marginWidth = Math.max((columns - contentWidth - getBorderWidth(options.borderStyle)) / 2, 0);
marginLeft = PAD.repeat(marginWidth);
} else if (options.float === 'right') {
const marginWidth = Math.max(columns - contentWidth - options.margin.right - BORDERS_WIDTH, 0);
const marginWidth = Math.max(columns - contentWidth - options.margin.right - getBorderWidth(options.borderStyle), 0);
marginLeft = PAD.repeat(marginWidth);
}

const top = colorizeBorder(NEWLINE.repeat(options.margin.top) + marginLeft + chars.topLeft + (options.title ? makeTitle(options.title, chars.top.repeat(contentWidth), options.titleAlignment) : chars.top.repeat(contentWidth)) + chars.topRight);
const bottom = colorizeBorder(marginLeft + chars.bottomLeft + chars.bottom.repeat(contentWidth) + chars.bottomRight + NEWLINE.repeat(options.margin.bottom));
let result = '';

if (options.margin.top) {
result += NEWLINE.repeat(options.margin.top);
}

if (options.borderStyle !== NONE || options.title) {
result += colorizeBorder(marginLeft + chars.topLeft + (options.title ? makeTitle(options.title, chars.top.repeat(contentWidth), options.titleAlignment) : chars.top.repeat(contentWidth)) + chars.topRight) + NEWLINE;
}

const lines = content.split(NEWLINE);

const middle = lines.map(line => marginLeft + colorizeBorder(chars.left) + colorizeContent(line) + colorizeBorder(chars.right)).join(NEWLINE);
result += lines.map(line => marginLeft + colorizeBorder(chars.left) + colorizeContent(line) + colorizeBorder(chars.right)).join(NEWLINE);

return top + NEWLINE + middle + NEWLINE + bottom;
if (options.borderStyle !== NONE) {
result += NEWLINE + colorizeBorder(marginLeft + chars.bottomLeft + chars.bottom.repeat(contentWidth) + chars.bottomRight);
}

if (options.margin.bottom) {
result += NEWLINE.repeat(options.margin.bottom);
}

return result;
};

const sanitizeOptions = options => {
Expand All @@ -268,37 +285,40 @@ const sanitizeOptions = options => {

// If width is provided, make sure it's not below 1
if (options.width) {
options.width = Math.max(1, options.width - BORDERS_WIDTH);
options.width = Math.max(1, options.width - getBorderWidth(options.borderStyle));
}

// If height is provided, make sure it's not below 1
if (options.height) {
options.height = Math.max(1, options.height - BORDERS_WIDTH);
options.height = Math.max(1, options.height - getBorderWidth(options.borderStyle));
}

return options;
};

const formatTitle = (title, borderStyle) => borderStyle === NONE ? title : ` ${title} `;

const determineDimensions = (text, options) => {
options = sanitizeOptions(options);
const widthOverride = options.width !== undefined;
const columns = terminalColumns();
const maxWidth = columns - options.margin.left - options.margin.right - BORDERS_WIDTH;
const borderWidth = getBorderWidth(options.borderStyle);
const maxWidth = columns - options.margin.left - options.margin.right - borderWidth;

const widest = widestLine(wrapAnsi(text, columns - BORDERS_WIDTH, {hard: true, trim: false})) + options.padding.left + options.padding.right;
const widest = widestLine(wrapAnsi(text, columns - borderWidth, {hard: true, trim: false})) + options.padding.left + options.padding.right;

// If title and width are provided, title adheres to fixed width
if (options.title && widthOverride) {
options.title = options.title.slice(0, Math.max(0, options.width - 2));
if (options.title) {
options.title = ` ${options.title} `;
options.title = formatTitle(options.title, options.borderStyle);
}
} else if (options.title) {
options.title = options.title.slice(0, Math.max(0, maxWidth - 2));

// Recheck if title isn't empty now
if (options.title) {
options.title = ` ${options.title} `;
options.title = formatTitle(options.title, options.borderStyle);
// If the title is larger than content, box adheres to title width
if (stringWidth(options.title) > widest) {
options.width = stringWidth(options.title);
Expand All @@ -312,7 +332,7 @@ const determineDimensions = (text, options) => {
if (!widthOverride) {
if ((options.margin.left && options.margin.right) && options.width > maxWidth) {
// Let's assume we have margins: left = 3, right = 5, in total = 8
const spaceForMargins = columns - options.width - BORDERS_WIDTH;
const spaceForMargins = columns - options.width - borderWidth;
// Let's assume we have space = 4
const multiplier = spaceForMargins / (options.margin.left + options.margin.right);
// Here: multiplier = 4/8 = 0.5
Expand All @@ -323,7 +343,7 @@ const determineDimensions = (text, options) => {
}

// Re-cap width considering the margins after shrinking
options.width = Math.min(options.width, columns - BORDERS_WIDTH - options.margin.left - options.margin.right);
options.width = Math.min(options.width, columns - borderWidth - options.margin.left - options.margin.right);
}

// Prevent padding overflow
Expand Down
2 changes: 0 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,7 @@ Values:
```
- `'none'`
```

foo

```

Style of the box border.
Expand Down
9 changes: 9 additions & 0 deletions tests/height-option.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,12 @@ test('height option with width + padding + margin', t => {

t.snapshot(box);
});

test('height option with border style (none)', t => {
const box = boxen('foo', {
height: 3,
borderStyle: 'none',
});

t.snapshot(box);
});
14 changes: 14 additions & 0 deletions tests/margin-option.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,17 @@ test('margin proportionally decreases when content <= columns', t => {

t.snapshot(box);
});

test('margin option with border style (none)', t => {
const box = boxen('foo', {
margin: {
top: 1,
bottom: 1,
left: 1,
right: 1,
},
borderStyle: 'none',
});

t.snapshot(box);
});
14 changes: 14 additions & 0 deletions tests/padding-option.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,17 @@ test('padding option advanced', t => {

t.snapshot(box);
});

test('padding option with border style (none)', t => {
const box = boxen('foo', {
padding: {
top: 1,
bottom: 1,
left: 1,
right: 1,
},
borderStyle: 'none',
});

t.snapshot(box);
});
4 changes: 1 addition & 3 deletions tests/snapshots/tests/border-option.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,7 @@ Generated by [AVA](https://avajs.dev).

> Snapshot 1

`␊
foo␊
`
'foo'

## border style (custom ascii style)

Expand Down
Binary file modified tests/snapshots/tests/border-option.js.snap
Binary file not shown.
8 changes: 8 additions & 0 deletions tests/snapshots/tests/height-option.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,11 @@ Generated by [AVA](https://avajs.dev).
└──────────────────┘␊
`

## height option with border style (none)

> Snapshot 1

`foo␊
`
Binary file modified tests/snapshots/tests/height-option.js.snap
Binary file not shown.
8 changes: 8 additions & 0 deletions tests/snapshots/tests/margin-option.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,11 @@ Generated by [AVA](https://avajs.dev).
└──────────────────────────────────────────────────────────┘␊
`

## margin option with border style (none)

> Snapshot 1

`␊
foo␊
`
Binary file modified tests/snapshots/tests/margin-option.js.snap
Binary file not shown.
8 changes: 8 additions & 0 deletions tests/snapshots/tests/padding-option.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,11 @@ Generated by [AVA](https://avajs.dev).
│ │␊
│ │␊
└──────────────────┘`

## padding option with border style (none)

> Snapshot 1

` ␊
foo ␊
`
Binary file modified tests/snapshots/tests/padding-option.js.snap
Binary file not shown.
7 changes: 7 additions & 0 deletions tests/snapshots/tests/title-option.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,10 @@ Generated by [AVA](https://avajs.dev).
`┌ very long title ─┐␊
│foo │␊
└──────────────────┘`

## title option with border style (none)

> Snapshot 1

`title␊
foo `
Binary file modified tests/snapshots/tests/title-option.js.snap
Binary file not shown.
6 changes: 6 additions & 0 deletions tests/snapshots/tests/width-option.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,9 @@ Generated by [AVA](https://avajs.dev).
│ │␊
│ │␊
└────┘`

## width option with border style (none)

> Snapshot 1

'foo'
Binary file modified tests/snapshots/tests/width-option.js.snap
Binary file not shown.
9 changes: 9 additions & 0 deletions tests/title-option.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,12 @@ test('title + width option', t => {
}),
);
});

test('title option with border style (none)', t => {
const box = boxen('foo', {
title: 'title',
borderStyle: 'none',
});

t.snapshot(box);
});
9 changes: 9 additions & 0 deletions tests/width-option.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,12 @@ test('width option with big padding', t => {

t.snapshot(box);
});

test('width option with border style (none)', t => {
const box = boxen('foo', {
width: 3,
borderStyle: 'none',
});

t.snapshot(box);
});