Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: sindresorhus/cli-truncate
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v3.0.0
Choose a base ref
...
head repository: sindresorhus/cli-truncate
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v3.1.0
Choose a head ref
  • 2 commits
  • 5 files changed
  • 2 contributors

Commits on Oct 9, 2021

  1. Add truncationCharacter option (#19)

    Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
    codemaster138 and sindresorhus authored Oct 9, 2021
    Copy the full SHA
    23b40dc View commit details
  2. 3.1.0

    sindresorhus committed Oct 9, 2021
    Copy the full SHA
    ad595f2 View commit details
Showing with 65 additions and 17 deletions.
  1. +20 −0 index.d.ts
  2. +13 −16 index.js
  3. +1 −1 package.json
  4. +20 −0 readme.md
  5. +11 −0 test.js
20 changes: 20 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -50,6 +50,26 @@ export interface Options {
````
*/
readonly preferTruncationOnSpace?: boolean;

/**
The character to use at the breaking point.
@default '…'
@example
```
import cliTruncate from 'cli-truncate';
cliTruncate('unicorns', 5, {position: 'end'});
//=> 'unic…'
cliTruncate('unicorns', 5, {position: 'end', truncationCharacter: '.'});
//=> 'unic.'
cliTruncate('unicorns', 5, {position: 'end', truncationCharacter: ''});
//=> 'unico'
*/
readonly truncationCharacter?: string;
}

/**
29 changes: 13 additions & 16 deletions index.js
Original file line number Diff line number Diff line change
@@ -23,12 +23,12 @@ export default function cliTruncate(text, columns, options) {
options = {
position: 'end',
preferTruncationOnSpace: false,
truncationCharacter: '…',
...options,
};

const {position, space, preferTruncationOnSpace} = options;
let ellipsis = '…';
let ellipsisWidth = 1;
let {truncationCharacter} = options;

if (typeof text !== 'string') {
throw new TypeError(`Expected \`input\` to be a string, got ${typeof text}`);
@@ -43,7 +43,7 @@ export default function cliTruncate(text, columns, options) {
}

if (columns === 1) {
return ellipsis;
return truncationCharacter;
}

const length = stringWidth(text);
@@ -55,50 +55,47 @@ export default function cliTruncate(text, columns, options) {
if (position === 'start') {
if (preferTruncationOnSpace) {
const nearestSpace = getIndexOfNearestSpace(text, length - columns + 1, true);
return ellipsis + sliceAnsi(text, nearestSpace, length).trim();
return truncationCharacter + sliceAnsi(text, nearestSpace, length).trim();
}

if (space === true) {
ellipsis += ' ';
ellipsisWidth = 2;
truncationCharacter += ' ';
}

return ellipsis + sliceAnsi(text, length - columns + ellipsisWidth, length);
return truncationCharacter + sliceAnsi(text, length - columns + stringWidth(truncationCharacter), length);
}

if (position === 'middle') {
if (space === true) {
ellipsis = ` ${ellipsis} `;
ellipsisWidth = 3;
truncationCharacter = ` ${truncationCharacter} `;
}

const half = Math.floor(columns / 2);

if (preferTruncationOnSpace) {
const spaceNearFirstBreakPoint = getIndexOfNearestSpace(text, half);
const spaceNearSecondBreakPoint = getIndexOfNearestSpace(text, length - (columns - half) + 1, true);
return sliceAnsi(text, 0, spaceNearFirstBreakPoint) + ellipsis + sliceAnsi(text, spaceNearSecondBreakPoint, length).trim();
return sliceAnsi(text, 0, spaceNearFirstBreakPoint) + truncationCharacter + sliceAnsi(text, spaceNearSecondBreakPoint, length).trim();
}

return (
sliceAnsi(text, 0, half)
+ ellipsis
+ sliceAnsi(text, length - (columns - half) + ellipsisWidth, length)
+ truncationCharacter
+ sliceAnsi(text, length - (columns - half) + stringWidth(truncationCharacter), length)
);
}

if (position === 'end') {
if (preferTruncationOnSpace) {
const nearestSpace = getIndexOfNearestSpace(text, columns - 1);
return sliceAnsi(text, 0, nearestSpace) + ellipsis;
return sliceAnsi(text, 0, nearestSpace) + truncationCharacter;
}

if (space === true) {
ellipsis = ` ${ellipsis}`;
ellipsisWidth = 2;
truncationCharacter = ` ${truncationCharacter}`;
}

return sliceAnsi(text, 0, columns - ellipsisWidth) + ellipsis;
return sliceAnsi(text, 0, columns - stringWidth(truncationCharacter)) + truncationCharacter;
}

throw new Error(`Expected \`options.position\` to be either \`start\`, \`middle\` or \`end\`, got ${position}`);
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cli-truncate",
"version": "3.0.0",
"version": "3.1.0",
"description": "Truncate a string to a specific width in the terminal",
"license": "MIT",
"repository": "sindresorhus/cli-truncate",
20 changes: 20 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -124,6 +124,26 @@ cliTruncate('unicorns rainbow dragons', 6, {position: 'middle', preferTruncation
//=> 'uni…ns'
```

##### truncationCharacter

Type: `string`\
Default: ``

The character to use at the breaking point.

```js
import cliTruncate from 'cli-truncate';

cliTruncate('unicorns', 5, {position: 'end'});
//=> 'unic…'

cliTruncate('unicorns', 5, {position: 'end', truncationCharacter: '.'});
//=> 'unic.'

cliTruncate('unicorns', 5, {position: 'end', truncationCharacter: ''});
//=> 'unico'
```

## Related

- [wrap-ansi](https://github.com/chalk/wrap-ansi) - Wordwrap a string with ANSI escape codes
11 changes: 11 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
@@ -43,3 +43,14 @@ test('preferTruncationOnSpace option', t => {
t.is(cliTruncate('unicorns rainbow dragons', 6, {position: 'middle', preferTruncationOnSpace: true}), 'uni…ns');
t.is(cliTruncate('unicorns partying with dragons', 20, {position: 'middle', preferTruncationOnSpace: true}), 'unicorns…dragons');
});

test('truncationCharacter option', t => {
t.is(cliTruncate('unicorns', 5, {position: 'end', truncationCharacter: '.'}), 'unic.');
t.is(cliTruncate('unicorns', 5, {position: 'start', truncationCharacter: '.'}), '.orns');
t.is(cliTruncate('unicorns', 5, {position: 'middle', truncationCharacter: '.'}), 'un.ns');
t.is(cliTruncate('unicorns', 5, {position: 'end', truncationCharacter: '.', space: true}), 'uni .');
t.is(cliTruncate('unicorns', 5, {position: 'end', truncationCharacter: ' .'}), 'uni .');
t.is(cliTruncate('unicorns partying with dragons', 20, {position: 'middle', truncationCharacter: '.', preferTruncationOnSpace: true}), 'unicorns.dragons');
t.is(cliTruncate('안녕하세요', 4, {position: 'start', space: true, truncationCharacter: '.'}), '. 요', 'wide char');
t.is(cliTruncate('\u001B[31municornsareawesome\u001B[39m', 10, {position: 'middle', space: true, truncationCharacter: '.'}), '\u001B[31munico\u001B[39m . \u001B[31mme\u001B[39m');
});