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

feat: add truncate-middle string package #1121

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
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
Loading