From 651ebf9dbc07f3f098ef1d00edf83457a9a33db3 Mon Sep 17 00:00:00 2001 From: rajanpanth Date: Sat, 7 Nov 2026 23:02:42 +0545 Subject: [PATCH] fix: insert zero padding after sign and prefix in `string/base/format-interpolate` Co-Authored-By: Claude Opus 5.5 --- .../format-interpolate/lib/format_integer.js | 4 +- .../base/format-interpolate/lib/zero_pad.js | 30 +++----- .../test/test.format_integer.js | 2 +- .../base/format-interpolate/test/test.js | 77 +++++++++++++++++++ .../format-interpolate/test/test.zero_pad.js | 33 ++++++++ 5 files changed, 123 insertions(+), 23 deletions(-) diff --git a/lib/node_modules/@stdlib/string/base/format-interpolate/lib/format_integer.js b/lib/node_modules/@stdlib/string/base/format-interpolate/lib/format_integer.js index f16a61e4ab80..be7e7760c618 100644 --- a/lib/node_modules/@stdlib/string/base/format-interpolate/lib/format_integer.js +++ b/lib/node_modules/@stdlib/string/base/format-interpolate/lib/format_integer.js @@ -79,7 +79,7 @@ function formatInteger( token ) { if ( i < 0 ) { out = ( -i ).toString( base ); if ( token.precision ) { - out = zeroPad( out, token.precision, token.padRight ); + out = zeroPad( out, token.precision, false ); } out = '-' + out; } else { @@ -87,7 +87,7 @@ function formatInteger( token ) { if ( !i && !token.precision ) { out = ''; } else if ( token.precision ) { - out = zeroPad( out, token.precision, token.padRight ); + out = zeroPad( out, token.precision, false ); } if ( token.sign ) { out = token.sign + out; diff --git a/lib/node_modules/@stdlib/string/base/format-interpolate/lib/zero_pad.js b/lib/node_modules/@stdlib/string/base/format-interpolate/lib/zero_pad.js index ba68db2d621e..f3edb230659f 100644 --- a/lib/node_modules/@stdlib/string/base/format-interpolate/lib/zero_pad.js +++ b/lib/node_modules/@stdlib/string/base/format-interpolate/lib/zero_pad.js @@ -18,18 +18,13 @@ 'use strict'; -// FUNCTIONS // +// VARIABLES // -/** -* Tests if a string starts with a minus sign (`-`). -* -* @private -* @param {string} str - input string -* @returns {boolean} boolean indicating if a string starts with a minus sign (`-`) -*/ -function startsWithMinus( str ) { - return str[ 0 ] === '-'; -} +// Sign (`-`, `+`, or ` `) and/or hexadecimal prefix (`0x` or `0X`), which must precede any zeros: +var RE_PREFIX = /^[-+ ]?(?:0[xX])?/; + + +// FUNCTIONS // /** * Returns a string of `n` zeros. @@ -60,22 +55,17 @@ function zeros( n ) { * @returns {string} padded token argument */ function zeroPad( str, width, right ) { - var negative = false; + var prefix; var pad = width - str.length; if ( pad < 0 ) { return str; } - if ( startsWithMinus( str ) ) { - negative = true; - str = str.substr( 1 ); - } + prefix = RE_PREFIX.exec( str )[ 0 ]; + str = str.substring( prefix.length ); str = ( right ) ? str + zeros( pad ) : zeros( pad ) + str; - if ( negative ) { - str = '-' + str; - } - return str; + return prefix + str; } diff --git a/lib/node_modules/@stdlib/string/base/format-interpolate/test/test.format_integer.js b/lib/node_modules/@stdlib/string/base/format-interpolate/test/test.format_integer.js index 9242698bc7ef..391e1ccde20b 100644 --- a/lib/node_modules/@stdlib/string/base/format-interpolate/test/test.format_integer.js +++ b/lib/node_modules/@stdlib/string/base/format-interpolate/test/test.format_integer.js @@ -162,7 +162,7 @@ tape( 'the function returns an integer-formatted token argument (precision)', fu 'precision': 5, 'padRight': true }; - expected = '10000'; + expected = '00010'; actual = formatInteger( token ); t.strictEqual( actual, expected, 'returns expected value' ); diff --git a/lib/node_modules/@stdlib/string/base/format-interpolate/test/test.js b/lib/node_modules/@stdlib/string/base/format-interpolate/test/test.js index 9123cb023180..75c38c2f0baf 100644 --- a/lib/node_modules/@stdlib/string/base/format-interpolate/test/test.js +++ b/lib/node_modules/@stdlib/string/base/format-interpolate/test/test.js @@ -529,6 +529,83 @@ tape( 'the function returns a formatted string (`d` specifier, minimum width, ze t.end(); }); +tape( 'the function returns a formatted string (`d` specifier, minimum width, zero-padded, sign)', function test( t ) { + var expected; + var tokens; + var actual; + + tokens = formatTokenize( '%+05d' ); + actual = formatInterpolate( tokens, 42 ); + expected = '+0042'; + t.strictEqual( actual, expected, 'returns expected output' ); + + tokens = formatTokenize( '% 05d' ); + actual = formatInterpolate( tokens, 42 ); + expected = ' 0042'; + t.strictEqual( actual, expected, 'returns expected output' ); + + tokens = formatTokenize( '%+05d' ); + actual = formatInterpolate( tokens, -42 ); + expected = '-0042'; + t.strictEqual( actual, expected, 'returns expected output' ); + + t.end(); +}); + +tape( 'the function returns a formatted string (`d` specifier, precision, left-justified)', function test( t ) { + var expected; + var tokens; + var actual; + + tokens = formatTokenize( '%-8.3d|' ); + actual = formatInterpolate( tokens, -7 ); + expected = '-007 |'; + t.strictEqual( actual, expected, 'returns expected output' ); + + tokens = formatTokenize( '%-+6.2d|' ); + actual = formatInterpolate( tokens, 5 ); + expected = '+05 |'; + t.strictEqual( actual, expected, 'returns expected output' ); + + t.end(); +}); + +tape( 'the function returns a formatted string (`x` and `X` specifiers, alternate form, minimum width, zero-padded)', function test( t ) { + var expected; + var tokens; + var actual; + + tokens = formatTokenize( '%#08x' ); + actual = formatInterpolate( tokens, 255 ); + expected = '0x0000ff'; + t.strictEqual( actual, expected, 'returns expected output' ); + + tokens = formatTokenize( '%#08X' ); + actual = formatInterpolate( tokens, 255 ); + expected = '0X0000FF'; + t.strictEqual( actual, expected, 'returns expected output' ); + + t.end(); +}); + +tape( 'the function returns a formatted string (`f` specifier, minimum width, zero-padded, sign)', function test( t ) { + var expected; + var tokens; + var actual; + + tokens = formatTokenize( '%+08.3f' ); + actual = formatInterpolate( tokens, 3.14159 ); + expected = '+003.142'; + t.strictEqual( actual, expected, 'returns expected output' ); + + tokens = formatTokenize( '% 08.3f' ); + actual = formatInterpolate( tokens, 3.14159 ); + expected = ' 003.142'; + t.strictEqual( actual, expected, 'returns expected output' ); + + t.end(); +}); + tape( 'the function returns a formatted string (`f` specifier)', function test( t ) { var expected; var tokens; diff --git a/lib/node_modules/@stdlib/string/base/format-interpolate/test/test.zero_pad.js b/lib/node_modules/@stdlib/string/base/format-interpolate/test/test.zero_pad.js index 10bcdf74d158..d9d576fe6805 100644 --- a/lib/node_modules/@stdlib/string/base/format-interpolate/test/test.zero_pad.js +++ b/lib/node_modules/@stdlib/string/base/format-interpolate/test/test.zero_pad.js @@ -67,3 +67,36 @@ tape( 'the function pads an argument with zeros to a minimum width on the right' t.end(); }); + +tape( 'the function inserts zeros after a sign and a hexadecimal prefix', function test( t ) { + var expected; + var actual; + var str; + + str = '+42'; + expected = '+0042'; + actual = zeroPad( str, 5 ); + t.strictEqual( actual, expected, 'pads' ); + + str = ' 42'; + expected = ' 0042'; + actual = zeroPad( str, 5 ); + t.strictEqual( actual, expected, 'pads' ); + + str = '0xff'; + expected = '0x0000ff'; + actual = zeroPad( str, 8 ); + t.strictEqual( actual, expected, 'pads' ); + + str = '0XFF'; + expected = '0X0000FF'; + actual = zeroPad( str, 8 ); + t.strictEqual( actual, expected, 'pads' ); + + str = '+3.142'; + expected = '+003.142'; + actual = zeroPad( str, 8 ); + t.strictEqual( actual, expected, 'pads' ); + + t.end(); +});