Skip to content

Commit

Permalink
feat: add truncate-middle string package
Browse files Browse the repository at this point in the history
  • Loading branch information
steff456 committed Oct 30, 2023
1 parent 6893e6e commit 09e0bfb
Show file tree
Hide file tree
Showing 11 changed files with 699 additions and 119 deletions.
17 changes: 16 additions & 1 deletion lib/node_modules/@stdlib/string/truncate-middle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ limitations under the License.
var truncateMiddle = require( '@stdlib/string/truncate-middle' );
```

#### truncate( str, len\[, seq] )
#### truncate( str, len\[, seq]\[, options] )

Truncates a string in the middle to a specified length.

Expand All @@ -49,6 +49,16 @@ var out = truncateMiddle( 'beep boop', 7 );
// returns 'be...op'
```

The function supports the following options:

- **mode**: type of characters to return. Must be one of the following:

- `'grapheme'`: grapheme clusters. Appropriate for strings containing visual characters which can span multiple Unicode code points (e.g., emoji).
- `'code_point'`: Unicode code points. Appropriate for strings containing visual characters which are comprised of more than one Unicode code unit (e.g., ideographic symbols and punctuation and mathematical alphanumerics).
- `'code_unit'`: UTF-16 code units. Appropriate for strings containing visual characters drawn from the basic multilingual plane (BMP) (e.g., common characters, such as those from the Latin, Greek, and Cyrillic alphabets).

Default: `'grapheme'`.

By default, the truncated string uses the replacement sequence `'...'`. To customize the replacement sequence, provide a `seq` argument:

```javascript
Expand All @@ -67,6 +77,10 @@ out = truncateMiddle( 'beep boop', 7, '!!!' );

<section class="notes">

## Notes

- By default, the function assumes the general case in which an input string may contain an arbitrary number of grapheme clusters. This assumption comes with a performance cost. Accordingly, if an input string is known to only contain visual characters of a particular type (e.g., only alphanumeric), one can achieve better performance by specifying the appropriate `mode` option.

</section>

<!-- /.notes -->
Expand Down Expand Up @@ -131,6 +145,7 @@ Options:
--len length String length.
--seq str Custom replacement sequence. Default: '...'.
--split sep Delimiter for stdin data. Default: '/\\r?\\n/'.
--mode mode Type of character to return. Default: 'grapheme'.
```

</section>
Expand Down
156 changes: 105 additions & 51 deletions lib/node_modules/@stdlib/string/truncate-middle/benchmark/benchmark.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,70 +22,124 @@

var bench = require( '@stdlib/bench' );
var isString = require( '@stdlib/assert/is-string' ).isPrimitive;
var fromCodePoint = require( '@stdlib/string/from-code-point' );
var pkg = require( './../package.json' ).name;
var truncateMiddle = require( './../lib' );


// FUNCTIONS //
// MAIN //

