Skip to content

Commit

Permalink
Require Node.js 12.20 and add an option to count ANSI escape codes (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
Richienb committed Jun 5, 2021
1 parent 0656975 commit e681f7d
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 25 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ jobs:
fail-fast: false
matrix:
node-version:
- 16
- 14
- 12
- 10
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- run: npm install
Expand Down
15 changes: 11 additions & 4 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
export interface Options {
/**
Whether [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) should be counted. They are ignored by default.
@default false
*/
readonly countAnsiEscapeCodes?: boolean;
}

/**
Get the real length of a string - by correctly counting astral symbols and ignoring [ansi escape codes](https://github.com/sindresorhus/strip-ansi).
`String#length` erroneously counts [astral symbols](https://web.archive.org/web/20150721114550/http://www.tlg.uci.edu/~opoudjis/unicode/unicode_astral.html) as two characters.
@example
```
import stringLength = require('string-length');
import stringLength from 'string-length';
'🐴'.length;
//=> 2
Expand All @@ -17,6 +26,4 @@ stringLength('\u001B[1municorn\u001B[22m');
//=> 7
```
*/
declare function stringLength(string: string): number;

export = stringLength;
export default function stringLength(string: string, options?: Options): number;
19 changes: 9 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
'use strict';
const stripAnsi = require('strip-ansi');
const charRegex = require('char-regex');
import stripAnsi from 'strip-ansi';
import charRegex from 'char-regex';

const stringLength = string => {
export default function stringLength(string, {countAnsiEscapeCodes = false} = {}) {
if (string === '') {
return 0;
}

const strippedString = stripAnsi(string);
if (!countAnsiEscapeCodes) {
string = stripAnsi(string);
}

if (strippedString === '') {
if (string === '') {
return 0;
}

return strippedString.match(charRegex()).length;
};

module.exports = stringLength;
return string.match(charRegex()).length;
}
3 changes: 2 additions & 1 deletion index.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {expectType} from 'tsd';
import stringLength = require('.');
import stringLength from './index.js';

expectType<number>(stringLength('🐴'));
expectType<number>(stringLength('\u001B[1municorn\u001B[22m'));
expectType<number>(stringLength('\u001B[1municorn\u001B[22m', {countAnsiEscapeCodes: true}));
12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
"url": "https://sindresorhus.com"
},
"engines": {
"node": ">=10"
"node": ">=12.20"
},
"type": "module",
"exports": "./index.js",
"scripts": {
"test": "xo && ava && tsd"
},
Expand All @@ -34,12 +36,12 @@
"codes"
],
"dependencies": {
"char-regex": "^1.0.2",
"char-regex": "^2.0.0",
"strip-ansi": "^6.0.0"
},
"devDependencies": {
"ava": "^3.1.0",
"tsd": "^0.11.0",
"xo": "^0.25.3"
"ava": "^3.15.0",
"tsd": "^0.17.0",
"xo": "^0.40.2"
}
}
17 changes: 16 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ $ npm install string-length
## Usage

```js
const stringLength = require('string-length');
import stringLength from 'string-length';

'🐴'.length;
//=> 2
Expand All @@ -25,6 +25,21 @@ stringLength('\u001B[1municorn\u001B[22m');
//=> 7
```

## API

### stringLength(string, options?)

#### options

Type: `object`

##### countAnsiEscapeCodes

Type: `boolean`\
Default: `false`

Whether [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) should be counted. They are ignored by default.

## Related

- [string-length-cli](https://github.com/LitoMore/string-length-cli) - CLI for this module
Expand Down
7 changes: 5 additions & 2 deletions test.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
const test = require('ava');
const stringLength = require('.');
import test from 'ava';
import stringLength from './index.js';

test('get the real length of a string', t => {
t.is(stringLength(''), 0);
t.is(stringLength('\u001B[1m\u001B[22m'), 0);
t.is(stringLength('\u001B[1m\u001B[22m', {countAnsiEscapeCodes: true}), 9);
t.is(stringLength('𠀔'), 1);
t.is(stringLength('foo𠁐bar𠀃'), 8);
t.is(stringLength('あ'), 1);
t.is(stringLength('谢'), 1);
t.is(stringLength('🐴'), 1);
t.is(stringLength('𝌆'), 1);
t.is(stringLength('\u001B[1mfoo\u001B[22m'), 3);
t.is(stringLength('\u001B[1mfoo\u001B[22m', {countAnsiEscapeCodes: true}), 12);
t.is(stringLength('❤️'), 1);
t.is(stringLength('👊🏽'), 1);
t.is(stringLength('🏴󠁧󠁢󠁥󠁮󠁧󠁿❤️谢👪'), 4);
t.is(stringLength('\u001B[1m👩‍👧‍👦°✿\u001B[22m'), 3);
t.is(stringLength('\u001B[1m👩‍👧‍👦°✿\u001B[22m', {countAnsiEscapeCodes: true}), 12);
});

0 comments on commit e681f7d

Please sign in to comment.