pad.js (4824B)
1 /** 2 * @license Apache-2.0 3 * 4 * Copyright (c) 2018 The Stdlib Authors. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 'use strict'; 20 21 // MODULES // 22 23 var isNonNegativeInteger = require( '@stdlib/assert/is-nonnegative-integer' ).isPrimitive; 24 var isString = require( '@stdlib/assert/is-string' ).isPrimitive; 25 var repeat = require( './../../repeat' ); 26 var format = require( './../../format' ); 27 var floor = require( '@stdlib/math/base/special/floor' ); 28 var ceil = require( '@stdlib/math/base/special/ceil' ); 29 var lpad = require( './../../left-pad' ); 30 var rpad = require( './../../right-pad' ); 31 var abs = require( '@stdlib/math/base/special/abs' ); 32 var FLOAT64_MAX_SAFE_INTEGER = require( '@stdlib/constants/float64/max-safe-integer' ); 33 var validate = require( './validate.js' ); 34 35 36 // MAIN // 37 38 /** 39 * Pads a string such that the padded string has a length of `len`. 40 * 41 * @param {string} str - string to pad 42 * @param {NonNegativeInteger} len - string length 43 * @param {Options} [options] - function options 44 * @param {string} [options.lpad=''] - string used to left pad 45 * @param {string} [options.rpad=' '] - string used to right pad 46 * @param {boolean} [options.centerRight=false] - boolean indicating whether to center right in the event of a tie 47 * @throws {TypeError} first argument must be a string 48 * @throws {TypeError} second argument must be a nonnegative integer 49 * @throws {TypeError} options argument must be an object 50 * @throws {TypeError} must provide valid options 51 * @throws {RangeError} at least one padding must have a length greater than `0` 52 * @returns {string} padded string 53 * 54 * @example 55 * var str = pad( 'a', 5 ); 56 * // returns 'a ' 57 * 58 * @example 59 * var str = pad( 'a', 10, { 60 * 'lpad': 'b' 61 * }); 62 * // returns 'bbbbbbbbba' 63 * 64 * @example 65 * var str = pad( 'a', 12, { 66 * 'rpad': 'b' 67 * }); 68 * // returns 'abbbbbbbbbbb' 69 * 70 * @example 71 * var opts = { 72 * 'lpad': 'a', 73 * 'rpad': 'c' 74 * }; 75 * var str = pad( 'b', 10, opts ); 76 * // returns 'aaaabccccc' 77 * 78 * @example 79 * var opts = { 80 * 'lpad': 'a', 81 * 'rpad': 'c', 82 * 'centerRight': true 83 * }; 84 * var str = pad( 'b', 10, opts ); 85 * // returns 'aaaaabcccc' 86 */ 87 function pad( str, len, options ) { 88 var nright; 89 var nleft; 90 var isodd; 91 var right; 92 var left; 93 var opts; 94 var err; 95 var tmp; 96 var n; 97 if ( !isString( str ) ) { 98 throw new TypeError( format( 'invalid argument. First argument must be a string. Value: `%s`.', str ) ); 99 } 100 if ( !isNonNegativeInteger( len ) ) { 101 throw new TypeError( format( 'invalid argument. Second argument must be a nonnegative integer. Value: `%s`.', len ) ); 102 } 103 if ( len > FLOAT64_MAX_SAFE_INTEGER ) { 104 throw new RangeError( format( 'invalid argument. Output string length exceeds maximum allowed string length. Value: `%u`.', len ) ); 105 } 106 opts = {}; 107 if ( arguments.length > 2 ) { 108 err = validate( opts, options ); 109 if ( err ) { 110 throw err; 111 } 112 } 113 if ( opts.lpad && opts.rpad ) { 114 n = ( len-str.length ) / 2; 115 if ( n === 0 ) { 116 return str; 117 } 118 tmp = floor( n ); 119 if ( tmp !== n ) { 120 isodd = true; 121 } 122 if ( n < 0 ) { 123 n = floor( abs( n ) ); 124 nleft = n; 125 nright = str.length - n; 126 127 // If |len-str.length| is an odd number, take away an additional character from one side... 128 if ( isodd ) { 129 if ( opts.centerRight ) { 130 nright -= 1; 131 } else { 132 nleft += 1; 133 } 134 } 135 return str.substring( nleft, nright ); 136 } 137 nleft = ceil( n / opts.lpad.length ); 138 left = repeat( opts.lpad, nleft ); 139 140 nright = ceil( n / opts.rpad.length ); 141 right = repeat( opts.rpad, nright ); 142 143 // If (len-str.length) is an odd number, give one side one extra character... 144 n = tmp; 145 nleft = n; 146 nright = n; 147 if ( isodd ) { 148 if ( opts.centerRight ) { 149 nleft += 1; 150 } else { 151 nright += 1; 152 } 153 } 154 left = left.substring( 0, nleft ); 155 right = right.substring( 0, nright ); 156 return left + str + right; 157 } 158 if ( opts.lpad ) { 159 tmp = lpad( str, len, opts.lpad ); 160 return tmp.substring( tmp.length-len ); 161 } 162 if ( opts.rpad ) { 163 return ( rpad( str, len, opts.rpad ) ).substring( 0, len ); 164 } 165 if ( opts.rpad === void 0 ) { 166 return ( rpad( str, len, ' ' ) ).substring( 0, len ); 167 } 168 throw new RangeError( format( 'invalid argument. At least one padding option must have a length greater than 0. Left padding: `%s`. Right padding: `%s`.', opts.lpad, opts.rpad ) ); 169 } 170 171 172 // EXPORTS // 173 174 module.exports = pad;