/**
* Creates a benchmark function.
*
* @private
* @param {PositiveInteger} len - string length
* @returns {Function} benchmark function
*/
function createBenchmark( len ) {
return benchmark;

/**
* Benchmark function.
*
* @private
* @param {Benchmark} b - benchmark instance
*/
function benchmark( b ) {
var out;
var i;

b.tic();
for ( i = 0; i < b.iterations; i++ ) {
out = truncateMiddle( fromCodePoint( i%126 )+'eep boop', len );
if ( typeof out !== 'string' ) {
b.fail( 'should return a string' );
}
}
b.toc();
if ( !isString( out ) ) {
bench( pkg, function benchmark( b ) {
var values;
var out;
var i;

values = [
'beep boop',
'foo bar',
'xyz abc'
];

b.tic();
for ( i = 0; i < b.iterations; i++ ) {
out = truncateMiddle( values[ i%values.length ], 6 );
if ( typeof out !== 'string' ) {
b.fail( 'should return a string' );
}
b.pass( 'benchmark finished' );
b.end();
}
}
b.toc();
if ( !isString( out ) ) {
b.fail( 'should return a string' );
}
b.pass( 'benchmark finished' );
b.end();
});

bench( pkg+':mode=grapheme', function benchmark( b ) {
var values;
var opts;
var out;
var i;

// MAIN //
values = [
'beep boop',
'foo bar',
'xyz abc'
];
opts = {
'mode': 'grapheme'
};

/**
* Main execution sequence.
*
* @private
*/
function main() {
var min;
var max;
var f;
b.tic();
for ( i = 0; i < b.iterations; i++ ) {
out = truncateMiddle( values[ i%values.length ], 6, opts );
if ( typeof out !== 'string' ) {
b.fail( 'should return a string' );
}
}
b.toc();
if ( !isString( out ) ) {
b.fail( 'should return a string' );
}
b.pass( 'benchmark finished' );
b.end();
});

bench( pkg+':mode=code_point', function benchmark( b ) {
var values;
var opts;
var out;
var i;

min = 1;
max = 10;
values = [
'beep boop',
'foo bar',
'xyz abc'
];
opts = {
'mode': 'code_point'
};

for ( i = min; i <= max; i++ ) {
f = createBenchmark( i );
bench( pkg+':len='+i, f );
b.tic();
for ( i = 0; i < b.iterations; i++ ) {
out = truncateMiddle( values[ i%values.length ], 6, opts );
if ( typeof out !== 'string' ) {
b.fail( 'should return a string' );
}
}
b.toc();
if ( !isString( out ) ) {
b.fail( 'should return a string' );
}
}
b.pass( 'benchmark finished' );
b.end();
});

main();
bench( pkg+':mode=code_unit', function benchmark( b ) {
var values;
var opts;
var out;
var i;

values = [
'beep boop',
'foo bar',
'xyz abc'
];
opts = {
'mode': 'code_unit'
};

b.tic();
for ( i = 0; i < b.iterations; i++ ) {
out = truncateMiddle( values[ i%values.length ], 6, opts );
if ( typeof out !== 'string' ) {
b.fail( 'should return a string' );
}
}
b.toc();
if ( !isString( out ) ) {
b.fail( 'should return a string' );
}
b.pass( 'benchmark finished' );
b.end();
});
13 changes: 9 additions & 4 deletions lib/node_modules/@stdlib/string/truncate-middle/bin/cli
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ function main() {
var split;
var flags;
var args;
var opts;
var cli;
var len;

Expand All @@ -62,6 +63,10 @@ function main() {
if ( flags.help || flags.version ) {
return;
}
opts = {};
if ( flags.mode ) {
opts.mode = flags.mode;
}

// Get any provided command-line arguments:
args = cli.args();
Expand All @@ -81,9 +86,9 @@ function main() {
return stdin( onRead );
}
if ( flags.seq ) {
console.log( truncateMiddle( args[ 0 ], len, flags.seq ) ); // eslint-disable-line no-console
console.log( truncateMiddle( args[ 0 ], len, flags.seq, opts ) ); // eslint-disable-line no-console
} else {
console.log( truncateMiddle( args[ 0 ], len ) ); // eslint-disable-line no-console
console.log( truncateMiddle( args[ 0 ], len, opts ) ); // eslint-disable-line no-console
}

/**
Expand All @@ -108,11 +113,11 @@ function main() {
}
if ( flags.seq ) {
for ( i = 0; i < lines.length; i++ ) {
console.log( truncateMiddle( lines[ i ], len, flags.seq ) ); // eslint-disable-line no-console
console.log( truncateMiddle( lines[ i ], len, flags.seq, opts ) ); // eslint-disable-line no-console
}
} else {
for ( i = 0; i < lines.length; i++ ) {
console.log( truncateMiddle( lines[ i ], len ) ); // eslint-disable-line no-console
console.log( truncateMiddle( lines[ i ], len, opts ) ); // eslint-disable-line no-console
}
}
}
Expand Down
21 changes: 20 additions & 1 deletion lib/node_modules/@stdlib/string/truncate-middle/docs/repl.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

{{alias}}( str, len[, seq] )
{{alias}}( str, len[, seq][, options] )
Truncates a string in the middle to a specified length.

Parameters
Expand All @@ -13,6 +13,25 @@
seq: string (optional)
Custom replacement sequence. Default: '...'.

options: Object (optional)
Options.

options.mode: string (optional)
Type of characters to return. The following modes are supported:

- grapheme: grapheme clusters. Appropriate for strings containing visual
characters which can span multiple Unicode code points (e.g., emoji).
- code_point: Unicode code points. Appropriate for strings containing
visual characters which are comprised of more than one Unicode code
unit (e.g., ideographic symbols and punctuation and mathematical
alphanumerics).
- code_unit': UTF-16 code units. Appropriate for strings containing
visual characters drawn from the basic multilingual plane (BMP) (e.g.,
common characters, such as those from the Latin, Greek, and Cyrillic
alphabets).

Default: 'grapheme'.

Returns
-------
out: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,75 @@

/// <reference types="@stdlib/types"/>

// tslint:disable:unified-signatures

/**
* Interface describing function options.
*/
interface Options {
/**
* Specifies the type of characters to return (default: 'grapheme').
*
* ## Notes
*
* - The following option values are supported:
*
* - `'grapheme'`: grapheme clusters. Appropriate for strings containing visual characters which can span multiple Unicode code points (e.g., emoji).
* - `'code_point'`: Unicode code points. Appropriate for strings containing visual characters which are comprised of more than one Unicode code unit (e.g., ideographic symbols and punctuation and mathematical alphanumerics).
* - `'code_unit'`: UTF-16 code units. Appropriate for strings containing visual characters drawn from the basic multilingual plane (BMP) (e.g., common characters, such as those from the Latin, Greek, and Cyrillic alphabets).
*/
mode?: 'grapheme' | 'code_point' | 'code_unit';
}

/**
* Truncates a string in the middle to a specified length.
*
* @param str - input string
* @param len - output string length (including sequence)
* @param seq - custom replacement sequence (default: `...`)
* @param options - options
* @returns truncated string
*
* @example
* var str = 'beep boop';
* var out = truncateMiddle( str, 5, '>>>', {
* 'mode': 'code_unit'
* });
* // returns 'b>>>p'
*
* @example
* var str = '🐺 Wolf Brothers 🐺';
* var out = truncateMiddle( str, 6, '..', {
* 'mode': 'grapheme'
* });
* // returns '🐺 .. 🐺'
*/
declare function truncateMiddle( str: string, len: number, seq: string, options?:Options ): string; // tslint-disable-line max-line-length

/**
* Truncates a string in the middle to a specified length.
*
* @param str - input string
* @param len - output string length (including sequence)
* @param options - options
* @returns truncated string
*
* @example
* var str = 'beep boop';
* var out = truncateMiddle( str, 5, {
* 'mode': 'code_unit'
* });
* // returns 'b...p'
*
* @example
* var str = '🐺 Wolf Brothers 🐺';
* var out = truncateMiddle( str, 7, {
* 'mode': 'grapheme'
* });
* // returns '🐺 ... 🐺'
*/
declare function truncateMiddle( str: string, len: number, options?:Options ): string; // tslint-disable-line max-line-length

/**
* Truncates a string in the middle to a specified length.
*
Expand Down
Loading

0 comments on commit 09e0bfb

Please sign in to comment.